Commit graph

6 commits

Author SHA1 Message Date
1ecaefe1d8 feat: async analysis with polling + nested archive extraction
- Backend /api/v1/analyze now returns 202 with analysis_id immediately
- New GET /api/v1/analyze/{id} for polling analysis status
- Background thread handles extraction, disk discovery, OS/EFI detection
- Nested archive extraction: handles chained zips and split zips (.z01-.zNN)
- Frontend polls /session/analyze/status/{id} every 2s until complete
- SCP page now has complete confirm form flow with job polling
2026-07-26 00:13:14 +00:00
6db69f434c fix: Clean Up now deletes entire session directory tmp/{guid}/
- Backend cleanup_staging accepts session_id, deletes whole
  STAGING_ROOT/{guid}/ dir when provided
- CleanupRequest model gets session_id field
- Frontend cleanup proxy passes session_id from body
- api_client passes session_id to backend
- reuseImage JS includes session_id in cleanup payload
2026-07-23 10:54:42 +00:00
63659e4f93 feat: session GUID isolation for multi-user support
Each browser gets a UUID stored in localStorage, set as a cookie,
and attached to every API call. Files go to session-specific dirs:

  /mnt/converter/in/{guid}/    — uploads, downloads, SCP pulls
  /mnt/converter/out/{guid}/   — converted QCOW2s

Changes:
- base.html: generates UUID via crypto.randomUUID(), stores in
  localStorage + cookie, exposes as window.VM_BENCH_SID
- Frontend: all endpoints accept session_id, _staging() helper
  creates session-aware paths on demand
- JavaScript: session_id appended to all FormData, set as
  X-Session-ID header on raw uploads
- Backend models: JobSubmissionRequest.session_id field added
- Provisioner: _staging_in/_staging_out helpers, source path
  resolution uses session-aware directory
- Converter: extract_if_needed skips re-extraction if dir exists
2026-07-23 09:32:16 +00:00
9eb0f15261 feat: Clone (qm clone) + Copy (re-convert) buttons on completion
After conversion completes, the user sees a form with VM Name and ID
prefilled, and three buttons:

- Clone (instant): qm clone --full via backend, takes seconds
- Copy (re-convert): shows CPU/RAM/Disk fields, re-runs full pipeline
- Clean Up & Finish: deletes staging, returns to start page

Backend: new /api/v1/clone endpoint → provisioner.clone_vm()
Frontend: new /session/clone proxy, api_client.clone_vm()
2026-07-23 09:02:57 +00:00
c887ccd5a3 fix: uniform /api/v1/ prefix, real EFI detection, spec alignment
Backend:
- All routes now consistently under /api/v1/ (health, analyze, jobs)
- Replace dummy EFI heuristic with actual guestfish-based detect_efi()
- Add path traversal validation on analyze source_filename
- Use typed response models (HealthResponse, CleanupResponse) everywhere
- Clean up unused imports (Path, ErrorResponse)

Models:
- Align AnalyzeResponse with open-api.yaml (add vmid, remove bootable/error,
  make efi_detectable nullable, deduplicate CleanupResponse)

Converter:
- Add detect_efi(disk_path) using guestfish list-filesystems

Frontend:
- Update api_client paths to /api/v1/health and /api/v1/analyze
- Remove unsupported 'network' field from job payload

Spec:
- Promote inline HealthResponse/CleanupResponse to named schemas
- Move /analyze and /health under /api/v1/ prefix

Docs:
- Add README.md with architecture, install, API reference, usage flow
2026-07-21 17:40:08 +00:00
a8099f504c chore: initial commit — vm-bench frontend + backend 2026-07-21 14:53:29 +00:00