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"