v0.5.8: Windows ISOs just work (HTTP sanboot) + Storage UX
Windows boot, the "less is more" way. Windows ISOs now boot via iPXE HTTP sanboot of the raw image — iPXE exposes the unmodified ISO as an emulated CD backed by on-demand HTTP range reads, and Windows Setup boots from it. This replaces the wimboot+SMB chain, which needed an SMB server the host often can't provide (:445 collisions), served in-ISO files via an ISO9660 lookup that failed on UDF-only Win11 ISOs, and was gated behind a Settings toggle the WebUI never even exposed (so Windows never booted). Now it needs only the HTTP port — works in any environment, SMB or not — and nothing is injected into Windows (no httpdisk.sys, no test certs, no trust-store changes; fully within the project's hard rules). - iso-store/store.rs: WindowsPe boot entry -> BootKind::SanBootIso of the raw iso/<id>.iso (render_entry already emits `sanboot --no-describe`). - iso-store/introspect.rs: broaden Windows detection for UDF-only Win10/11 ISOs — UTF-16LE markers (boot.wim/bootmgr/install.wim/microsoft), extra ASCII markers, and a filename heuristic, since their volume labels are cryptic and filenames are UTF-16. + unit tests. - http-api/ipxe_script.rs: Windows installers submenu shows whenever a Windows ISO is present — no toggle, no "disabled in Settings". - webui: dashboard no longer flags Windows ISOs (they boot now); the generic large-ISO warning reworded to read sensibly for genuinely non-bootable images (e.g. VMware VCSA appliance bundles). Storage UX: - Available images listed alphabetically by filename. - Upload gains a Cancel button (aborts the chunk + discards the partial). - beforeunload warning while an upload is in flight. 263 tests pass, clippy clean. NOTE: actual Windows boot is validated on real hardware — code/script/range-serving are validated here. Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
This commit is contained in:
co-authored by
Claude Opus 4.8
parent
ac433b30e9
commit
9fc9a9a1af
@@ -693,7 +693,7 @@ async fn log_recent_returns_buffered_lines() {
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn windows_iso_renders_clean_wimboot_script_with_no_trust_store_writes() {
|
||||
async fn windows_iso_renders_clean_sanboot_script_with_no_trust_store_writes() {
|
||||
// Synthesize an ISO with a Windows volume label + the sources/boot.wim
|
||||
// sentinel so introspection labels it WindowsPe with has_boot_wim.
|
||||
let mut buf = vec![0u8; 32 * 2048];
|
||||
@@ -763,38 +763,35 @@ async fn windows_iso_renders_clean_wimboot_script_with_no_trust_store_writes() {
|
||||
"introspection should detect sources/boot.wim sentinel"
|
||||
);
|
||||
|
||||
// The boot entry should be a wimboot kind with the canonical 5-file
|
||||
// chain documented in the LinusTechTips iPXE-Windows guide.
|
||||
// v0.5.8: Windows boots via iPXE HTTP sanboot of the raw ISO — no SMB,
|
||||
// no extraction, no in-ISO file serving, no operator toggle. The boot
|
||||
// entry is a `san_boot_iso` kind pointing at the raw image.
|
||||
let entry = &meta["boot_entries"][0];
|
||||
assert_eq!(entry["kind"]["kind"], "wimboot");
|
||||
let files = entry["kind"]["files"].as_array().unwrap();
|
||||
let names: Vec<&str> = files.iter().map(|f| f[0].as_str().unwrap()).collect();
|
||||
assert!(names.contains(&"bootmgr"));
|
||||
assert!(names.contains(&"bootmgr.efi"));
|
||||
assert!(names.contains(&"bcd"));
|
||||
assert!(names.contains(&"boot.sdi"));
|
||||
assert!(names.contains(&"boot.wim"));
|
||||
assert_eq!(entry["kind"]["kind"], "san_boot_iso");
|
||||
let iso_url = entry["kind"]["iso_url"].as_str().unwrap();
|
||||
assert!(
|
||||
std::path::Path::new(iso_url)
|
||||
.extension()
|
||||
.is_some_and(|e| e.eq_ignore_ascii_case("iso")),
|
||||
"sanboot should target the raw ISO, got: {iso_url}"
|
||||
);
|
||||
|
||||
// Render the entry script and verify:
|
||||
// 1. It uses wimboot
|
||||
// 2. All 5 files are referenced via `initrd --name`
|
||||
// 3. NO trust-store / driver / testsigning operations slip in
|
||||
// 1. It uses `sanboot` against the raw ISO over HTTP
|
||||
// 2. NO trust-store / driver / testsigning operations slip in
|
||||
let entry_id = entry["id"].as_str().unwrap();
|
||||
let url = format!("/boot/{entry_id}.ipxe");
|
||||
let (s, body) = get(&app, &url).await;
|
||||
assert_eq!(s, StatusCode::OK);
|
||||
let script = String::from_utf8(body).unwrap();
|
||||
assert!(script.contains("kernel "), "missing kernel line:\n{script}");
|
||||
assert!(
|
||||
script.contains("ipxe/wimboot"),
|
||||
"missing wimboot loader:\n{script}"
|
||||
script.contains("sanboot"),
|
||||
"missing sanboot line:\n{script}"
|
||||
);
|
||||
assert!(
|
||||
script.contains(&format!("/{iso_url}")),
|
||||
"sanboot should reference the raw ISO url:\n{script}"
|
||||
);
|
||||
for tag in ["bootmgr", "bootmgr.efi", "bcd", "boot.sdi", "boot.wim"] {
|
||||
assert!(
|
||||
script.contains(&format!("initrd --name {tag}")),
|
||||
"missing `initrd --name {tag}` line:\n{script}"
|
||||
);
|
||||
}
|
||||
// Hard guarantees we never want to see in any client-facing script.
|
||||
let lower = script.to_lowercase();
|
||||
for forbidden in [
|
||||
|
||||
Reference in New Issue
Block a user