Skip to content

feat(qemu): back the guest boot image with an overlay by default - #215

Merged
safl merged 2 commits into
mainfrom
qemu-boot-overlay
Oct 23, 2026
Merged

safl merged 2 commits into
mainfrom
qemu-boot-overlay

Conversation

@safl

@safl safl commented Oct 23, 2026 •

Copy link
Copy Markdown
Collaborator

Makes the guest boot image a qcow2 overlay backed by the staged disk image, instead of a copy of it. System-imaging is the store of images, and a guest now references one, holding only what it writes. That saves the copy, over a minute for an 11.7 GiB image on a CI runner, and lets several guests share one image.

Worth a look: this is now the default, so every task using qemu.guest_initialize gets an overlay; overlay: false restores the copy. The image must stay unchanged while a guest uses it. diskimage_from_cloudimage asks for the copy explicitly, because it turns boot.img into the disk image afterwards. nosi's own diskimage_build.py also calls Guest.initialize() and will get an overlay, which is fine there: it resizes boot.img and finishes with qemu-img convert -c, which reads through the backing file.

Verification: tests/qemu/test_guest_initialize.py covers the default overlay, the copy, an absolute backing path given a relative disk path (qemu would read a relative one from the overlay's directory), and a real qcow2 overlay's backing file and size; the Linux unittest job now installs qemu-utils so the last one runs there, while it skips on macOS. This repository's example jobs boot guests from overlays (qemu.guest_x86_64, qemu.guest_aarch64) and build disk images through diskimage_from_cloudimage (core.get_put, system_imaging.debian). On a physical host, xNVMe's full verify flow for its ROCm guest booted from the overlay, built xNVMe and SPDK in it, and passed 62 tests with 103 skipped, the same as with a copy; the overlay held 1.15 GiB of writes against an 11.7 GiB copy.

@coveralls

coveralls commented Oct 23, 2026 •

Copy link
Copy Markdown

Coverage Report for CI Build 39980601444

Coverage decreased (-0.001%) to 71.672%

Details

  • Coverage decreased (-0.001%) from the base build.
  • Patch coverage: 3 uncovered changes across 2 files (12 of 15 lines covered, 80.0%).
  • No coverage regressions found.

Uncovered Changes

File Changed Covered %
src/cijoe/qemu/wrapper.py 8 6 75.0%
src/cijoe/qemu/scripts/guest_initialize.py 6 5 83.33%
Total (3 files) 15 12 80.0%

Coverage Regressions

No coverage regressions found.


Coverage Stats

Coverage Status
Relevant Lines: 2280
Covered Lines: 1708
Line Coverage: 74.91%
Relevant Branches: 830
Covered Branches: 521
Branch Coverage: 62.77%
Branches in Coverage %: Yes
Coverage Strength: 0.75 hits per line

💛 - Coveralls

@safl
safl force-pushed the qemu-boot-overlay branch 2 times, most recently from 6e3d872 to 47491fc Compare October 23, 2026 10:05
@safl
safl requested a review from naddinadja October 23, 2026 10:17
@safl
safl force-pushed the qemu-boot-overlay branch from 47491fc to 4311383 Compare October 23, 2026 10:26

@naddinadja naddinadja left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Single question, but otherwise it looks good! :)

Comment thread tests/qemu/test_guest_initialize.py Outdated
Comment on lines +15 to +21
class FakeConfig:
def __init__(self, options):
self.options = options


class FakeCijoe:
"""Records local commands; runs them for real when 'execute' is set"""

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These "FakeConfig" and "FakeCijoe" - is that not something we've had use for in other tests? Sounds like either (a) something other tests could use, or (b) something we've solved in other ways in the existing tests?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good catch, (b): tests/core/test_transport_ssh.py in #214 uses a real Cijoe built from a real Config and fakes only the boundary, so this test now does the same, patching only run_local to record the commands, and the two fakes are gone (3dc33ea). tests/system_imaging/test_diskimage_from_oras.py still carries its own FakeCijoe; folding that one in is left for a separate change.

@safl
safl force-pushed the qemu-boot-overlay branch from 4311383 to 3dc33ea Compare October 23, 2026 11:01

@naddinadja naddinadja left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cool! :)

@safl

safl commented Oct 23, 2026

Copy link
Copy Markdown
Collaborator Author

xNVMe exercises this together with #214 and #216 in xnvme/xnvme#825, which pins cijoe to the preview branch ci-preview-overlay-ssh (01aedad). Its verify jobs boot every guest on an overlay boot image and are green across Debian and FreeBSD guests. Together with #214 the guest provision-and-test step takes 2734 s less than on xNVMe main across 13 jobs, a mean of 210 s per job; most of that is the kept SSH connection, and the overlay accounts for a smaller fixed saving per boot. The per-job table is in xnvme/xnvme#825.

safl added 2 commits October 23, 2026 17:41
guest_initialize copied the staged disk image to the guest's boot.img.
For a large image that copy is a real cost: the 11.7 GiB qcow2 of a ROCm
guest takes over a minute on a CI runner, which then throws the guest
away, and every further guest from the same image pays it again, in
time and in disk. boot.img is now a qcow2 overlay backed by the staged
image, which takes no time, and several guests share one image, each
holding only what it writes. That matches the split already there:
system-imaging is the store of images, and a guest references one.

The image must stay unchanged while a guest uses it. 'overlay: false'
restores the copy, and diskimage_from_cloudimage asks for it, since it
turns boot.img into the disk image afterwards.

Assisted-by: Claude Code:claude-opus-5-5
Signed-off-by: Simon A. F. Lund <os@safl.dk>
The report options change landed before the 0.9.61 section existed, so
its entry is added now that the section is there.

Assisted-by: Claude Code:claude-opus-5-5
Signed-off-by: Simon A. F. Lund <os@safl.dk>
@safl
safl force-pushed the qemu-boot-overlay branch from 3dc33ea to 20c04eb Compare October 23, 2026 15:42
@safl
safl merged commit e7587b3 into main Oct 23, 2026
30 checks passed
@safl safl mentioned this pull request Oct 23, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants