# VM Bench — Proxmox Image Conversion Frontend Web GUI and REST API for converting VMware disk images (VMDK, VHD, etc.) into Proxmox-compatible QCOW2 disks and provisioning VMs with automatic OS and boot type detection. ## Architecture ``` Browser vm-bench LXC Proxmox Host (srv2) (this container) ──→ :5000 ──→ frontend/app.py ──→ :9000 backend/app.py │ ├─ qemu-img (format, size) ├─ guestfish (OS, EFI detection) ├─ 7z/unzip (archive extraction) └─ qm create (VM provisioning) ``` - **Frontend** (`vm-bench` LXC) — FastAPI + Jinja2 web UI on port 5000 - **Backend** (`srv2` Proxmox host) — FastAPI REST API on port 9000 - **Shared storage** — `/mnt/converter/in` (staging) and `/mnt/converter/out` (output) ## Directory Layout ``` /mnt/converter/ ├── frontend/ # Web UI (runs on vm-bench LXC) │ ├── app.py # FastAPI app, routes, session handling │ ├── api_client.py # Typed REST client → backend │ ├── requirements.txt │ ├── templates/ # Jinja2 HTML templates │ │ ├── base.html │ │ ├── index.html # New session form │ │ ├── _analysis.html # Analysis result + confirm form │ │ └── polling.html # Progress bar + job status │ └── static/ │ └── proxmox.css ├── backend/ # REST API (deploy to Proxmox host srv2) │ ├── app.py # FastAPI app, routes │ ├── models.py # Pydantic request/response models │ ├── converter.py # Archive extraction, disk probing, OS/EFI detection │ ├── provisioner.py # VM provisioning (qm create/importdisk) │ ├── requirements.txt │ ├── install.sh # Systemd installation script │ └── vm-bench-backend.service ├── open-api.yaml # API spec (single source of truth) ├── in/ # Shared staging directory (gitignored) └── out/ # Shared output directory (gitignored) ``` ## Features - **File upload or URL download** — ingest `.vmdk`, `.vhd`, `.7z`, `.zip`, `.tar.gz` archives - **Automatic archive extraction** — 7z, unzip, tar, gunzip - **Disk analysis** — detects format, virtual size, guest OS, EFI bootability - **VM provisioning** — creates Proxmox VM with automatic disk import and boot config - **Progress polling** — real-time job status with progress bar - **Staging reuse** — keep source files to create multiple VMs from one image ## Prerequisites ### Backend (Proxmox host `srv2`) - Python 3.13+ - `qemu-img` (from `qemu-utils`) - `guestfish` (from `libguestfs-tools`) - `7z`, `unzip`, `tar` (for archive extraction) - `systemd` (for service management) ### Frontend (`vm-bench` LXC) - Python 3.13+ - `wget` (for URL downloads) - `systemd` (for service management) - Network access to backend at `10.2.0.2:9000` ## Installation ### 1. Backend (on Proxmox host `srv2`) ```bash # The backend code is shared via /mnt/converter/backend/ cd /mnt/converter/backend bash install.sh ``` This installs Python dependencies, copies the systemd service, and starts `vm-bench-backend` on port 9000. Verify: ```bash curl http://127.0.0.1:9000/api/v1/health # → {"status":"ok"} ``` ### 2. Frontend (on `vm-bench` LXC) ```bash # Install dependencies cd /mnt/converter/frontend pip3 install --break-system-packages -r requirements.txt # Copy service file and start cp /etc/systemd/system/vm-bench.service /etc/systemd/system/ systemctl daemon-reload systemctl enable --now vm-bench ``` The frontend serves on port 5000. Open `http://:5000` in a browser. ## API Reference All endpoints are under `/api/v1/`. Full specification in [`open-api.yaml`](open-api.yaml). | Method | Path | Description | |--------|------|-------------| | `GET` | `/api/v1/health` | Health check | | `POST` | `/api/v1/analyze` | Probe source image (format, size, OS, EFI) | | `POST` | `/api/v1/jobs` | Submit conversion + provisioning job | | `GET` | `/api/v1/jobs/{id}` | Poll job status and progress | | `POST` | `/api/v1/jobs/{id}/cleanup` | Delete or preserve staging files | ### Example: Analyze a source image ```bash curl -X POST http://10.2.0.2:9000/api/v1/analyze \ -H "Content-Type: application/json" \ -d '{"vmid": 21050, "source_filename": "64bit/Debian 12.11.0 (64bit).vmdk"}' # Response: # { # "vmid": 21050, # "filename": "Debian 12.11.0 (64bit).vmdk", # "disk_format": "vmdk", # "disk_size_gb": 7.5, # "os_type": "Debian", # "efi_detectable": true # } ``` ### Example: Submit a conversion job ```bash curl -X POST http://10.2.0.2:9000/api/v1/jobs \ -H "Content-Type: application/json" \ -d '{ "vmid": 21050, "vm_name": "debian-test", "boot_disk": { "disk_type": "image_file", "source_filename": "64bit/Debian 12.11.0 (64bit).vmdk", "format": "vmdk" }, "cpu_cores": 2, "ram_mb": 4096, "target_storage": "local-lvm" }' # Response: # { "job_id": "job_21050_1737480000", "vmid": 21050, "status": "queued", ... } ``` ## Usage Flow 1. **Open the web UI** → new session form 2. **Upload or download a source image** → file lands in `/mnt/converter/in/` 3. **Backend analyses the image** → shows format, size, OS, EFI status 4. **Configure VM settings** → name, CPU, RAM, storage, boot type 5. **Submit job** → backend converts, shrinks (if needed), creates VM 6. **Poll progress** → real-time status bar updates every 2 seconds 7. **Reuse or cleanup** → create another VM from same source, or delete staging files ## Configuration | Variable | Default | Description | |----------|---------|-------------| | `BACKEND_URL` | `http://10.2.0.2:9000` | Backend API base URL (set in systemd unit) | | `VM_ID_MIN` | `21000` | Minimum allowed Proxmox VM ID | | `VM_ID_MAX` | `21100` | Maximum allowed Proxmox VM ID | ## Development **Source of truth**: `open-api.yaml` — always derive models from this file. **Backend tool requirements** (on srv2): - `qemu-img` — disk format and size detection - `guestfish` / `virt-inspector` — OS type and EFI boot detection - `7z`, `unzip`, `tar`, `gunzip`, `bunzip2`, `xz` — archive extraction **Provisioner note**: `backend/provisioner.py` is currently a stub with simulated progress. Replace with real `qm create`, `qm importdisk`, and `qm set` commands when deploying to the Proxmox host. **Staging files**: `/mnt/converter/in/` and `/mnt/converter/out/` are gitignored — they contain user data, not code.