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
Both frontend and backend now write rotating log files to
/mnt/converter/logs/ (shared between host and LXC):
/mnt/converter/logs/vm-bench.log (frontend)
/mnt/converter/logs/vm-bench-backend.log (backend)
- RotatingFileHandler: 10 MB per file, 5 backups
- Console handler still writes to systemd journal
- Logs/ directory is gitignored and auto-created on startup
- Install script creates logs/ directory
Backend had zero logging. Frontend logs were fine (logging.basicConfig
in app.py). Now both services write structured logs to systemd journal:
journalctl -u vm-bench -f # frontend (LXC)
journalctl -u vm-bench-backend -f # backend (srv2)
{job_id} in f-strings was interpreted as Python variable instead
of FastAPI path parameter. Double braces {{job_id}} produce
literal {job_id} in the route string.
Large-file handling:
- Set TMPDIR=/mnt/converter/in in service to spool uploads to
shared storage instead of 24 GB LXC rootfs (critical for >24GB)
- Chunked upload streaming (8 MiB) with progress logging every 1 GiB
- Pre-flight disk space check via Content-Length header
- Clean up partial files on upload/download failure
- Download timeout extended to 7200s (2 hours) for 88 GB images
- Switched wget from --show-progress to --progress=dot:giga
(compact output, won't fill memory on large transfers)
- uvicorn --timeout-keep-alive 300 on both frontend and backend
VM name:
- Added vm_name field to initial session form (step 1)
- Falls back to auto-generated 'os_type-vmid' if left blank
- Pre-filled & editable in confirm form (step 2)