Linux create: cache the prefetches and show progress while downloading - #124
Closed
adihanifsdr wants to merge 5 commits into
Closed
Linux create: cache the prefetches and show progress while downloading#124adihanifsdr wants to merge 5 commits into
adihanifsdr wants to merge 5 commits into
Conversation
…kernel Refs jamesstringer90#66. do_ubuntu_to_vhdx builds the rootfs from casper/minimal.squashfs and picks the kernel version up from the first /boot/vmlinuz-* it sees during the walk. On the Ubuntu 26.04 desktop ISO that layer carries the kernel; on 24.04 it does not (the kernel lives only in the minimal.standard.live overlay). A full ingest of ubuntu-24.04.4-desktop-amd64.iso walks 85,075 files / 4.9 GiB and never sees a vmlinuz, so kernel_ver stays empty and the bootstrap grub.cfg is written as: linux /boot/vmlinuz- root=UUID=... ro ... initrd /boot/initrd.img- GRUB cannot load that, the guest sits at the GRUB prompt with one vCPU busy and ~24 MB of RAM touched, the agent never comes up, and the UI shows "Installing Linux" forever with nothing in the log explaining why. Two changes: * tools/iso-patch/ubuntu_vhdx.c: after the squashfs ingest, treat an empty kernel version as a hard error. log_err() reports which image lacked /boot/vmlinuz-* and that only Ubuntu Desktop 26.04 LTS ISOs are supported; exit_code stays 1 so cleanup deletes the VHDX. Also log the detected kernel version as a STATUS line on success. * src/backend_win/asb_core.c (run_iso_patch_ubuntu): forward iso-patch STATUS: and ERROR: lines into the app log. The Windows --to-vhdx path deliberately ignores STATUS lines because the in-guest installer logs are available later; the Linux build has no such fallback, so these lines are the only host-side record of how the disk was built. A cheaper pre-flight on casper/minimal.manifest was considered and dropped: the manifest lists no linux-image-* package on the 26.04 and 26.04.1 ISOs either, so it cannot tell bootable from unbootable images. The post-ingest check reads the actual squashfs contents and only rejects builds that would have produced an unbootable disk. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Refs jamesstringer90#66. Ubuntu Desktop ISOs since 23.04 are "fsimage-layered". On 26.04 the base layer (casper/minimal.squashfs) still carries /boot/vmlinuz-*, initrd and /usr/lib/modules, so the plain ingest boots. On 24.04 it does not: the kernel lives only in minimal.standard.live.squashfs and the initrd only as casper/initrd, which is why a 24.04 build used to hang at GRUB ("Installing Linux" forever). Three things were needed to make 24.04 an installable target end to end: iso-patch (ubuntu_vhdx.c) * The squashfs ingest is now a function (ingest_squashfs) with an optional include-prefix filter, so an overlay layer can be walked for just /boot/{vmlinuz,System.map,config}-* and /usr/lib/modules/*. * When the base layer yields no kernel, stage_kernel_from_live_layer() pulls those from the live overlay, stores casper/initrd as /boot/initrd.img-<ver>, adds boot=local to the bootstrap grub.cfg (the live initrd defaults to BOOT=casper but honours boot=) plus an /etc/default/grub.d drop-in so update-grub keeps it, and leaves /etc/appsandbox-kernel-from-iso for first boot. * First boot gains STEP 7.6: with that marker present, apt-install linux-image/-modules/-modules-extra for the running kernel from the local mirrors so dpkg owns the files and a regular initrd is generated. Best-effort - the ISO initrd keeps working if it cannot. * The no-kernel error from the previous commit now only fires when the fallback also finds nothing. prefetch-build-deps (prefetch_build_deps.c) * Merge the <codename>-updates Packages index after the release one. Point-release ISOs (24.04.4) are -updates snapshots: the base already has libasound2t64 1.2.11-1ubuntu0.1, and the release pocket's libasound2-dev pins "= 1.2.11-1build2", so apt refused the whole build tool set. Later stanzas win in the hash chain, so -updates is preferred. * Seed build-essential and dkms (the 24.04.4 pool has gcc-13 but not libstdc++-13-dev / libgcc-13-dev / cpp-13) and initramfs-tools + linux-base (needed by STEP 7.6, absent from the pool). * Retry each download 3x with back-off; only the last attempt logs an ERROR. One flaky GET out of ~180 used to abort the run. * On failure wipe the output dir. A half-populated dir left the raw release-pocket Packages index behind and apt in the guest happily resolved "= version" candidates from it - then failed on everything. app (asb_core.c) * detect_iso_kernel reads the release string from casper/vmlinuz's bzImage header (falling back to the pool scan). On 24.04 the pool scan returned the GA 6.8 headers while the ISO boots the HWE 6.17 kernel, so the prefetched linux-headers did not match uname -r. * spawn_iso_patch_prefetch captures the child's output and forwards ERROR: and summary STATUS: lines to the app log, so a failed prefetch finally says why. Verified on Windows 11 26200 / RTX 3070 with ubuntu-24.04.4-desktop-amd64.iso through the headless daemon: build 3.5 min (+ prefetch), first boot runs all steps OK (apt build tools, kernel dpkg registration + initrd regen, agent build, DKMS asb_drm + dxgkrnl against 6.17.0-14-generic), reboot, agent online, sshState 4. Inside the guest: /dev/dxg and /dev/dri/card1 present, all four appsandbox services active, nvidia-smi reports the host GPU. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Refs jamesstringer90#66. Follow-up to the 24.04 layered-ISO support: with the kernel sorted, the guest came online but the display stayed black, and a Force Stop then left it unbootable. Both turned out to be general robustness gaps that 24.04 merely exposed first. Black desktop * The wsl-mesa prebuilt is built on 26.04 against LLVM 21. STEP 13 put it on ld.so.conf unconditionally, which shadows the distro Mesa for every process. On 24.04 libgallium cannot resolve libLLVM.so.21.1, so mutter fails to create a GBM device on asb_drm ("No GPUs found"), the Xorg fallback finds no screens, gdm gives up, and appsandbox-display waits forever for a framebuffer. * STEP 13 now runs ldd on the extracted libgallium/libgbm and only activates the prebuilt when everything resolves; otherwise it removes /opt/wsl-mesa and logs which libraries are missing. The desktop then runs on the distro Mesa (llvmpipe, exactly what the compositor uses on 26.04 as well). * 50-appsandbox-gpu and appsandbox-gpu gain a fallback: with /dev/dxg present but no /opt/wsl-mesa, they select the distro Mesa's own d3d12 gallium driver (Ubuntu builds it for WSL; libdxcore/libd3d12 come from the wsl-deps prefetch already on the loader path). OpenGL apps still reach the host GPU; Vulkan stays on lavapipe because stock mesa-vulkan-drivers ships no dzn ICD. Unbootable after Force Stop * iso-patch's ext4 writer lays the root fs down without a journal. An unclean stop of a running guest (Force Stop while a graceful shutdown was still in progress) left it "not clean with errors"; the boot-time fsck could not preen it, dropped to a maintenance prompt nobody can see, and the VM sat idle with no agent. * fsck.repair=yes on the bootstrap cmdline and a grub.d drop-in that keeps it there after update-grub (plus GRUB_RECORDFAIL_TIMEOUT=5 so a failed boot does not park the menu for ever). * New first-boot STEP 98 adds a journal to the mounted root with tune2fs -O has_journal right before the reboot, so later unclean stops replay a journal instead of needing a full check. Verified so far on the 24.04.4 guest from the previous commit, with the same changes applied offline through a WSL mount of its VHDX: e2fsck -fy brought the fs back from 'not clean with errors', tune2fs -O has_journal added the journal, and the boot-time journal explained the black desktop (mutter: 'MESA-LOADER: failed to open dri: libLLVM.so.21.1', 'No GPUs found'). A fresh 24.04 build exercising STEP 13's rollback and STEP 98 end to end is the next test. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Every Linux create re-downloaded the same three things from scratch, sequentially, before iso-patch even started: the repo tarball from GitHub (~80 MB), the apt build-deps closure (~180 .debs, ~120 MB) and the wsl-deps NuGet package. That is 5-7 minutes during which the UI sits at "Building Disk (0%)" and looks hung - the disk build itself takes ~90 s. * %ProgramData%\AppSandbox\cache\prefetch\<key>\ now keeps each prefetch result (repo-<branch>, build-deps-<codename>-<kver>, wsl-deps). A fresh entry is copied into the staging dir instead of downloading; entries carry a .cache-ok marker written only after a complete run and expire by age (repo daily, build-deps weekly, wsl-deps monthly), so a moved branch or a refreshed -updates pocket is still picked up. APPSANDBOX_NO_PREFETCH_CACHE=1 bypasses it; deleting the dir does too. * spawn_iso_patch_prefetch reports build progress: the three prefetches own 1..9% of the bar, advanced per downloaded .deb using the "closure = N packages" line, so the bar moves during the downloads. run_iso_patch_ubuntu keeps the bar monotonic through iso-patch's own early 2/4/6% steps. Second and later creates for the same release go from ~7 min of prefetch to a few seconds of copying. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Follow-up to the prefetch cache: make the first (uncached) download fast
and stop calling it "Building Disk".
* prefetch-build-deps downloads the closure on 6 connections at once
(a small worker pool over the closure list; first failure stops the
rest). archive.ubuntu.com and most mirrors cap per-connection
throughput well below the link, so this is where the minutes went.
* The app passes --mirror http://<cc>.archive.ubuntu.com/ubuntu, Ubuntu's
per-country alias derived from the Windows region (the same choice the
Ubuntu installer makes); APPSANDBOX_APT_MIRROR overrides it. iso-patch
falls back to the main archive if the alias is unusable, so a bad guess
costs one failed request, not the build.
* VmInstance.vhdx_step (already there, never used) now carries the phase
name: "Downloading sources", "Downloading packages 42/182",
"Downloading GPU libraries", then iso-patch's own step names from its
PROGRESS:<pct>:<step> lines ("Building rootfs", ...). ui.c emits it as
vhdxStep and the status cell shows it instead of the generic
"Building Disk (0%)" that sat there for minutes and looked hung.
Measured from Indonesia against a 24.04 closure (182 .debs): one
connection to archive.ubuntu.com took >10 min; 6 connections to
id.archive.ubuntu.com take 27 s.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Author
|
Second commit: makes the first (uncached) download fast and fixes the label.
Measured from Indonesia against a 24.04 closure (182 debs): one connection to archive.ubuntu.com took >10 min; 6 connections to id.archive.ubuntu.com take 27 s. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Stacked on #123 (it builds on the prefetch output capture added there).
Problem
Every Linux create re-downloads the same three things from scratch, one file at a time, before iso-patch even starts: the repo tarball from GitHub (~80 MB), the apt build-deps closure (~180
.debs, ~120 MB) and the wsl-deps NuGet package. On a normal connection that is 5–7 minutes during which the UI sits at "Building Disk (0%)" and looks hung — the disk build itself takes ~90 s.Change
%ProgramData%\AppSandbox\cache\prefetch\<key>\(repo-<branch>,build-deps-<codename>-<kver>,wsl-deps). A fresh entry is copied into the staging dir instead of downloading. Entries get a.cache-okmarker only after a complete run and expire by age (repo daily, build-deps weekly, wsl-deps monthly), so a moved branch or refreshed-updatespocket is still picked up.APPSANDBOX_NO_PREFETCH_CACHE=1bypasses it; deleting the directory does too..deb(from iso-patch'sclosure = N packagesline).run_iso_patch_ubuntukeeps the bar monotonic through iso-patch's own early 2/4/6% steps.Second and later creates for the same release go from ~7 min of prefetch to a few seconds of copying. No change to what ends up in the guest: the cache holds exactly what the prefetch wrote.
🤖 Generated with Claude Code