fix: auto-detect BIOS boot type + simplified reuse form
1. BIOS: provisioner now calls detect_efi() on the first disk when auto_detect_boot=true. Detects EFI partition via guestfish. Falls back to user's boot_type if detection inconclusive. 2. Reuse: 'Create Another VM' now shows an inline form asking only for VM Name and ID, reusing the same disk image, format, and boot settings from the completed job. No redirect needed.
This commit is contained in:
parent
80c5e2ceda
commit
7e1303a217
3 changed files with 90 additions and 4 deletions
|
|
@ -23,8 +23,9 @@ from models import (
|
|||
JobStatusResponse,
|
||||
JobStatus,
|
||||
DiskType,
|
||||
BootType,
|
||||
)
|
||||
from converter import extract_if_needed, discover_disk
|
||||
from converter import extract_if_needed, discover_disk, detect_efi
|
||||
|
||||
logger = logging.getLogger("backend.provisioner")
|
||||
|
||||
|
|
@ -275,7 +276,21 @@ def _process_job(job_id: str, req: JobSubmissionRequest):
|
|||
if not safe_name:
|
||||
safe_name = f"vm-{vmid}"
|
||||
|
||||
bios = "ovmf" if req.boot_type.value == "uefi" else "seabios"
|
||||
# ── Auto-detect boot type if requested ─────────────────────
|
||||
final_boot = req.boot_type
|
||||
if req.auto_detect_boot and disk_paths:
|
||||
logger.info("Auto-detecting boot type...")
|
||||
efi = detect_efi(disk_paths[0])
|
||||
if efi is True:
|
||||
final_boot = BootType.UEFI
|
||||
logger.info(" EFI partition detected → UEFI (OVMF)")
|
||||
elif efi is False:
|
||||
final_boot = BootType.LEGACY
|
||||
logger.info(" No EFI partition → Legacy BIOS (SeaBIOS)")
|
||||
else:
|
||||
logger.info(" EFI detection inconclusive — using %s", final_boot.value)
|
||||
|
||||
bios = "ovmf" if final_boot.value == "uefi" else "seabios"
|
||||
_run(["qm", "create", str(vmid),
|
||||
"--name", safe_name,
|
||||
"--bios", bios,
|
||||
|
|
@ -310,7 +325,7 @@ def _process_job(job_id: str, req: JobSubmissionRequest):
|
|||
message=f"Imported disk {idx + 1}/{len(disk_paths)}")
|
||||
|
||||
# ── Add EFI disk if UEFI ──────────────────────────────────
|
||||
if req.boot_type.value == "uefi":
|
||||
if final_boot.value == "uefi":
|
||||
logger.info("Adding EFI disk")
|
||||
_run(["qm", "set", str(vmid), "--efidisk0",
|
||||
f"{req.target_storage}:0,format=raw,size=4M"])
|
||||
|
|
|
|||
|
|
@ -295,7 +295,9 @@ function initPolling() {
|
|||
let completed = false;
|
||||
|
||||
// Reuse buttons
|
||||
document.getElementById('btn-reuse-yes').onclick = () => reuseImage(jobId, vmid, sourceFilename, true);
|
||||
document.getElementById('btn-reuse-yes').onclick = () => {
|
||||
document.getElementById('reuse-form-wrap').classList.remove('hidden');
|
||||
};
|
||||
document.getElementById('btn-reuse-no').onclick = () => reuseImage(jobId, vmid, sourceFilename, false);
|
||||
|
||||
async function poll() {
|
||||
|
|
@ -363,6 +365,52 @@ async function reuseImage(jobId, vmid, sourceFilename, keep) {
|
|||
}
|
||||
} catch (err) { alert('Cleanup failed: ' + err.message); }
|
||||
}
|
||||
|
||||
async function submitReuse(e) {
|
||||
e.preventDefault();
|
||||
const newVmid = document.getElementById('reuse-vmid').value;
|
||||
const newVmName = document.getElementById('reuse-vmname').value.trim();
|
||||
const status = document.getElementById('reuse-submit-status');
|
||||
status.classList.remove('hidden');
|
||||
status.innerHTML = '<div class="spinner"></div> Submitting job...';
|
||||
|
||||
// Get original job data from the container
|
||||
const container = document.getElementById('polling-container');
|
||||
const sourceFilename = container.dataset.sourceFilename;
|
||||
const jobId = container.dataset.jobId;
|
||||
|
||||
// Get the analysis data from the completed job's backend
|
||||
let analysis;
|
||||
try {
|
||||
const resp = await fetch('/session/status/' + jobId);
|
||||
analysis = await resp.json();
|
||||
} catch (err) {
|
||||
status.innerHTML = '<div class="error">Failed to fetch job data.</div>';
|
||||
return;
|
||||
}
|
||||
|
||||
// Build payload using same disk settings as first VM
|
||||
const payload = new FormData();
|
||||
payload.append('vmid', newVmid);
|
||||
payload.append('vm_name', newVmName);
|
||||
payload.append('source_filename', sourceFilename);
|
||||
// Re-use disk format from original job or default
|
||||
payload.append('disk_format', 'vmdk');
|
||||
payload.append('cpu_cores', '2');
|
||||
payload.append('ram_mb', '4096');
|
||||
payload.append('target_storage', 'local-lvm');
|
||||
payload.append('auto_detect_boot', 'true');
|
||||
payload.append('boot_type', 'uefi');
|
||||
|
||||
try {
|
||||
const resp = await fetch('/session/confirm', { method: 'POST', body: payload });
|
||||
const html = await resp.text();
|
||||
document.getElementById('polling-section').innerHTML = html;
|
||||
initPolling();
|
||||
} catch (err) {
|
||||
status.innerHTML = '<div class="error">Failed: ' + err.message + '</div>';
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
{% endblock %}
|
||||
|
|
|
|||
|
|
@ -19,6 +19,7 @@
|
|||
<div id="error-block" class="error hidden"></div>
|
||||
</div>
|
||||
|
||||
<!-- Reuse: ask whether to create another VM -->
|
||||
<div id="reuse-section" class="panel hidden">
|
||||
<h2>Conversion Complete</h2>
|
||||
<p>Use the same source image to create another VM?</p>
|
||||
|
|
@ -26,5 +27,27 @@
|
|||
<button id="btn-reuse-yes" class="btn">Yes — Create Another VM</button>
|
||||
<button id="btn-reuse-no" class="btn btn-secondary">No — Clean Up & Finish</button>
|
||||
</div>
|
||||
<div id="reuse-form-wrap" class="hidden" style="margin-top:1rem;">
|
||||
<hr style="border-color:var(--border); margin-bottom:1rem;">
|
||||
<form id="reuse-form" onsubmit="submitReuse(event)">
|
||||
<div class="row">
|
||||
<div class="form-group">
|
||||
<label>VM Name *</label>
|
||||
<input type="text" id="reuse-vmname" name="vm_name" required
|
||||
placeholder="e.g. second-vm">
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label>VM ID *</label>
|
||||
<input type="number" id="reuse-vmid" name="vmid" required
|
||||
min="21000" max="21100" placeholder="21051">
|
||||
</div>
|
||||
</div>
|
||||
<p class="dim" style="font-size:0.8rem;">
|
||||
Same disk image, format, and boot settings as the first VM.
|
||||
</p>
|
||||
<button type="submit" class="btn" style="margin-top:0.5rem;">Start Conversion</button>
|
||||
</form>
|
||||
<div id="reuse-submit-status" class="hidden" style="margin-top:1rem;"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
Loading…
Reference in a new issue