vm-bench/backend/provisioner.py

116 lines
3.4 KiB
Python

"""
VM provisioning on the Proxmox host.
This module is a stub — the real Proxmox integration (qm create, qm importdisk,
qm set) runs on the backend host (srv2). Fill in the actual Proxmox commands
when you deploy the backend to the host.
"""
from __future__ import annotations
import subprocess
import uuid
import time
from pathlib import Path
from typing import Optional
from models import (
JobSubmissionRequest,
JobStatusResponse,
JobStatus,
)
STAGING_OUT = Path("/mnt/converter/out")
def submit_job(req: JobSubmissionRequest) -> JobStatusResponse:
"""Submit a conversion + provisioning job. Returns initial status."""
job_id = f"job_{req.vmid}_{int(time.time())}"
# Create output staging directory
out_dir = STAGING_OUT / str(req.vmid)
out_dir.mkdir(parents=True, exist_ok=True)
# In the real backend, this would:
# 1. Convert the source image to QCOW2 via qemu-img convert
# 2. Resize if target_disk_size_gb is set
# 3. Create the VM with qm create
# 4. Import the disk: qm importdisk <vmid> <qcow2> <storage>
# 5. Configure boot: qm set <vmid> --boot order=scsi0 --bios ovmf
# 6. Auto-start if configured: qm set <vmid> --onboot 1
# Stub: simulate a job being queued
return JobStatusResponse(
job_id=job_id,
vmid=req.vmid,
status=JobStatus.QUEUED,
progress_percentage=0,
message="Job queued for processing",
error_details=None,
)
def get_job_status(job_id: str) -> JobStatusResponse:
"""Query the current status of a job.
In the real backend, this would check the actual conversion process
(qemu-img progress, qm task status, etc.).
For now, returns a simulated progressing status to demonstrate the flow.
"""
# Stub: simulate progress advancing
parts = job_id.split("_")
vmid = int(parts[1]) if len(parts) >= 2 else 0
ts = int(parts[2]) if len(parts) >= 3 else 0
elapsed = int(time.time()) - ts
if elapsed < 5:
progress = min(int(elapsed * 10), 40)
status = JobStatus.PROCESSING_CONVERSION
msg = "Converting disk image..."
elif elapsed < 10:
progress = 40 + min(int((elapsed - 5) * 10), 50)
status = JobStatus.IMPORTING_STORAGE
msg = "Importing disk to Proxmox storage..."
else:
progress = 100
status = JobStatus.COMPLETED
msg = "VM created successfully"
return JobStatusResponse(
job_id=job_id,
vmid=vmid,
status=status,
progress_percentage=progress,
message=msg,
error_details=None,
)
def cleanup_staging(vmid: int, delete: bool) -> dict:
"""Remove staging files for a VM ID. Returns action details."""
in_dir = Path("/mnt/converter/in")
out_dir = STAGING_OUT / str(vmid)
if not delete:
return {
"job_id": f"job_{vmid}",
"action_taken": "retained",
"message": f"Staging files preserved for VM {vmid}",
}
# Remove extracted source files in /mnt/converter/in for this vmid
# (In production, you'd track which files belong to which job)
cleaned_in = False
cleaned_out = False
if out_dir.exists():
import shutil
shutil.rmtree(out_dir, ignore_errors=True)
cleaned_out = True
return {
"job_id": f"job_{vmid}",
"action_taken": "purged",
"message": f"Staging files deleted for VM {vmid}",
}