Commit graph

11 commits

Author SHA1 Message Date
f3477dc23b fix: raw streaming upload endpoint — bypasses multipart parser for large files
Starlette's multipart parser (pure Python) is too slow for >1 GB uploads —
boundary scanning over gigabytes blocks the event loop indefinitely.

New /session/upload-raw endpoint:
- Receives raw binary body via request.stream() — no parsing overhead
- Metadata (filename, vmid, vm_name) passed in HTTP headers
- Async chunked write directly to staging — true zero-copy streaming
- Same progress logging as before

Frontend now sends File object directly via xhr.send(file)
instead of FormData — eliminates multipart encoding on the client too.
2026-07-22 09:02:05 +00:00
837e674195 feat: SCP Pull page for large files from remote servers
New /scp page with form for host, user, password, remote path.
Runs scp via sshpass in background with progress polling.
Files go to /mnt/converter/in/{session_id}/ for multi-user isolation.

- Added sshpass + openssh-client to frontend installer
- scp.html template with full form + progress bar
- POST /scp/start — launches background SCP via sshpass -e
- GET /scp/progress/{sid}/{file} — polls file size + speed
- 'SCP Pull (+10 GB)' button on start page
2026-07-22 05:52:01 +00:00
1183059d8b fix: add no-cache headers + remove debug console.logs
- Cache-Control/Pragma/Expires headers prevent browser caching
  of JS-heavy pages (fixes stale code after updates)
- Removed debug console.log statements from upload handlers
2026-07-22 05:24:21 +00:00
6519fc1cf7 fix: use permanent DOM elements for progress instead of innerHTML reset
innerHTML reset in startSession was destroying #phase-label and
#progress-fill elements, then recreating them with same IDs. XHR
progress events fired asynchronously but getElementById might
return stale references or fail during the DOM update window.

Now #phase-label, #progress-fill, and #session-error are permanent
elements in the static HTML. startSession clears them via
textContent/style instead of innerHTML — no DOM destruction.
showError appends to #session-error instead of #session-status.
2026-07-22 05:19:13 +00:00
f032c546e1 debug: add console.log to upload handlers to diagnose missing progress 2026-07-21 19:46:08 +00:00
5ff0635aa5 fix: show upload phase immediately + fallback for non-computable progress
Added loadstart handler to show 'Uploading...' spinner as soon as
upload begins, plus fallback label when lengthComputable is false
(shows bytes uploaded even without percentage).
2026-07-21 19:43:04 +00:00
989807f29e fix: innerHTML script execution bug — confirm form and polling now work
Root cause: innerHTML does not execute <script> tags in modern browsers.
The _analysis.html and polling.html fragments had inline <script> blocks
that were silently dropped, causing:
- Confirm form's submitJob() undefined → form submitted as normal GET
  back to '/' (user saw 'New Conversion Session' instead of polling)
- Polling page's poll() never started → stuck on 'Waiting for backend...'

Fix:
- Stripped all <script> tags from _analysis.html and polling.html
- Moved all JS logic into index.html (executed on page load)
- initConfirmForm() attaches submit/change listeners after analysis HTML
  is injected via innerHTML
- initPolling() attaches poll timer + reuse button handlers after
  polling fragment is injected
- Polling fragment replaces step1/analysis content while keeping
  base.html header/footer intact
- Reuse buttons now use onclick attached via JS (not inline)
2026-07-21 18:43:16 +00:00
af26da7b64 feat: two-phase upload/download with real-time progress + smart speed timeout
Split monolithic /session/start into two endpoints:
- POST /session/upload  — phase 1: file acquisition only, returns JSON
- POST /session/analyze — phase 2: backend analysis, returns HTML
- GET  /session/progress/{filename} — poll download progress

Uploads:
- Browser-native progress bar via XMLHttpRequest (real % + GiB)

Downloads:
- wget runs in background (Popen), frontend polls /session/progress
- HEAD request gets Content-Length before download starts
- Real-time speed (MB/s) and ETA displayed in the UI
- Smart timeout: after 30s, if ETA > 1 hour, kills download and
  suggests manual download to laptop + File Upload instead
- Absolute safety net at 4 hours

UI: clear phase transitions — 'Downloading... 2.3 GiB (4.5 MB/s) ~12 min'
→ 'Step 2/2: Analysing source image...' → result
2026-07-21 18:10:52 +00:00
509eb97b57 fix: large-file support + user-defined VM name
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)
2026-07-21 17:59:31 +00:00
6bcb68c552 chore: VM ID range 21000-21100, network default vmbr0, target_storage default local-lvm 2026-07-21 16:50:40 +00:00
a8099f504c chore: initial commit — vm-bench frontend + backend 2026-07-21 14:53:29 +00:00