From 6bcb68c5520674c5c7dcc560a41f2f673bbf63e7 Mon Sep 17 00:00:00 2001 From: Claus Lohmar Date: Tue, 21 Jul 2026 16:50:40 +0000 Subject: [PATCH] chore: VM ID range 21000-21100, network default vmbr0, target_storage default local-lvm --- frontend/app.py | 22 +++ frontend/templates/index.html | 4 +- open-api.yaml | 245 ---------------------------------- 3 files changed, 24 insertions(+), 247 deletions(-) delete mode 100644 open-api.yaml diff --git a/frontend/app.py b/frontend/app.py index 900d184..8ae3fa0 100644 --- a/frontend/app.py +++ b/frontend/app.py @@ -43,6 +43,17 @@ STAGING = Path("/mnt/converter/in") api = ApiClient() +# Config +VM_ID_MIN = 21000 +VM_ID_MAX = 21100 +DEFAULT_STORAGE = "local-lvm" +DEFAULT_NETWORK = "vmbr0" + +def _validate_vmid(vmid: int) -> Optional[str]: + if not (VM_ID_MIN <= vmid <= VM_ID_MAX): + return f"VM ID must be between {VM_ID_MIN} and {VM_ID_MAX}." + return None + def render(name: str, status: int = 200, **ctx) -> HTMLResponse: tpl = _jinja.get_template(name) return HTMLResponse(tpl.render(**ctx), status_code=status) @@ -71,6 +82,11 @@ async def start_session( filename = None error = None + # Validate VM ID range + err = _validate_vmid(vmid) + if err: + return render("_analysis.html", request=request, error=err) + # --- Get the file into /mnt/converter/in/ --- if source_type == "upload": if not source_file or not source_file.filename: @@ -134,12 +150,18 @@ async def confirm_session( boot_type: str = Form("uefi"), ): """Build the job payload and submit to the backend.""" + # Validate VM ID range + err = _validate_vmid(vmid) + if err: + return render("_analysis.html", request=request, error=err) + payload = { "vmid": vmid, "vm_name": vm_name, "cpu_cores": cpu_cores, "ram_mb": ram_mb, "target_storage": target_storage, + "network": DEFAULT_NETWORK, "auto_detect_boot": auto_detect_boot == "true", "boot_type": boot_type, "boot_disk": { diff --git a/frontend/templates/index.html b/frontend/templates/index.html index c0e78f1..2ab0f0e 100644 --- a/frontend/templates/index.html +++ b/frontend/templates/index.html @@ -9,8 +9,8 @@
- Must be unique on the Proxmox host + placeholder="e.g. 21050" min="21000" max="21100"> + Range 21000–21100. Must be unique on the Proxmox host.
diff --git a/open-api.yaml b/open-api.yaml deleted file mode 100644 index 8c2bf6c..0000000 --- a/open-api.yaml +++ /dev/null @@ -1,245 +0,0 @@ -openapi: 3.0.3 -info: - title: Proxmox Image Conversion Engine - description: | - Backend API that runs on the Proxmox host (`srv2`) to convert VMware images - (VMDK, VHD, etc.) to Proxmox‑compatible QCOW2, optionally shrink the disk, - and provision a VM with automatic boot‑type detection. - version: 1.1.0 - contact: - name: Support - url: https://github.com/your-org/converter - -servers: - - url: http://10.2.0.2:9000/api/v1 - description: Internal Proxmox host (srv2) - -paths: - /jobs: - post: - summary: Submit a new VM conversion and creation job - operationId: createJob - requestBody: - required: true - content: - application/json: - schema: - $ref: '#/components/schemas/JobSubmissionRequest' - responses: - '202': - description: Job accepted and queued for processing - content: - application/json: - schema: - $ref: '#/components/schemas/JobStatusResponse' - '400': - description: Invalid request or source file not found - content: - application/json: - schema: - $ref: '#/components/schemas/ErrorResponse' - - /jobs/{job_id}: - get: - summary: Get the current status of a conversion job - operationId: getJobStatus - parameters: - - name: job_id - in: path - required: true - schema: - type: string - example: "job_10007_1784637888" - responses: - '200': - description: Job status details - content: - application/json: - schema: - $ref: '#/components/schemas/JobStatusResponse' - '404': - description: Job not found - content: - application/json: - schema: - $ref: '#/components/schemas/ErrorResponse' - - /jobs/{job_id}/cleanup: - post: - summary: Delete staging files or preserve them for reuse - operationId: cleanupJob - parameters: - - name: job_id - in: path - required: true - schema: - type: string - example: "job_10007_1784637888" - requestBody: - required: true - content: - application/json: - schema: - $ref: '#/components/schemas/CleanupRequest' - responses: - '200': - description: Cleanup action performed - content: - application/json: - schema: - type: object - properties: - job_id: - type: string - action_taken: - type: string - enum: [purged, retained] - message: - type: string - - /health: - get: - summary: Health check endpoint - operationId: healthCheck - responses: - '200': - description: Service is healthy - content: - application/json: - schema: - type: object - properties: - status: - type: string - example: ok - -components: - schemas: - DiskSpec: - type: object - required: - - disk_type - properties: - disk_type: - type: string - enum: [image_file, empty_disk] - description: | - `image_file` – convert an existing file from `source_filename`. - `empty_disk` – create a blank disk of the given `size_gb`. - source_filename: - type: string - nullable: true - description: Path relative to `/mnt/converter/in` (required if `disk_type=image_file`) - example: "64bit/Debian 12.11.0 (64bit).vmdk" - size_gb: - type: integer - nullable: true - description: Size in GiB (required if `disk_type=empty_disk`) - example: 50 - format: - type: string - enum: [qcow2, raw, vmdk] - default: qcow2 - description: Source image format (for `image_file`) - - JobSubmissionRequest: - type: object - required: - - vmid - - vm_name - - boot_disk - properties: - vmid: - type: integer - description: Proxmox VM ID (must be unique on host) - example: 10007 - vm_name: - type: string - description: Display name for the VM - example: "debian-default-shrink" - boot_type: - type: string - enum: [uefi, legacy] - default: uefi - description: Boot firmware type (ignored if `auto_detect_boot=true`) - auto_detect_boot: - type: boolean - default: true - description: | - If `true`, automatically detects whether the disk is EFI‑bootable and - overrides `boot_type`. Falls back to `legacy` if detection fails. - cpu_cores: - type: integer - default: 4 - minimum: 1 - example: 2 - ram_mb: - type: integer - default: 8192 - minimum: 512 - example: 4096 - target_storage: - type: string - default: "local-lvm" - description: Proxmox storage pool for the VM disks - example: "local-lvm" - boot_disk: - $ref: '#/components/schemas/DiskSpec' - additional_disks: - type: array - items: - $ref: '#/components/schemas/DiskSpec' - description: Additional data disks (converted or empty) - target_disk_size_gb: - type: integer - nullable: true - description: | - If provided, the boot disk (and only the boot disk) is resized to this - size (GiB). If omitted and the boot disk is larger than 30 GiB, it is - automatically shrunk to 30 GiB. Only shrinks when disk_type=image_file. - example: 40 - - JobStatusResponse: - type: object - properties: - job_id: - type: string - example: "job_10007_1784637888" - vmid: - type: integer - example: 10007 - status: - type: string - enum: [queued, processing_conversion, importing_storage, completed, failed] - description: Current job phase - progress_percentage: - type: integer - minimum: 0 - maximum: 100 - example: 75 - message: - type: string - description: Human‑readable status message - example: "Creating VM and importing disks..." - error_details: - type: string - nullable: true - description: If status is `failed`, contains the error reason - - CleanupRequest: - type: object - required: - - delete_staging_files - properties: - delete_staging_files: - type: boolean - description: | - `true` – delete extracted source files and converted disk images. - `false` – keep files so another VM can be created from the same source. - - ErrorResponse: - type: object - properties: - detail: - type: string - example: "Source file not found: 64bit/Debian 12.11.0 (64bit).vmdk"