Показать второй прогресс конвертации после загрузки образа
Этот коммит содержится в:
@@ -51,7 +51,7 @@
|
||||
</div>
|
||||
<button id="disk-upload-button" type="submit" class="primary wide">Загрузить образ диска</button>
|
||||
</form>
|
||||
<p class="muted small-note">Файл попадёт в <b>/var/lib/virtuality/disk-images</b>. При создании VM образ будет скопирован/сконвертирован в отдельный <b>qcow2</b>-диск VM.</p>
|
||||
<p class="muted small-note">После загрузки .img/.raw прогресс начнётся заново и покажет конвертацию в qcow2. Уже готовый .qcow2 сохраняется без конвертации.</p>
|
||||
</article>
|
||||
|
||||
<article class="card">
|
||||
@@ -62,15 +62,14 @@
|
||||
<div class="quick-actions">
|
||||
<div class="big-action static">
|
||||
<strong>Raspberry / Orange Pi images</strong>
|
||||
<span>Загрузи .img, затем в “Создать VM” выбери режим “Готовый диск”.</span>
|
||||
<span>Загрузи .img, дождись конвертации, затем в “Создать VM” выбери режим “Готовый диск”.</span>
|
||||
</div>
|
||||
<div class="big-action static">
|
||||
<strong>Оригинал не трогаем</strong>
|
||||
<span>Virtuality делает отдельный диск VM, чтобы загруженный образ оставался шаблоном.</span>
|
||||
<span>Virtuality сохраняет исходник и создаёт рядом готовый qcow2-шаблон.</span>
|
||||
</div>
|
||||
</div>
|
||||
<pre>qemu-img convert -O qcow2 source.img VM.qcow2
|
||||
virt-install --import --disk path=VM.qcow2</pre>
|
||||
<pre>qemu-img convert -p -f raw -O qcow2 source.img source.qcow2</pre>
|
||||
</article>
|
||||
</section>
|
||||
|
||||
@@ -126,6 +125,44 @@ virt-install --import --disk path=VM.qcow2</pre>
|
||||
return value.toFixed(value >= 10 || i === 0 ? 0 : 1) + ' ' + units[i];
|
||||
}
|
||||
|
||||
function resetProgress(title, detail) {
|
||||
bar.style.width = '0%';
|
||||
percent.textContent = '0%';
|
||||
statusLine.textContent = title;
|
||||
loadedLine.textContent = detail || '0%';
|
||||
speedLine.textContent = 'ожидание…';
|
||||
}
|
||||
|
||||
async function pollConvert(operationId) {
|
||||
resetProgress('Конвертация образа в qcow2…', '0%');
|
||||
while (true) {
|
||||
const response = await fetch('/api/operations/' + operationId, {cache: 'no-store'});
|
||||
const payload = await response.json();
|
||||
if (!payload.ok) throw new Error(payload.error || 'operation error');
|
||||
const op = payload.operation;
|
||||
const progress = Math.max(0, Math.min(100, Number(op.progress || 0)));
|
||||
bar.style.width = progress + '%';
|
||||
percent.textContent = progress + '%';
|
||||
loadedLine.textContent = 'Конвертация: ' + progress + '%';
|
||||
speedLine.textContent = op.status;
|
||||
statusLine.textContent = op.message || 'Конвертация образа…';
|
||||
if (op.status === 'success') {
|
||||
bar.style.width = '100%';
|
||||
percent.textContent = '100%';
|
||||
statusLine.textContent = 'Конвертация завершена. Обновляем список образов…';
|
||||
setTimeout(() => { window.location.href = '/disk-images'; }, 650);
|
||||
return;
|
||||
}
|
||||
if (op.status === 'error') {
|
||||
statusLine.textContent = 'Ошибка конвертации: ' + (op.message || 'см. журнал операций');
|
||||
button.disabled = false;
|
||||
fileInput.disabled = false;
|
||||
return;
|
||||
}
|
||||
await new Promise(resolve => setTimeout(resolve, 1000));
|
||||
}
|
||||
}
|
||||
|
||||
fileInput.addEventListener('change', function () {
|
||||
const file = fileInput.files[0];
|
||||
hint.textContent = file ? file.name + ' · ' + bytesText(file.size) : 'Файл ещё не выбран.';
|
||||
@@ -143,11 +180,7 @@ virt-install --import --disk path=VM.qcow2</pre>
|
||||
box.hidden = false;
|
||||
button.disabled = true;
|
||||
fileInput.disabled = true;
|
||||
statusLine.textContent = 'Передача образа на сервер…';
|
||||
bar.style.width = '0%';
|
||||
percent.textContent = '0%';
|
||||
loadedLine.textContent = '0 MB из ' + bytesText(file.size);
|
||||
speedLine.textContent = 'скорость считается…';
|
||||
resetProgress('Передача образа на сервер…', '0 MB из ' + bytesText(file.size));
|
||||
|
||||
xhr.upload.onprogress = function (event) {
|
||||
if (!event.lengthComputable) {
|
||||
@@ -164,8 +197,14 @@ virt-install --import --disk path=VM.qcow2</pre>
|
||||
if (pct >= 100) statusLine.textContent = 'Файл передан. Сервер сохраняет образ…';
|
||||
};
|
||||
|
||||
xhr.onload = function () {
|
||||
xhr.onload = async function () {
|
||||
if (xhr.status >= 200 && xhr.status < 400) {
|
||||
let payload = null;
|
||||
try { payload = JSON.parse(xhr.responseText); } catch (error) {}
|
||||
if (payload && payload.mode === 'converting' && payload.operation_id) {
|
||||
await pollConvert(payload.operation_id);
|
||||
return;
|
||||
}
|
||||
bar.style.width = '100%';
|
||||
percent.textContent = '100%';
|
||||
statusLine.textContent = 'Готово. Обновляем список образов…';
|
||||
@@ -184,6 +223,8 @@ virt-install --import --disk path=VM.qcow2</pre>
|
||||
};
|
||||
|
||||
xhr.open('POST', form.action);
|
||||
xhr.setRequestHeader('Accept', 'application/json');
|
||||
xhr.setRequestHeader('X-Requested-With', 'XMLHttpRequest');
|
||||
xhr.send(data);
|
||||
});
|
||||
</script>
|
||||
|
||||
Ссылка в новой задаче
Block a user