Repository navigation
host: drive a restore over NVXC for blocking callers (SL4.3) - #1476
Merged
Pedro Henrique Penna (ppenna) merged 1 commit intoNov 11, 2026
Merged
Pedro Henrique Penna (ppenna) merged 1 commit into
Pedro Henrique Penna (ppenna) merged 1 commit into
Conversation
Contributor
This pull request changes existing testsIt modifies or removes 3 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 policy
Relocated unchanged: 0; added: 39. Compared the merge base |
Contributor
There was a problem hiding this comment.
🟢 Approval recommended
No active review issues block approval of the private, CLI-gated blocking restore driver.
No open issues 🎉
What changed in this PR
Adds the private, CLI-gated blocking restore driver for SL4.3, connecting the existing restore state machine to NVX control sessions. This prepares the mechanism for later snapshot CLI integration without changing the public API or taking ownership of VM cleanup.
Changes:
- Drives restore through verified peers, activation, mappings and workload Start, with bounded retries and deadlines.
- Adds cancellation and VM-exit monitoring, backed by Linux socket shutdown and Windows pipe-transfer cancellation.
- Adds driver and activation tests, documentation and a temporary test-layout allowance.
| File | Description |
|---|---|
scripts/test-layout-allowlist.json |
Allows the driver’s temporary unused-code hook. |
nvx-rs/src/protocol/mod.rs |
Re-exports activation helpers for CLI builds. |
nvx-rs/src/protocol/app.rs |
Updates unused-code attributes for CLI activation use. |
nvx-rs/src/host/vm/tests.rs |
Adds a launched-VM stand-in helper. |
nvx-rs/src/host/session/tests.rs |
Tests activation requests and Ready validation. |
nvx-rs/src/host/session.rs |
Adds the control-session activation exchange. |
nvx-rs/src/host/restore_driver/tests.rs |
Tests retries, peer checks, budgets, interruptions and failures. |
nvx-rs/src/host/restore_driver.rs |
Implements bounded blocking restore orchestration. |
nvx-rs/src/host/platform/windows/mod.rs |
Exposes the Windows transfer-interruption helper internally. |
nvx-rs/src/host/platform/windows/endpoint.rs |
Cancels pending pipe transfers with CancelIoEx. |
nvx-rs/src/host/platform/linux/mod.rs |
Exposes the Linux transfer-interruption helper internally. |
nvx-rs/src/host/platform/linux/endpoint.rs |
Interrupts socket transfers through shutdown. |
nvx-rs/src/host/mod.rs |
Registers and documents the private CLI-gated driver. |
nvx-rs/README.md |
Documents blocking restore guarantees and budgets. |
Review effort: Balanced
NVX's blocking CLI callers need one bounded operation that restores a launched VM over NVXC and returns a usable control session. The private restore_driver module, beside host::session and gated by the cli feature, drives RestoreMachine to the guest's Ready, then sends the mapping table and the workload's Start, and returns the live ControlSession. restore() checks that the restore-ready client and the control server are the launched VM's held process, sends the same activate message, the activation record and the workload's identity, in each session, replaces a lost session in at most three sessions, and allows 60 s to Ready and 30 s more for the mapping table and Start. Every pending accept, read and write races the step's deadline, the caller's cancellation and the VM's verified exit: the restore-ready endpoint and the control endpoint are waited for in 50 ms slices, and a watcher thread ends a session's pending transfers through a duplicate of its connection, with the new crate-private platform::interrupt_transfers, a shutdown on Linux and CancelIoEx on Windows. ControlRestoreError tells a failure of the machine from one of the mapping table or of Start, and a failure leaves the VM's process to the caller. ControlSession::activate sends the activate message and returns what the guest's Ready reports. The driver is a child of host of its own, above vm, so that host::session stays below vm and the children of host stay acyclic. Reworked from the first implementation on esaurez/slim-3.2.1-sl4.3-private-20261108 (b30be68), whose driver loop, failure classification and Python peer tests it keeps: the driver moved out of host::session, which spares moving vm's capability generator below it, and a watcher thread replaces the restore checkpoints that the first implementation added to the platform transports. Tests: a Python stand-in for OpenVMM and its guest, spawned as a VM is, so that it inherits no other test's handles, checks the reconnection with the same activate message and the live session that returns, the third lost session and a malformed Ready, the refusal of an unverified restore-ready client or control server, the 60 s and 30 s budgets, cancellation and the VM's exit at each pending accept and read, a pending write ended by each, distinct machine, MAPS and Start failures, and a cold record or a root workload refused before any exchange. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Pedro Henrique Penna (ppenna)
force-pushed
the
agents/slim-sl4-3-restore-driver
branch
from
November 11, 2026 08:24
8ba185a to
8a76176
Compare
Pedro Henrique Penna (ppenna)
merged commit Nov 11, 2026
35cedfd
into
feature/nvx-refactor
48 checks passed
Pedro Henrique Penna (ppenna)
deleted the
agents/slim-sl4-3-restore-driver
branch
November 11, 2026 08:45
This was referenced Nov 11, 2026
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.
Part of #1113 (SL4.3, "A blocking caller can drive a restore"). Parent #1084, umbrella #1076.
What and why
NVX's blocking CLI callers, first SL3.8a's
snapshot restore(#1114), need one bounded operation that drives a launched restore over NVXC to a usable control session. The pieces exist: SL2.16 (#1470) launches a restore with its bound restore-ready listener, SL2.18a's I/O-freeRestoreMachineorders the activation to Ready, SL2.18b (#1354) reports the failure facts, and SL4.2 (#1331) added the activate message. This PR adds the driver that runs them:host::restore_driver(featurecli) hasrestore(launched, record, workload, maps, cancel) -> Result<ControlSession, ControlRestoreError>. It drivesRestoreMachinethrough OpenVMM's restore-ready event and the control sessions to the guest's Ready, then sends the mapping table and the workload's Start (APP_EXECwith the caller's request ID), and returns the liveControlSession, in which the workload's events arrive.ReadyListener::receiveandsession::connect's peer checks); anything else gets no activation.AtomicBool) and the VM's verified exit. The restore-ready endpoint and the control endpoint are waited for in slices of at most 50 ms, between which the driver checks both. While a session transfers, a scoped watcher thread checks them and ends the session's pending transfers through a duplicate of its connection, with the new crate-privateplatform::interrupt_transfers:shutdown(SHUT_RDWR)on Linux andCancelIoExon Windows.ControlRestoreErrortells a failure of the machine (Machine(RestoreError), with its phase, evidence and source) from one of the mapping table (Maps) or of Start (Start). A failure stops nothing: the VM's process, outputs and restore-ready listener stay the caller's.ControlSession::activate(featurecli) sends the activate message and returns the activation that the guest's Ready reports.APP_ACTIVATEandencode_activate_payloadare now used by theclibuild, so theirexpect(dead_code)hooks no longer apply to it (see the test changes below), andprotocolre-exports them for it.restorebullet ofhost's module docs and thenvx::host::restoresection of the README describe the driver.Layering
The driver is a child of
hostof its own, abovevm, rather than part ofhost::session: the driver needsvm::Launched, andvmalready depends onsessionthroughinstance, so a driver insessionwould make the children ofhostcyclic, whichtests/host_modules.rsrefuses.host::sessionstays belowvm.The
expect(dead_code)hook that SL3.8a endsNothing calls
restoreoutside its tests yet, so it carries#[cfg_attr(not(test), expect(dead_code, reason = "SL3.8a'ssnapshot restorerestores sandboxes through it"))], with its seam entry"nvx-rs/src/host/restore_driver.rs": 1inscripts/test-layout-allowlist.json. SL3.8a (#1114) calls it fromsnapshot restoreand then removes the hook and, withscripts/check_test_layout.py --tighten, the entry. The functions that onlyrestorereaches need no hook of their own.History: the first implementation, reworked into one commit
Enrique Saurez (@esaurez)'s first implementation is
esaurez/slim-3.2.1-sl4.3-private-20261108(b30be688, checkpoint on #1113), four commits:c2a199d8(drive bounded blocking restores over NVXC),bc389dae(document blocking restore invariants),b7b17a68(preserve completed pipe transfers during restore races) andb30be688(break the restore session dependency cycle). It measured 565 core lines in 8 counted files, over the limit of 5. This PR reworks it into one commit, with Enrique Saurez (@esaurez) as its author, because the later commits fix and restructure the first, and the rework replaces two of their approaches rather than adding to them:host::sessionintohost::restore_driver, which spares movingvm's capability generator belowsessionintoplatform(b30be688's break of the cycle).platform::interrupt_transfersreplace the restore checkpoints thatc2a199d8andb7b17a68added to the Linux and Windows transports, with their platform tests.restore_driver/tests.rs. The stand-in is now spawned as a VM is (vm::spawnwith its handle allowlist), so on Windows it inherits no other test's handles.The commit message records the same history.
Size
Measured against
feature/nvx-refactor821de193: 432 core lines (stop 600) in 5 counted files:host/restore_driver.rs394,host/session.rs19,host/platform/windows/endpoint.rs10,host/platform/linux/endpoint.rs7 andhost/mod.rs2.protocol/app.rs,protocol/mod.rs,host/platform/linux/mod.rsandhost/platform/windows/mod.rschange only attributes and imports (29 lines).Stack
The branch was built on SL2.16's head
9bc9d403before #1470 folded its fixups, and rebased withgit rebase --onto origin/feature/nvx-refactor 9bc9d403onto the merged8b775211, whose SL2.16 differs from9bc9d403only in docs and the example. It was then rebased onto821de193, after #1460 (SL3.5b) merged; that touches only the CLI's sandbox lifecycle and spawn helpers that the driver does not use, and the allowlist's neighboring lines. Neither rebase changed this commit's added or removed lines (git range-diff).Not in this PR
The caller (
snapshot restore, SL3.8a); any public API (everything is crate-private); stopping or cleaning up the VM after a failure, which stays the caller's; the per-snapshot lock, which the caller holds; retries beyond the three sessions.Validation
On the head
8a761767(on821de193), on the local Windows workstation, with this branch'scheck-nvx-rsandcheck-qualitycommands (innvx-rs/,NVX_BUNDLE=skip):cargo fmt --all --checkcargo clippy --lockedwith-D warnings:--all-targets --all-features,--lib,-p nvx --lib --no-default-features,--lib --bins --features cli,--lib --bins --no-default-features --features testing--target x86_64-unknown-linux-musl:--all-targets --all-features,--lib --bins --features cli,-p nvx --lib --no-default-featuresinterrupt_transfers)cargo test --locked --all-features --lib -- host::restore_driver host::session::tests::activatecargo test --locked --all-features --test host_modulespython scripts\check_test_layout.pypython scripts\check_test_changes.py --base origin/feature/nvx-refactorpython scripts\public_api.pyEarlier, on
40c86afa, the same patch on9bc9d403:cargo check,cargo doc --no-deps --all-features, the doctests, the runtime adapter's Clippy, the Markdown links andcargo test --all-featurespassed, except three timing-sensitive tests outside this change:a_capture_ack_and_successful_output_without_timely_exit_are_stopped_but_never_finishedandtemplate_capture::vms_that_never_end_are_torn_down_at_the_deadlinefail the same way at the base5947e4e8on this loaded workstation, andchildren_inherit_only_their_standard_handlesis flaky there and passes alone.scripts/public_api.pyand the driver's tests passed.cargo test --all-featuresfailed only the 28guest::tests that fail identically at the base on that host (a process-groupkillreturnsEINVALthere).No microVM scenario was run: nothing reaches the driver outside its tests until SL3.8a, and no runtime path changes. CI run 42983982090 of the previous head
8ba185aa(the same patch on8b775211) passed in full. Left to CI: the full test suites on Linux and Windows, the microVM and runtime-adapter suites on KVM, MSHV and WHP, and the benchmarks.Changes to existing tests (
tests-modified)python3 scripts/check_test_changes.py --base origin/feature/nvx-refactorlists 3 changes to existing tests, and 39 added items:APP_ACTIVATE's test hook (protocol/app.rs): itscfg_attr(not(any(test, ...)), expect(dead_code, ...))addsfeature = "cli", since the driver sends the message in theclibuild; the reason becomes "only the CLI's restore driver sends it, and only nvx-init reads it".encode_activate_payload's test hook (protocol/app.rs):not(test)becomesnot(any(test, feature = "cli")), since the driver encodes the payload in theclibuild; the reason becomes "only the CLI's restore driver encodes activation requests"."nvx-rs/src/host/restore_driver.rs": 1for theexpect(dead_code)hook onrestore, which SL3.8a removes.No existing test is rewritten or removed: the tests of the session's capture, the activate payload's round trips, the restore machine, the platform endpoints and
vmare unchanged. The added items are the driver's 9 tests and their Python stand-in,ControlSession::activate's 2 tests and the test helperLaunched::stand_ininhost::vm::tests.