Repository navigation
tests: capture and restore named snapshots end to end on real VMs (SL5.1c) - #1500
Conversation
This pull request changes existing testsIt modifies or removes 38 existing test asset(s), listed below. Review each with care: a change to a test can hide a regression that the test caught. See doc/contribute.md#changes-to-existing-tests. Test code
Test data
End-to-end tests
CI test wiring
Relocated unchanged: 0; added: 86. Compared the merge base |
There was a problem hiding this comment.
🟡 Changes recommended
The capture workflow never requests a snapshot, and indeterminate VM spawns can lose recovery context, allowing callers to release snapshot resources while OpenVMM still uses them.
3 open issues
What changed in this PR
This PR moves real-VM snapshot acceptance from raw OpenVMM snapshots to the CLI’s named snapshots, preparing for runtime-adapter removal. The reviewed diff also includes temporary-base changes for named restores, cold-boot acceptance, and public-API examples.
Changes:
- Exercises named capture and restore, snapshot locking, guest isolation, failure handling, and image/upper combinations.
- Moves snapshot scenarios into public acceptance on KVM, MSHV, and WHP, retiring raw-only checks.
- Updates CLI coverage, workflow examples, and documentation for the replacement acceptance paths.
| File | Description |
|---|---|
scripts/test-layout-allowlist.json |
Removes obsolete test-hook allowances. |
scripts/test_nvx_tools.py |
Requires new public acceptance scenarios in CI. |
scripts/nvx_tools/microvm_test_scripts/snapshot-tier.sh.in |
Deletes the raw tier probe. |
scripts/nvx_tools/microvm_test_scripts/snapshot-core.sh |
Deletes the raw snapshot probe. |
scripts/nvx_tools/microvm_test_scripts/run-console-restore.sh |
Deletes the raw console-restore probe. |
scripts/nvx_tools/microvm_shards.json |
Rebalances shards after scenario removals and moves. |
scripts/nvx_tools/adversarial_cases/snapshot-isolation.json |
Updates snapshot-tier campaign coverage descriptions. |
README.md |
Links the acceptance case matrix. |
nvx-rs/tests/vm_lifecycle.rs |
Adds real-VM public-API lifecycle acceptance. |
nvx-rs/tests/cli/validation.rs |
Tests named-restore input refusals. |
nvx-rs/tests/cli/usage.rs |
Updates restore option and help expectations. |
nvx-rs/tests/cli/openvmm.rs |
Removes raw-restore fixtures and helpers. |
nvx-rs/tests/cli/one_shot.rs |
Removes obsolete raw-restore launch cases. |
nvx-rs/tests/cli/dry_run.rs |
Removes unsupported raw-restore dry runs. |
nvx-rs/tests/cli/download.rs |
Checks invalid restores trigger no downloads. |
nvx-rs/tests/cli.rs |
Adapts restore failure coverage to named snapshots. |
nvx-rs/src/host/vm/tests.rs |
Adds a checked-launch substitution helper. |
nvx-rs/src/host/template/mod.rs |
Removes the raw attachment-reader re-export. |
nvx-rs/src/host/snapshot/manifest/tests.rs |
Tests attachments through the retained manifest reader. |
nvx-rs/src/host/snapshot/manifest.rs |
Removes the raw snapshot attachment reader. |
nvx-rs/src/host/restore_driver.rs |
Removes the now-unneeded dead-code allowance. |
nvx-rs/src/host/platform/windows/tests.rs |
Removes obsolete foreground-spawn tests. |
nvx-rs/src/host/platform/windows/spawn.rs |
Deletes unused foreground-spawn helpers. |
nvx-rs/src/host/platform/windows/mod.rs |
Removes the foreground-spawn re-export. |
nvx-rs/src/host/cli/tests.rs |
Checks the assembled run option list. |
nvx-rs/src/host/cli/snapshots/tests.rs |
Covers restore parsing and snapshot-view cleanup. |
nvx-rs/src/host/cli/snapshots/capture/tests.rs |
Adapts tests to capture-only argument parsing. |
nvx-rs/src/host/cli/snapshots/capture.rs |
Moves snapshot subcommand dispatch out of capture. |
nvx-rs/src/host/cli/snapshots.rs |
Adds named restore dispatch and locked view cleanup. |
nvx-rs/src/host/cli/sandbox/state/tests.rs |
Tests complete restore-source records. |
nvx-rs/src/host/cli/sandbox/state.rs |
Records snapshot store and restore workload. |
nvx-rs/src/host/cli/sandbox/one_shot.rs |
Deletes the obsolete direct-launch helper. |
nvx-rs/src/host/cli/sandbox/mod.rs |
Adds managed and one-off restore orchestration. |
nvx-rs/src/host/cli/sandbox/lifecycle/stop.rs |
Removes restored views under the snapshot lock. |
nvx-rs/src/host/cli/sandbox/lifecycle/mod.rs |
Threads snapshot sources through provisioning. |
nvx-rs/src/host/cli/run/tests.rs |
Tests shared restore options and NIC policy. |
nvx-rs/src/host/cli/network.rs |
Removes obsolete direct argument lowering. |
nvx-rs/src/host/cli/mod.rs |
Wires snapshot restore into CLI dispatch. |
nvx-rs/src/guest/init/boot/tests.rs |
Adds compile-only reference-space workflows. |
nvx-rs/examples/host-workflows.rs |
Adds documented host lifecycle examples. |
nvx-rs/examples/guest-workflows.rs |
Adds documented guest workflow examples. |
nvx-rs/Cargo.toml |
Registers feature-gated workflow examples. |
doc/run.md |
Documents named snapshot acceptance and raw OpenVMM usage. |
doc/project-structure.md |
Lists new examples and acceptance tests. |
doc/contribute.md |
Updates feature checks and test guidance. |
doc/ci.md |
Describes replacement acceptance and scenario placement. |
.github/workflows/run-nvx-microvm-tests.yml |
Adds public acceptance scenarios and removes obsolete placement. |
.github/actions/check-nvx-rs/action.yml |
Adds the standalone serde feature check. |
Review effort: Balanced
74e8551 to
ca5457b
Compare
There was a problem hiding this comment.
🟡 Changes recommended
The cleanup path can delete the fixture and its recovery journal even when OpenVMM termination is unconfirmed, leaving a potentially surviving VM without recovery data.
1 open issue
3 resolved since last review
Review effort: Balanced
ca5457b to
e92ad8b
Compare
e92ad8b to
d606f76
Compare
d606f76 to
4093a94
Compare
set_ready_socket_mode opened the restore-ready socket with O_PATH through OpenOptionsExt::custom_flags, which masks out the bits of O_ACCMODE. On musl, O_ACCMODE is 0o10000003 and includes O_PATH, so the musl build of nvx-rs, which CI and the releases run, opened the socket itself, which the kernel refuses with ENXIO, and could restore no named snapshot. Open the socket with nix::fcntl::open, which passes the flags on as they are. On a musl build, ten tests of the listener, in host::restore and host::platform::linux, failed without this and pass with it. CI runs the unit tests only on glibc, whose O_ACCMODE is 0o3; snapshot-core and snapshot-tiers, which run the musl build on Linux, found the failure (#1118, SL5.1c). Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
The two scenarios drove raw OpenVMM snapshots, which the final CLI refuses. They now capture a named snapshot with `nvx-rs snapshot capture`, whose VM nvx-init runs, and restore it with `snapshot restore` and `run --restore-snapshot`, which open it with `Snapshot::open` under the CLI's lock of the snapshot (#1118, SL5.1c). snapshot-core checks the published snapshot; one-off restores whose guests keep the snapshot's uptime, follow the host's clock, and take fresh entropy and machine IDs; a scratch image that the snapshot cannot serve, which the CLI refuses before any VM starts with an error that names the requested scratch; a restore that fails in its guest, which ends its VM, frees the lock and reports guest-exit status 125; and three concurrent restores, which take turns at the lock while a restore that cannot wait fails with sandbox-busy, then run at once with their own shares, uppers and machine IDs. snapshot-tiers restores the platform-tier snapshot into each image format over each upper. Both become public sandbox scenarios, which CI's guest and sandbox jobs run on KVM, MSHV and WHP, and journal the OpenVMM processes of their managed restores for the snapshot-isolation campaign. Their checks of raw snapshots retire with their guest scripts; snapshot-rollback keeps the checks of a released capture request. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
snapshot-core and snapshot-tiers are rewritten on named snapshots, and their rows name the checks that retire with raw snapshots. untiered-network-policy stays on a raw snapshot until a strict snapshot can carry a NIC (SL3.7c, #1114), so a restore's DNS, egress, forwards and listener publication stay covered until then. The adapter's cases that named SL5.1c's smoke tests now name the scenarios, and a Snapshots section maps the smoke tests of #1118 to them. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
4093a94 to
e0dc237
Compare
There was a problem hiding this comment.
🟡 Changes recommended
An interruption during restore startup can block VM cleanup until the CLI subprocess times out; cancellable subprocesses and a regression test for startup interruption are still needed.
1 open issue
2 resolved since last review
Review effort: Balanced
47b9f9c
into
feature/nvx-refactor
restore_private_file_mode, open_plain_dir, and Directory::search open their path only to locate it, with O_PATH, through OpenOptionsExt::custom_flags, which masks out the bits of O_ACCMODE. On musl, O_ACCMODE is 0o10000003 and includes O_PATH, so the musl build of nvx-rs, which CI and the releases ship, opened the file or directory for reading instead, which needs the permission to read it and waits for a writer of a FIFO. A store directory created under a umask that withholds its owner's permission to read it failed with EACCES instead of getting its mode 0700, a lock file that its owner may not read never got its mode back, a directory that grants its owner the right to search it alone could not be searched, and a FIFO in place of a lock file blocked the restore of its mode. Open them with nix::fcntl::open, which passes the flags on as they are, through a helper, open_to_locate, as c19dc62 did for the restore-ready socket (#1500). Nothing changes on glibc, whose O_ACCMODE is 0o3. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
restore_private_file_mode, open_plain_dir, and Directory::search open their path only to locate it, with O_PATH, through OpenOptionsExt::custom_flags, which masks out the bits of O_ACCMODE. On musl, O_ACCMODE is 0o10000003 and includes O_PATH, so the musl build of nvx-rs, which CI and the releases ship, opened the file or directory for reading instead, which needs the permission to read it and waits for a writer of a FIFO. A store directory created under a umask that withholds its owner's permission to read it failed with EACCES instead of getting its mode 0700, a lock file that its owner may not read never got its mode back, a directory that grants its owner the right to search it alone could not be searched, and a FIFO in place of a lock file blocked the restore of its mode. Open them with nix::fcntl::open, which passes the flags on as they are, through a helper, open_to_locate, as c19dc62 did for the restore-ready socket (#1500). Nothing changes on glibc, whose O_ACCMODE is 0o3. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
restore_private_file_mode, open_plain_dir, and Directory::search open their path only to locate it, with O_PATH, through OpenOptionsExt::custom_flags, which masks out the bits of O_ACCMODE. On musl, O_ACCMODE is 0o10000003 and includes O_PATH, so the musl build of nvx-rs, which CI and the releases ship, opened the file or directory for reading instead, which needs the permission to read it and waits for a writer of a FIFO. A store directory created under a umask that withholds its owner's permission to read it failed with EACCES instead of getting its mode 0700, a lock file that its owner may neither read nor write never got its mode back, a directory that grants its owner the right to search it alone could not be searched, and a FIFO in place of a lock file blocked the restore of its mode until a writer came. Open them with nix::fcntl::open, which passes the flags on as they are, through a helper, open_to_locate, as c19dc62 did for the restore-ready socket (#1500). Nothing changes on glibc, whose O_ACCMODE is 0o3. On musl builds of the base, on nvx-kvm-test (Linux 6.6) and nvx-mshv-test (Linux 6.18), two existing tests fail, and pass with this: lock_files_get_back_the_permissions_that_the_umask_cleared, of restore_private_file_mode, and the_payload_of_a_generation_opens_through_no_link, of Directory::search. So do two new tests in host::platform::linux, of open_plain_dir under such a umask and of a FIFO, which waits for a writer until the test's timeout. The four pass on glibc either way. CI runs the unit tests only on glibc. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
restore_private_file_mode and open_plain_dir open their path only to locate it, with O_PATH, through OpenOptionsExt::custom_flags, which masks out the bits of O_ACCMODE. On musl, O_ACCMODE is 0o10000003 and includes O_PATH, so the musl build of nvx-rs, which CI and the releases ship, opened the file or directory for reading instead, which needs the permission to read it and waits for a writer of a FIFO. A store directory created under a umask that withholds its owner's permission to read it failed with EACCES instead of getting its mode 0700, a lock file that its owner may neither read nor write never got its mode back, and a FIFO in place of a lock file blocked the restore of its mode until a writer came. Open them with nix::fcntl::open, which passes the flags on as they are, through a helper, open_to_locate, as c19dc62 did for the restore-ready socket (#1500). Nothing changes on glibc, whose O_ACCMODE is 0o3. On nvx-kvm-test (Linux 6.6) and nvx-mshv-test (Linux 6.18), a musl build without this fails the existing test lock_files_get_back_the_permissions_that_the_umask_cleared, of restore_private_file_mode, and two new tests in host::platform::linux, of open_plain_dir under such a umask and of a FIFO, which waits for a writer until the test's timeout. With this, the three pass on musl; they pass on glibc either way. CI runs the unit tests only on glibc. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
restore_private_file_mode and open_plain_dir open their path only to locate it, with O_PATH, through OpenOptionsExt::custom_flags, which masks out the bits of O_ACCMODE. On musl, O_ACCMODE is 0o10000003 and includes O_PATH, so the musl build of nvx-rs, which CI and the releases ship, opened the file or directory for reading instead, which needs the permission to read it and waits for a writer of a FIFO. A store directory created under a umask that withholds its owner's permission to read it failed with EACCES instead of getting its mode 0700, a lock file that its owner may neither read nor write never got its mode back, and a FIFO in place of a lock file blocked the restore of its mode until a writer came. Open them with nix::fcntl::open, which passes the flags on as they are, through a helper, open_to_locate, as c19dc62 did for the restore-ready socket (#1500). Nothing changes on glibc, whose O_ACCMODE is 0o3. On nvx-kvm-test (Linux 6.6) and nvx-mshv-test (Linux 6.18), a musl build without this fails the existing test lock_files_get_back_the_permissions_that_the_umask_cleared, of restore_private_file_mode, and two new tests in host::platform::linux, of open_plain_dir under such a umask and of a FIFO, which waits for a writer until the test's timeout. With this, the three pass on musl; they pass on glibc either way. CI runs the unit tests only on glibc. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
restore_private_file_mode and open_plain_dir open their path only to locate it, with O_PATH, through OpenOptionsExt::custom_flags, which masks out the bits of O_ACCMODE. On musl, O_ACCMODE is 0o10000003 and includes O_PATH, so the musl build of nvx-rs, which CI and the releases ship, opened the file or directory for reading instead, which needs the permission to read it and waits for a writer of a FIFO. A store directory created under a umask that withholds its owner's permission to read it failed with EACCES instead of getting its mode 0700, a lock file that its owner may neither read nor write never got its mode back, and a FIFO in place of a lock file blocked the restore of its mode until a writer came. Open them with nix::fcntl::open, which passes the flags on as they are, through a helper, open_to_locate, as c19dc62 did for the restore-ready socket (#1500). Nothing changes on glibc, whose O_ACCMODE is 0o3. On nvx-kvm-test (Linux 6.6) and nvx-mshv-test (Linux 6.18), a musl build without this fails the existing test lock_files_get_back_the_permissions_that_the_umask_cleared, of restore_private_file_mode, and two new tests in host::platform::linux, of open_plain_dir under such a umask and of a FIFO, which waits for a writer until the test's timeout. With this, the three pass on musl; they pass on glibc either way. CI runs the unit tests only on glibc. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
restore_private_file_mode and open_plain_dir open their path only to locate it, with O_PATH, through OpenOptionsExt::custom_flags, which masks out the bits of O_ACCMODE. On musl, O_ACCMODE is 0o10000003 and includes O_PATH, so the musl build of nvx-rs, which CI and the releases ship, opened the file or directory for reading instead, which needs the permission to read it and waits for a writer of a FIFO. A store directory created under a umask that withholds its owner's permission to read it failed with EACCES instead of getting its mode 0700, a lock file that its owner may neither read nor write never got its mode back, and a FIFO in place of a lock file blocked the restore of its mode until a writer came. Open them with nix::fcntl::open, which passes the flags on as they are, through a helper, open_to_locate, as c19dc62 did for the restore-ready socket (#1500). Nothing changes on glibc, whose O_ACCMODE is 0o3. On nvx-kvm-test (Linux 6.6) and nvx-mshv-test (Linux 6.18), a musl build without this fails the existing test lock_files_get_back_the_permissions_that_the_umask_cleared, of restore_private_file_mode, and two new tests in host::platform::linux, of open_plain_dir under such a umask and of a FIFO, which waits for a writer until the test's timeout. With this, the three pass on musl; they pass on glibc either way. CI runs the unit tests only on glibc. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
restore_private_file_mode and open_plain_dir open their path only to locate it, with O_PATH, through OpenOptionsExt::custom_flags, which masks out the bits of O_ACCMODE. On musl, O_ACCMODE is 0o10000003 and includes O_PATH, so the musl build of nvx-rs, which CI and the releases ship, opened the file or directory for reading instead, which needs the permission to read it and waits for a writer of a FIFO. A store directory created under a umask that withholds its owner's permission to read it failed with EACCES instead of getting its mode 0700, a lock file that its owner may neither read nor write never got its mode back, and a FIFO in place of a lock file blocked the restore of its mode until a writer came. Open them with nix::fcntl::open, which passes the flags on as they are, through a helper, open_to_locate, as c19dc62 did for the restore-ready socket (#1500). Nothing changes on glibc, whose O_ACCMODE is 0o3. On nvx-kvm-test (Linux 6.6) and nvx-mshv-test (Linux 6.18), a musl build without this fails the existing test lock_files_get_back_the_permissions_that_the_umask_cleared, of restore_private_file_mode, and two new tests in host::platform::linux, of open_plain_dir under such a umask and of a FIFO, which waits for a writer until the test's timeout. With this, the three pass on musl; they pass on glibc either way. CI runs the unit tests only on glibc. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>



Part of #1118 (SL5.1c, "Snapshots work end to end on real VMs"). Parent #1086, umbrella #1076.
This branch is three commits on
feature/nvx-refactor012123bf, which holds everything they need: SL5.1b (#1496), SL3.8a1 (#1486), SL3.8a2 (#1487) and SL3.8b (#1489). The first commit fixes a production defect that the rewritten scenarios found: the musl build ofnvx-rs, which the releases ship, could not restore any named snapshot.What and why
NVX deletes its runtime adapter in SL5.2 (#1119), once the tests that replace it pass. The microVM scenarios
snapshot-coreandsnapshot-tiersdrove raw OpenVMM snapshots: the guest captured itself withnvx-snapshotto a--snapshot-destination, and a raw--restore-snapshotrestored it. The final CLI refuses raw restores (#1489). This PR rewrites both scenarios on the CLI's strict, named snapshots, in the existing real-VM lane,scripts/nvx.py test-microvm. Its one production change is the fix that these scenarios need on musl, described below.nvx-rs snapshot capturecaptures a VM that nvx-init runs.nvx-rs snapshot restoreandnvx-rs run --restore-snapshotopen the snapshot withSnapshot::openand restore it under the CLI's per-snapshot lock, each with an image and an upper of its own. Each restore's workload is a probe that reports:The probe is a script that
/bin/sh -cruns. A restore runs its workload over the control protocol, assandbox execdoes, so the script goes as it is.snapshot-coreCapture. The capture must publish exactly
key.bin,snapshot.jsonandopenvmm/, each file with one link. It must leave no VM directory or OpenVMM process.Repeated restores. After a downtime longer than the capture, two
run --restore-snapshotrestores run: one in RAM as65534:65534, and one over a scratch upper as1:1, each with its own host name. Each guest must show:The restores must report different random bytes, kernel UUIDs, machine IDs and temporary file names.
Failure attribution, as decided on nvx-rs slimming 4.1.1: public-API tests, and smoke tests on real VMs #1118 (A1). This PR checks two failures:
snapshot restoreover a scratch image of half the dormant scratch's length is refused before any VM starts. Theerror[unsupported]message names the lengths of the requested scratch and of the dormant one, which attributes the failure to the request. A failed start keeps its sandbox provisioned, and the refused restore's sandbox must holdconfig.jsonandsandbox.lockalone, with no trace of a launch: no view of the snapshot, OpenVMM log or outcome report. Deprovision then removes it.run --restore-snapshotover a zeroed scratch image of the right length, which the guest can't mount as its upper, fails inside the guest. The VM ends before the workload runs and frees the lock, which the restores that follow take. The run reportserror[exited]: OpenVMM exited during startup: guest-exit status 125.That is all the attribution this PR covers. A2, a follow-up recorded on nvx-rs slimming 4.1.1: public-API tests, and smoke tests on real VMs #1118, covers the rest. nvx-init powers off every failed activation with status 125, so the library classifies the failure as
Unknown, and the CLI never printsRestoreError::attribution. A2 gives nvx-init a status for each class of failure and has the CLI print the restore's attribution.Concurrent restores under the CLI's lock. Three
snapshot restorerestores start at once. Each has its own host name and read-only host share, and the last has a scratch upper. Each workload ends only once the scenario creates areleasefile in its share, which the guest sees live.sandbox-busybefore its workload runs.The host observes this order directly, so the check needs no comparison of guest clocks. The three sandboxes then run at once:
sandbox execwrites in one sandbox's/tmpappears in no other.Snapshot integrity. No restore may change the snapshot, leave a link to its files, or leave an OpenVMM process.
snapshot-tierscaptures a platform-tier snapshot, the one tier thatsnapshot capturecaptures. It restores it into a managed sandbox of each image format over each upper: the Ubuntu EROFS layer, and a GPT disk of its tree, written assandbox-gpt-layerwrites one, each over scratch and RAM. Each root must have its image as its lower directory, over its upper, and an exec must see the same root. Neither image nor the snapshot may change.Networks, as decided on #1118 (N1). A snapshot that
snapshot capturecaptures has no NIC, and a restore must match the snapshot's NIC presence. So no strict snapshot restores with a network today (comment on #1114).untiered-network-policytherefore stays as it is, on a raw snapshot. Its case-matrix row reads "kept until a strict snapshot can carry a NIC (SL3.7c)". Its coverage of a restore's DNS, egress, forwards and listener publication stays real until SL3.7c (#1114) addssnapshot capture --netand rewrites the scenario on a strict snapshot. The oldsnapshot-coreandsnapshot-tierschecked no network:snapshot-tiersgave its raw capture a NIC but checked nothing of it.The musl restore-ready fix, the commit
host: open the restore-ready socket with O_PATH on musl too. CI's Linux guest and sandbox jobs run the static muslnvx-rs. At4093a941, in run 43137188812, the KVM and MSHV jobs both failed atsnapshot-core's first restore:error[io]: cannot use the restore-ready endpoint: No such device or address (os error 6).set_ready_socket_mode(nvx-rs/src/host/platform/linux/endpoint.rs) opened the restore-ready socket withO_PATH | O_NOFOLLOWthrough std'sOpenOptionsExt::custom_flags, which masks out the bits ofO_ACCMODE. On musl,O_ACCMODEis0o10000003and includesO_PATH; on glibc, it is0o3. So the musl build opened the socket itself, which the kernel refuses withENXIO, and no named snapshot could be restored.nix::fcntl::openandO_PATH | O_NOFOLLOW | O_CLOEXEC, which passes the flags on as they are.host::platform::linux::tests::a_restore_ready_socket_lets_its_owner_connect_whatever_the_umaskand ninehost::restore::tests, among thema_different_real_process_cannot_supply_the_event,the_socket_is_owner_only_even_when_the_umask_clears_owner_writeandthe_receiver_fails_closed_without_original_peer_pidfds.O_PATHthroughcustom_flags:restore_private_file_modeandopen_plain_dirinhost/platform/linux/private.rs, andDirHandle::searchinhost/platform/linux/identity.rs. They, and a CI run of the unit tests on musl, are follow-ups.CI. Both scenarios read the Ubuntu layer and the scratch template, so they become public sandbox scenarios (decided on #1118):
microvm_shards.jsonis planned again withplan-microvm-shards.snapshot-coreleaves the extended Ubuntu guest step on KVM, since only Alpine can act as sandbox control.snapshot-tiersleaves the debug-kernel jobs, sincesnapshot captureboots the installed kernel.Adversarial campaign. The managed restores journal their OpenVMM process IDs. So the weekly
snapshot-isolationcampaign keeps its two cases withadversarial_broker.pyunchanged. Thesnapshot-tier-boundarycase's description and coverage now say what the scenario does. The campaign's targets now need the Ubuntu layer and the scratch template, whichnvx-rs downloadinstalls with a release.Docs.
doc/run.mdgains a "Named snapshots" section, anddoc/ci.mdanddoc/usage.mdfollow.untiered-network-policy's cases name SL3.7c. The CI rows of the public acceptance steps and of the extended Ubuntu step say what they run now.Raw-only checks that retire
snapshot-core:nvx-snapshot, and its terminal capture boundary;snapshot-rollbackkeeps only the checks of the source after a released request, which follow the capture that it rolls back (doc/ci.mdnow says so directly);nvx-reseed. Fresh entropy stays checked: each restore's random bytes, kernel UUID and machine ID differ;snapshot-tiers:nvxa library of mechanisms and value types #1076 leaves paired tiers out of scope;--machine microvm, and its second claim;nvx-time statusafter the tier checks.Size
Measured against
feature/nvx-refactor012123bf:endpoint.rs(+11/−6, with 3 lines of comment). The rest of the change is tests. If the workflow's four--scenariolines count as code, as nvx-rs: build every feature set, compile the documented examples, and give every old test a fate (SL5.1a) #1488 counted its CI lines, the total is 12.endpoint.rswith the fix:nvx-rs/src/host/platform/linux/endpoint.rs: +11/−6, the fix.scripts/nvx_tools/microvm_tests.pyholds the two scenarios: +1346/−771 lines, 1043 of them code.check_test_changes.pyclassifies the module as end-to-end tests, but it is a Python script, which nvx-rs slimming workstream: makenvxa library of mechanisms and value types #1076 counts..github/workflows/run-nvx-microvm-tests.yml: +4/−1.scripts/test_*.py;microvm_shards.json;snapshot-isolation.json;snapshot-core.shandsnapshot-tier.sh.in.Commits
host: open the restore-ready socket with O_PATH on musl tootests: rewrite snapshot-core and snapshot-tiers on named snapshotsdoc: give the snapshot scenarios their fates in the case matrixNot in this PR
snapshot capture, anduntiered-network-policyon a strict snapshot: SL3.7c (nvx-rs slimming 3.2.2: the CLI captures and restores named snapshots #1114).O_PATHthroughcustom_flags, and a CI run of the unit tests on musl: follow-ups.Validation
Real VMs, at the head
e0dc2374, onfeature/nvx-refactor012123bf. The runs used the guest artifacts of CI run 43131339763, the push of14ca2671, whose guest code is the tip's, and the OpenVMM of CI run 43075697333, built from the sameopenvmmpin,14dc4116. The artifacts were checked by their SHA-256 digests. On Linux, the CLI is the static musl release build, run as CI runs it, withTMPDIRunset.snapshot-coresnapshot-tiersCI run 43141805757, at
e0dc2374: 34 jobs passed and 9 were skipped. Among them, the guest and sandbox jobs of KVM, MSHV and WHP ran the public step, with the musl CLI on Linux.At
4093a941, before the fix, a glibc CLI passed the same runs on KVM and MSHV, which is why the defect stayed hidden on the hosts. Before the rebase, on its temporary base, the branch passed the same runs on all three backends at74e85514, and the snapshot scenarios on WHP atd606f767. There, a capture that timed out under--timeout 1left no fixture and no OpenVMM process. The rebase changed one thing in the scenarios: the probe now goes to the restore's shell as it is, since a restore's workload now travels over the control protocol and may contain whitespace (#1487).Rust, on nvx-kvm-test at
e0dc2374:cargo test --locked --lib --target x86_64-unknown-linux-musl -- host::platform::linux::tests::a_restore_ready_socket host::restore::testscargo clippy --locked --all-targets --all-features -- -D warnings, for the host's glibc target and forx86_64-unknown-linux-muslcargo fmt --all --checkCI's
nvx-rsjobs ran the rest of the Rust checks, on Ubuntu with glibc and on Windows, and passed in that run.Gates, from this branch's
check-qualityandvalidate-nvxactions, aslocal_gates.py --filesselects them, ate0dc2374:ruff checkandruff format --checkofscripts .github/speculapyright --pythonplatform Linuxand--pythonplatform Windowscheck_markdown_links.py,check_test_layout.pycheck_test_layout.pypassedtest_microvm_teststest_nvx_toolsCiConfigurationTests, 94 tests, OK (6 skipped); CI'sNVX CLIjobs ran the whole suite on Linux and Windows, and passedtest_adversarialnvx.py test-microvm --helpLeft to CI:
Changes to existing tests
python3 scripts/check_test_changes.py --base origin/feature/nvx-refactorlists 38 changes to existing tests and 85 added items, so this PR has thetests-modifiedlabel:Removed with the raw scenarios (each retired check is listed above):
snapshot-core.shandsnapshot-tier.sh.in;_snapshot_tier_kinds,_snapshot_tier_script,_snapshot_storage_policy,_run_snapshot_tierand_parse_marker_pair, and the oldrun_snapshot_coreandrun_snapshot_tiers, which the new scenarios replace;test_snapshot_core_script_handles_no_clocksource;test_snapshot_core_checks_that_restored_processes_cannot_reach_the_ports;test_snapshot_core_reads_the_entropy_that_nvx_time_kept;test_snapshot_core_waits_for_no_destination_marker_line_before_exit;test_snapshot_tier_scripts_preserve_tier_specific_policy;test_restored_tier_guests_report_their_restore_checks_before_exiting;test_snapshot_tier_entry_points_reject_unsupported_tiers;test_snapshot_tier_runner_dispatches_all_tiers;test_snapshot_storage_policy_selects_generation_and_materialization.PublicSnapshotTestsreplaces them with nine tests, which run both scenarios against a fake of the CLI, with its lock. They inject 26 regressions that the scenarios must detect, among them a restore that launches a VM before it refuses a short scratch. They also run two failed captures. In one, cleanup ends the capture's VM through the capture's launch journal. In the other, the VM survives cleanup, after which the fixture must stay for recovery.test_snapshot_marker_parsers_require_single_well_formed_valuesno longer checks_parse_marker_pair, which leaves withsnapshot-core's markers.test_every_tcp_console_is_monitored_and_cold_boot_shells_are_queriedno longer counts the rawsnapshot-tiers' three TCP consoles (its capture, its restore and its gate-timeout restore) or its capture's time ABI monitor.test_debug_kernel_runs_the_same_host_restore_scenarios_on_vmlinux_debugdropssnapshot-tiersfrom the debug-kernel scenarios.CiConfigurationTests.test_ci_runs_the_public_sandbox_acceptance_on_every_backendalso requires--scenario snapshot-coreand--scenario snapshot-tiersin both public acceptance steps.Scenario lists:
SANDBOX_CONTROL_SCENARIOSgainssnapshot-core;PUBLIC_SANDBOX_SCENARIOSgains both scenarios;DEBUG_KERNEL_SCENARIOSlosessnapshot-tiers;_run_scenariosdispatches the new scenarios;GptLayerAcceptance.write_disknow callswrite_gpt_layer, whichsnapshot-tiersshares, unchanged.CI wiring: the extended Ubuntu step drops
--scenario snapshot-core, andmicrovm_shards.jsondrops both scenarios from each backend's shards.Test data:
snapshot-isolation.json'ssnapshot-tier-boundarycase has a new description and coverage.