Commit graph

15 commits

Author SHA1 Message Date
8ee3c78449 feat: add .vdi (VirtualBox) disk format support 2026-07-27 10:24:17 +00:00
75f90f16bb feat: multi-disk support — discover all disks in archive, select boot disk, additional disks included in job
- Storage pool discovery now uses pvesm status (reliable) with Custom... option
- discover_all_disks returns all found disk images sorted by size
- Analysis shows all disks with radio button for boot disk selection
- Confirm form passes boot disk + additional disks to job payload
2026-07-27 08:53:53 +00:00
878bc66da8 feat: add .ova support — OVA files are tar archives containing .vmdk disks 2026-07-26 07:42:06 +00:00
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
f1978008bd fix: use relative paths for STAGING_ROOT and LOG_DIR so backend works on host regardless of install location 2026-07-25 17:50:13 +00:00
6617aca341 fix: purge all old staging path references — full code review cleanup
Bugs found and fixed:
- converter.py: STAGING_IN.iterdir() → extract_base.iterdir()
  (checked wrong dir when source was in session subdir)
- vm-bench.service: TMPDIR=/mnt/converter/in → /mnt/converter/tmp
  (old path poisoned all temp file writes)
- backend/app.py: removed unused STAGING_IN constant
- converter.py: removed unused STAGING_OUT constant
- install.sh: removed creation of old /in and /out dirs
2026-07-23 10:36:03 +00:00
1b145adea7 fix: extraction uses file's parent dir as base, not hardcoded STAGING_IN
extract_if_needed now extracts relative to the source file's parent
directory instead of /mnt/converter/tmp/in/. This correctly handles
files in tmp/{guid}/in/ paths.
2026-07-23 10:19:43 +00:00
7a024ca166 fix: correct staging path resolution — tmp/{guid}/in not tmp/in/{guid}
Frontend now passes '{guid}/in/filename' to backend.
Backend extract_if_needed uses STAGING_ROOT (tmp/) as base.
Provisioner staging helpers build tmp/{guid}/in + tmp/{guid}/out.
2026-07-23 10:14:19 +00:00
9dcde5d022 fix: flatten nested single-child directories after extraction
Archives like Debian_13_VMG.7z contain nested single-child dirs:
  Debian_13_VMG_LinuxVMImages.COM/Debian_13_VMG_LinuxVMImages.COM/

_flatten_nested() collapses these chains until files sit directly
in the parent, eliminating the double-nesting issue.
2026-07-23 10:09:25 +00:00
a28e2af674 refactor: move staging to /mnt/converter/tmp/{guid}/in + out 2026-07-23 10:07:57 +00:00
7ded831354 fix: skip re-extraction if source directory already exists
When reusing a source image (Copy flow), the archive was already
extracted in /mnt/converter/in/. The extraction step failed with
'Destination path already exists' from 7z.

Now extract_if_needed checks if the expected output directory already
contains disk images, and returns it directly without re-extracting.
2026-07-23 09:28:02 +00:00
6ba7944bb2 fix: add unrar-free, use 7z for .zip extraction (more reliable)
- Added unrar-free package to backend installer
- Added .rar to archive extension detection
- Changed .zip extraction from unzip → 7z (x -y)
  7z handles .zip, .7z, and other formats with one tool
- Added unrar handler for .rar files
2026-07-21 19:37:27 +00:00
7808b16946 fix: prevent double-nested directory on archive extraction
Archives like 64bit.7z that already contain a 64bit/ top-level dir
were extracted into STAGING_IN/64bit/, creating 64bit/64bit/ nesting.

Now extract into STAGING_IN root, then:
- If the archive produced a single dir matching the stem, use it
- Otherwise, collect scattered files into a stem-named subdirectory

Removes the need for nested path: 64bit/Debian.vmdk instead of
64bit/64bit/Debian.vmdk
2026-07-21 18:58:13 +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