iso-detection — Integration with the ISO library
Integration with the ISO library
Section titled “Integration with the ISO library”The detector pipeline runs automatically every time an operator uploads an ISO. The dashboard never has to call the detection API directly — it just polls the cache.
Upload-time hook
Section titled “Upload-time hook”crates/daemon/src/api/isos.rs is the existing upload handler. After
the streamed body lands at its final path the handler spawns a
background blocking task:
let detect_path = final_path.clone();tokio::task::spawn_blocking(move || { match crate::iso_detection::detect_path(&detect_path) { Ok(result) => { tracing::info!( iso = %detect_path.display(), detector = %result.detector, profile_id = %result.hint.profile_id, confidence = ?result.confidence, "ISO detected" ); if let Err(e) = crate::iso_detection::store::cache_for_path(&detect_path, &result) { tracing::warn!(?e, "ISO detection cache write failed"); } } Err(e) => { tracing::warn!(iso = %detect_path.display(), error = %e, "ISO detection failed"); } }});Three properties matter here:
- The HTTP response returns immediately. Detection happens out of band; the dashboard’s “uploaded” toast fires before the pipeline starts.
- Detection is best-effort. A detector failure (mount refused, wimlib missing, no detector matched) is logged but never breaks the upload — the file is still in the library and the operator can pick a profile manually.
- The cache is the source of truth for the dashboard. Anything
that wants to know “what is this ISO” reads
GET /api/v1/iso-detection/results, not the live pipeline.
Cache flow
Section titled “Cache flow”upload handler --> spawn_blocking | v detect_path() -> DetectionResult | v store::cache_for_path(path, result) | sha256 the file (streaming) | v prisma row absent? -> sled.put(sha256, Entry) prisma row exists? -> sled.update(...) (refresh sha + size)The sled tree is iso-detection. Keys are hex SHA-256 strings;
values are JSON-serialised Entry blobs. Database location:
- prod:
/var/lib/synvirt/iso-detection.db/ - dev (
SYNVIRT_DEVset):$HOME/.synvirt/iso-detection.db/
Reading from the dashboard
Section titled “Reading from the dashboard”The dashboard’s ISOs view fans out to two endpoints in parallel:
GET /api/v1/isos → flat list of filesGET /api/v1/iso-detection/results → cache contents (sha256-keyed)It joins them client-side on filename / sha256 to render rows like:
| Filename | Size | Detected | Profile suggestion |
|---|---|---|---|
| Win11_23H2_x64.iso | 5.3 GiB | windows_modern (high) | windows-11 |
| ubuntu-24.04-live-server-amd64.iso | 2.7 GiB | ubuntu (high) | generic-other (until v0.11) |
| nas-recovery-2024.iso | 312 MiB | generic (low) | generic-other |
ISOs that landed before this module shipped show “—” in the
“Detected” column until the operator hits “Re-detect” (which calls
POST /api/v1/iso-detection/re-detect and refreshes the cache).
Manual re-detection
Section titled “Manual re-detection”curl -fsS -u admin:hunter2 -H 'content-type: application/json' \ -d '{"iso_path":"/var/lib/synvirt/isos/Win11_23H2_x64.iso"}' \ https://node.local/api/v1/iso-detection/re-detect | jqToday this endpoint is a synchronous probe. v0.10.1 will also write through to the cache so the dashboard’s results endpoint reflects the new run automatically — see ROADMAP.md.
What about storage pools?
Section titled “What about storage pools?”The original v0.10.0 spec mentioned /api/v1/storage-pools/{id}/isos.
The current daemon doesn’t have per-pool ISO buckets — /api/v1/isos
is a flat library at /var/lib/synvirt/isos/. When per-pool ISO
folders ship (planned for the storage refactor), the upload handler
already passes the final path into the detector unchanged, so
detection will keep working without any change to this module.
Failure modes
Section titled “Failure modes”| Symptom | Cause | Fix |
|---|---|---|
| Cache empty after upload | Pipeline crashed before reaching the store, or sled DB couldn’t open | Check daemon logs for “ISO detection failed” / “ISO detection cache write failed” |
wimlib-imagex warnings |
wimtools package not installed on the host |
apt install wimtools (already in the live-build package list as of 0.10.0) |
mount: failed |
Loop devices exhausted (/dev/loop* busy) |
systemd’s periodic loop-detach should clear stale ones; manually losetup -d /dev/loop* if needed |
Detection succeeded but profile_id = "generic-other" for a Linux ISO |
Linux family vm-profiles haven’t shipped yet (v0.11) | Pick the base profile manually in the dashboard for now |
Cross-references
Section titled “Cross-references”- API.md — endpoints to read the cache.
- ARCHITECTURE.md — pipeline + store schema.
- ../vm-profiles/README.md — companion module
that consumes the
OsHint.profile_id.