Skip to content

host: finish exited captures into snapshot entries - #1455

Merged
Pedro Henrique Penna (ppenna) merged 3 commits into
feature/nvx-refactorfrom
esaurez/issue1102-sl214-20261110-b718df7e
Nov 11, 2026
Merged

Pedro Henrique Penna (ppenna) merged 3 commits into
feature/nvx-refactorfrom
esaurez/issue1102-sl214-20261110-b718df7e

Conversation

@esaurez

@esaurez Enrique Saurez (esaurez) commented Nov 10, 2026 •

Copy link
Copy Markdown
Contributor

Part of #1102, SL2.14, in #1076.

What and why

SL2.13 (#1454) prepares a capture launch; this pull request finishes the exited capture into the entries of a snapshot.

Capture finishing

  • Add host::snapshot::finish_capture(&VmDir, &CaptureContext, &Exited) -> Result<CapturedSnapshot> and CapturedSnapshot { pub key: SnapshotKey }.
  • Share the existing template capture's successful-outcome, strict manifest, private regular artifact and recorded-length checks. Derive the key from the opaque checked capture context.
  • Atomically write private key.bin and informational snapshot.json beside openvmm/. Leave logs, outcomes and unrelated VM entries untouched. Correctable validation failures and partial metadata writes can be retried; the caller alone publishes the three snapshot entries into its private immutable directory.
  • Expose the complete per-snapshot SnapshotKey::time. Preserve KeyIdentity's unchanged compatibility prefix: different capture times have different persisted bytes but the same compatibility identity. Opening compares the complete key time against the strict manifest.

No store, publication rename, journal, general transaction, version negotiation, backward decoder or manufactured exit proof. Rates contribute to compatibility; capture anchors, host/boot identities, lineage and cut-to-anchor interval are persisted but excluded from that identity. The Fresh encoding changes in place without a version bump.

VM directory ownership

Snapshot finishing needs the VM directory and its outcome file, but host::vm imports host::snapshot::{CaptureContext, Snapshot}, so importing vm::{OUTCOME, VmDir} from snapshot/capture.rs made host_modules::the_children_of_host_depend_on_one_another_without_cycles fail. The last commit moves VmDir, VmOutputs, private-directory creation, the output and endpoint names, and their privacy and error helpers, unchanged, into private host::vm_directory, which depends only on host path and platform primitives. host::vm re-exports VmDir, VmOutputs and create_private_dir at their existing public paths, so the public API gains only the snapshot items above, and TemplateKey::time through the existing alias. Launch, capture and process logic stay in host::vm; its three accesses to the private path field use the existing path() accessor.

Rebase onto feature/nvx-refactor

The branch is rebased onto feature/nvx-refactor at 34d5c66 as three linear commits, replacing the previous head c6de1d8:

Commit Previously
4de76db host: finish exited captures into snapshot entries b2bf182
f254457 host: retain capture time without changing compatibility identity 1148a74
aa319d6 host: share VM directory ownership below snapshot and launch a964f2b

The SL2.13 commits that the branch carried landed in the base as 8804b95 through e07a03b and are dropped, as are the two merge commits. Messages and authorship are unchanged. The final tree equals the three-way merge of c6de1d8 with 34d5c66, except in nvx-rs/README.md's module table, which keeps both the base's nvx::host::vm row and this pull request's nvx::host::snapshot row. The other conflict, in the imports of host/vm.rs, keeps the base's host::network import and this pull request's narrowed paths::absolute. The net diff against the base is unchanged: 21 files, 1613 insertions and 745 deletions.

As before the rebase, the first two commits compile but fail the host-module acyclicity test, 21 passed and 1 failed, until the third commit fixes it.

Size

The owned layer is seven production files, all under nvx-rs/src/: host/mod.rs, host/snapshot.rs, host/snapshot/capture.rs, host/snapshot/key.rs, host/template/store/capture.rs, host/vm.rs and new host/vm_directory.rs. As counted for c6de1d8, it adds or changes 439 and deletes 242 physical nonblank code lines, excluding comments, documentation and standalone test files and counting moved code as added: below 600. The rebase changes none of its hunks. Registering the shared owner, keeping its facade and removing the reverse dependency must be one compilable change, the narrow seven-file case that #1076 permits.

Validation

At aa319d6, on a Windows x64 host without a hypervisor, with Rust 1.95.0 unless noted and NVX_BUNDLE=skip as in CI (scripts/local_gates.py is not on this base, so the commands come from check-nvx-rs and check-quality):

Check Result
python scripts\nvx.py verify Passed
cargo fmt --all --check Passed
cargo clippy --locked ... -- -D warnings, all five check-nvx-rs configurations Passed
cargo test --locked --all-features Passed; library 1400 passed and 12 ignored, integration tests passed
cargo test --locked Passed; library 1205 passed and 10 ignored
cargo build --locked --lib --no-default-features and cargo test --locked --lib --no-default-features Passed; 283 passed
cargo doc --locked --no-deps --all-features with RUSTDOCFLAGS=-D warnings Passed
python scripts\public_api.py, Linux and Windows snapshots Passed
cargo +1.89 check --locked --all-targets --all-features Passed
cargo check --locked --all-targets --all-features --target aarch64-apple-darwin Passed; its 15 test-only warnings are in files that this pull request does not change
Runtime adapter, protocol-only and host configurations: format, Clippy, build, test, documentation and Rust 1.89 Passed; the tests that boot a VM are ignored
cargo test --locked --all-features --test host_modules Passed, 22 tests
cargo check --locked --all-targets --all-features at 4de76db and f254457 Passed
python scripts\check_test_layout.py and python scripts\check_markdown_links.py Passed

CI: run 42938629920 on aa319d6 passed: 34 jobs succeeded, including Linux and Windows check-nvx-rs, the NVX CLI on both, and the KVM, MSHV and WHP microVM, platform and package jobs, which were not run locally. The 9 skipped jobs publish the development release, package or publish the crate, record or persist performance results, handle merge groups, run the debug kernel on KVM and WHP, or check an OpenVMM pin that this pull request leaves unchanged.

Changes to existing tests

python scripts\check_test_changes.py --base 34d5c669 reports four changes, 12 relocated unchanged and 34 added, as before the rebase. No existing test is retired or weakened.

  • The imports of host::template::store::tests obtain the shared artifact inventory from host::snapshot.
  • keys_read_back_from_their_canonical_encoding hashes the specified compatibility prefix rather than the longer persisted bytes.
  • keys_of_machines_that_no_manifest_describes_are_refused still corrupts the invariant ordering, locating it before the time suffix.
  • snapshot-key-v1.txt appends time fields. Compatibility identities and CLASS vectors remain unchanged; truncation and trailing-byte cases retain their conditions. Its bytes were constructed independently of the Rust codec.

The 12 relocations are these ten tests and their is_fresh_pipe and vm_dir helpers, which move unchanged, with their platform attributes and assertions, from host/vm/tests.rs to host/vm_directory/tests.rs. Only the test-only vm_dir helper gains host-scoped visibility, for the launch tests that still use it.

  • a_vm_directory_is_created_with_mode_700_for_the_current_user_whatever_the_umask
  • an_existing_directory_that_is_not_private_is_refused_and_left_unchanged
  • trailing_separators_and_current_directory_suffixes_do_not_hide_a_symbolic_link
  • a_vm_directory_is_created_owner_only_and_protected_under_a_permissive_parent
  • existing_vm_directories_that_grant_others_or_inherit_are_refused_and_left_unchanged
  • a_vm_directory_that_cannot_be_opened_or_created_fails_with_the_hosts_error
  • outputs_name_the_vm_directorys_files_and_endpoints
  • the_endpoints_of_a_vm_directory_that_is_not_unicode_are_refused
  • a_restore_ready_endpoint_is_the_reserved_socket_or_a_fresh_pipe
  • creating_and_opening_a_vm_directory_writes_no_capability_file_or_output

The validation receipts of earlier heads, through c6de1d8, remain in this description's edit history.

@esaurez Enrique Saurez (esaurez) added tests-modified Changes existing tests, test data, or test wiring feat-nvx-refactor labels Nov 10, 2026
@github-actions

github-actions Bot commented Nov 10, 2026 •

Copy link
Copy Markdown
Contributor

This pull request changes existing tests

It modifies or removes 4 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

Change What Before After
modified imports the imports of host::template::store::tests nvx-rs/src/host/template/store/tests.rs:5 nvx-rs/src/host/template/store/tests.rs:5
modified test fn keys_read_back_from_their_canonical_encoding in host::snapshot::key::tests nvx-rs/src/host/snapshot/key/tests.rs:661 nvx-rs/src/host/snapshot/key/tests.rs:720
modified test fn keys_of_machines_that_no_manifest_describes_are_refused in host::snapshot::key::tests nvx-rs/src/host/snapshot/key/tests.rs:800 nvx-rs/src/host/snapshot/key/tests.rs:859

Test data

Change What Before After
modified file nvx-rs/tests/vectors/snapshot-key-v1.txt nvx-rs/tests/vectors/snapshot-key-v1.txt nvx-rs/tests/vectors/snapshot-key-v1.txt

Relocated unchanged: 12; added: 34. Compared the merge base 34d5c669ab1f with aa319d684e98.

Copilot AI 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.

🟢 Approval recommended

No active review issues block the capture-finishing API changes.

No open issues 🎉

What changed in this PR

Adds post-exit capture finishing to NVX’s snapshot API for #1102, building on #1454’s capture preparation. The library validates capture output and writes snapshot metadata; callers retain responsibility for publication and storage.

Changes:

  • Add finish_capture and CapturedSnapshot, sharing existing validation and supporting retries after partial metadata writes.
  • Persist the complete capture-time contract in snapshot keys while preserving compatibility identities.
  • Add capture-finishing and time-consistency tests, update encoding vectors, and document the public API.
File Description
nvx-rs/​tests/​vectors/​snapshot-key-v1.txt Append capture-time fields while preserving identity values.
nvx-rs/​tests/​vectors/​README.md Explain persisted time fields and compatibility hashing.
nvx-rs/​src/​host/​vm.rs Share the outcome filename with snapshot finishing.
nvx-rs/​src/​host/​template/​store/​tests.rs Import the shared snapshot artifact inventory.
nvx-rs/​src/​host/​template/​store/​capture/​tests.rs Keep fixture filenames local and use shared constants.
nvx-rs/​src/​host/​template/​store/​capture.rs Reuse extracted outcome and artifact validation.
nvx-rs/​src/​host/​snapshot/​tests.rs Test rejection of key/manifest capture-time mismatches.
nvx-rs/​src/​host/​snapshot/​manifest.rs Clarify time-contract identity semantics in documentation.
nvx-rs/​src/​host/​snapshot/​key/​tests.rs Test full time round trips and unchanged compatibility identities.
nvx-rs/​src/​host/​snapshot/​key.rs Derive keys from capture contexts and encode complete time contracts.
nvx-rs/​src/​host/​snapshot/​capture/​tests.rs Cover validation, privacy, retries, and caller-managed publication.
nvx-rs/​src/​host/​snapshot/​capture.rs Implement capture finishing and shared validation helpers.
nvx-rs/​src/​host/​snapshot/​canonical.rs Clarify which encoding bytes contribute to identities.
nvx-rs/​src/​host/​snapshot.rs Export finishing APIs and share strict artifact checks.
nvx-rs/​README.md Document finishing, publication responsibilities, and time semantics.
nvx-rs/​public-api/​windows.txt Record the new Windows-visible public APIs.
nvx-rs/​public-api/​linux.txt Record the new Linux-visible public APIs.

Review effort: Balanced

@esaurez
Enrique Saurez (esaurez) marked this pull request as ready for review November 10, 2026 22:21
@esaurez
Enrique Saurez (esaurez) marked this pull request as draft November 10, 2026 22:22
@esaurez
Enrique Saurez (esaurez) force-pushed the esaurez/sl2-13-capture-create-20261110-095bfb08 branch from 8d6cbce to e976e5c Compare November 10, 2026 22:27
Base automatically changed from esaurez/sl2-13-capture-create-20261110-095bfb08 to feature/nvx-refactor November 10, 2026 23:27
@esaurez
Enrique Saurez (esaurez) marked this pull request as ready for review November 11, 2026 00:33
Enrique Saurez and others added 3 commits November 10, 2026 16:55
Validate the proved-exited capture outcome, strict OpenVMM artifacts and checked capture context. Write retryable private key and description files without moving or cleaning VM-directory entries.

The Draft keeps SnapshotKey::time and its encoding/identity semantics pending the explicit user decision.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

Copilot-Session: b718df7e-13ad-474d-b3c5-b0f93a7e18e6
Copilot-Session: bc910877-842b-4ceb-8b01-c50d4c0d7af9
Persist and strictly decode the complete per-snapshot time contract; hash only the unchanged compatibility prefix and reject key/manifest time mismatches. Keep the single Fresh encoding in place without a version bump or backward reader.

Apply owner-only artifact validation at the snapshot boundary while preserving the legacy template validator and its existing callers.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

Copilot-Session: b718df7e-13ad-474d-b3c5-b0f93a7e18e6
Copilot-Session: bc910877-842b-4ceb-8b01-c50d4c0d7af9
Move the unchanged directory and endpoint contract into a private leaf, preserving the existing vm public paths and ownership. Keep capture and launch orchestration in their original modules and relocate directory tests with their owner.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: eecd1730-cf40-4c7f-8502-f74d24332b5c
@ppenna
Pedro Henrique Penna (ppenna) force-pushed the esaurez/issue1102-sl214-20261110-b718df7e branch from c6de1d8 to aa319d6 Compare November 11, 2026 01:23
@ppenna
Pedro Henrique Penna (ppenna) merged commit 9723f7a into feature/nvx-refactor Nov 11, 2026
48 checks passed
@ppenna
Pedro Henrique Penna (ppenna) deleted the esaurez/issue1102-sl214-20261110-b718df7e branch November 11, 2026 01:39
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

feat-nvx-refactor tests-modified Changes existing tests, test data, or test wiring

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants