diff --git a/backend/provisioner.py b/backend/provisioner.py index a25ad9f..f413308 100644 --- a/backend/provisioner.py +++ b/backend/provisioner.py @@ -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"]) diff --git a/frontend/templates/index.html b/frontend/templates/index.html index b90ee5f..485177e 100644 --- a/frontend/templates/index.html +++ b/frontend/templates/index.html @@ -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 = '
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 = '
Failed to fetch job data.
'; + 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 = '
Failed: ' + err.message + '
'; + } +} {% endblock %} diff --git a/frontend/templates/polling.html b/frontend/templates/polling.html index 12bc210..a1f05e6 100644 --- a/frontend/templates/polling.html +++ b/frontend/templates/polling.html @@ -19,6 +19,7 @@ + +