Skip to content

tests: capture templates in VMs through the runtime adapter - #933

Merged
Pedro Henrique Penna (ppenna) merged 1 commit into
devfrom
esaurez/841-pr3-captures-in-vms-20261024
Oct 28, 2026
Merged

Pedro Henrique Penna (ppenna) merged 1 commit into
devfrom
esaurez/841-pr3-captures-in-vms-20261024

Conversation

@esaurez

@esaurez Enrique Saurez (esaurez) commented Oct 27, 2026 •

Copy link
Copy Markdown
Contributor

Chain: this PR → #880 → #936 → #937 → #939 → #940 → #941, on dev; #879, #881, #885, #886, #877, #932, #884, and #887 have merged.

The runtime adapter's host program gets a create command, which serves a template of the guest agent from an NVX template store: a compatible generation that the store holds, or a new one that the store captures, in a VM of the adapter's template mode, through NVX's supervisor, and publishes. New VM tests capture templates on each backend, without a NIC and with one NIC per tested network policy, and check the generation that the store publishes.

Part of #841: the third of its three pull requests.

What changed

  • runtime-adapter-host create STORE --guest-agent PATH --distro FORMAT:PATH --distro-identity UUID, in tests/runtime-adapter/src/bin/runtime-adapter-host.rs, serves the template with nvx::host::template::Store::create_template (nvx-rs: capture templates into their store, and publish them #887), from a template store that it creates if needed. It stages the placeholder distro as stage stages an image, and takes --hypervisor, --cpu-profile (auto by default), --processors (1), --memory (256 MiB), --memory-capacity (the RAM by default), --scratch-length (64 MiB), and --network, which launch takes too. It reads the network before anything else, checks the capture class before it creates the store, and prints created (captured or existing), generation, key, and class.
  • runtime_adapter::capture (host-only): Request, what the options choose of a template, and Request::capture, NVX's Capture of it:
    • the adapter's plan of the placeholder (SandboxPlan::adapter), with the network, and the placeholder's DistroBinding;
    • NVX's artifacts, with the initramfs that puts the guest agent in place of NVX's agents;
    • the CaptureClass: the runtime identity of the adapter's VMs with the guest agent's build, the backend and the CPU profile, the processors, all online at boot, the RAM and its capacity, the geometries of the placeholder and of the dormant scratch (capture::geometry), and the network.
  • Template mode's allowlist, in tests/runtime-adapter/src/template.rs: is_platform_token is now OpenVMM's own check, platform_command_line_token_is_invariant, compiled with include! from the excerpts of OpenVMM's sources that nvx-rs: lower adapter plans into the plans of template captures #884 keeps in nvx-rs/tests/vectors/openvmm/, which nvx-rs/tests/openvmm_vectors.rs compares with the OpenVMM submodule. It replaces tests: capture a template's VM in the runtime adapter's guest #932's hand-written copy of the allowlist (PLATFORM_TOKENS and PLATFORM_PREFIXES). The excerpt admits maxcpus=, as OpenVMM does at the pinned d2338ea2, whose excerpts are unchanged since e68871cc, and tests: capture a template's VM in the runtime adapter's guest #932's tests of maxcpus= stay. As in OpenVMM, a token that is not UTF-8 text is not on the allowlist.
  • nvx-rs: the template plan's tests also check that no token of a template's kernel command line holds a byte outside ASCII or the kernel's whitespace, so that OpenVMM, which splits at ASCII whitespace, and the kernel find the same tokens. nvx-rs/tests/vectors/README.md notes that the adapter compiles the excerpts too.
  • Tests:
    • tests/vm_template.rs, ignored, since they boot VMs or need NVX's artifacts:
      • captures without a network; with a network that lets nothing through, which attaches no NIC; and with one NIC under egress, an allow rule, outbound host loopback, and a proxy alone;
      • each checks the store's one generation, whose payload holds the record of its capture, its key, and its snapshot, and whose key holds what the test asked for: a NIC exactly when the network lets something through, and a kernel command line of the platform tier's tokens alone, which names neither the placeholder's identity nor a root. The class's slot then holds no transaction and records no launch, and a second creation serves the generation without a capture;
      • refusals before any VM starts: ingress, host loopback both ways, and, before the store, a class that no capture takes.
    • tests/template_capture.rs, without a hypervisor: the capture's class and inputs from a request, and the creations that the host program refuses before it creates anything.
    • tests/layered_launch.rs: the options that create refuses.
    • tests/common: the harness creates templates, and the store's recovery ends the captures that a failed test interrupted.
  • tests/runtime-adapter/README.md: the Templates section, the create command and the values that it prints, and the allowlist as OpenVMM's own check.

Design notes

  • The adapter lowers no capture option and chooses no snapshot path itself: Store::create_template lowers the adapter's plan into nvx-rs: lower adapter plans into the plans of template captures #884's TemplatePlan, and launches the capture through the supervisor, as nvx-rs: capture templates into their store, and publish them #887 does for any caller.
  • The placeholder is a trusted artifact of the platform, which the command stages and binds as an image. Its length is the capacity of every clone's image, and the capture refuses one that anyone else may change.
  • The command writes the initramfs of the adapter's VMs into a directory of its own in the system's temporary directory, private to the current user, as a launch writes it into the sandbox's private store, and removes it once the creation returns.
  • On Linux, the capture's VMM listens at captures/C/transaction/control.sock in the store, beside the snapshot's destination, as OpenVMM requires, so NVX refuses a store whose path leaves no room for that socket's path.

Validation

At this head, with the OpenVMM submodule at d2338ea2, which dev now pins. The vectors and the template mode's allowlist tests pass with it, so the excerpts are OpenVMM's at d2338ea2 too.

Rebase: this head moves the one commit from #887's head 0b23113 onto dev's b855c4d, which holds #887, and resolves one conflict, in tests/runtime-adapter/README.md, whose paragraph on running the VM tests keeps tests/vm_template.rs and downloads the artifacts with nvx-rs download (#934). The previous head moved from a local integration of #887's 491de89 with #840 PR 2's 953eb0b onto #887's head 0b23113, which carries #932 beneath it. It keeps the base's sharing options in runtime-adapter-host beside create's --network, adds capture to the base's host-only modules, takes Staged from the base's staged module, drops a visibility change to layered::plan that the base already made, and replaces #932's hand-written allowlist with the excerpt, whose maxcpus= its doc now lists.

  • Windows: in nvx-rs, with NVX_BUNDLE=skip: cargo fmt --all --check; cargo clippy --locked --all-targets --all-features -- -D warnings; cargo clippy --locked --lib -- -D warnings, also with --no-default-features; cargo clippy --locked --all-targets --no-default-features --features <feature> -- -D warnings for host, cli, testing, serde, and bundled; cargo test --locked --all-features; cargo test --locked; cargo build --locked --lib --no-default-features and cargo test --locked --lib --no-default-features, also with --features host; RUSTDOCFLAGS="-D warnings" cargo doc --locked --no-deps --all-features; cargo +1.89 check --locked --all-targets --all-features; and cargo test --locked --test host_modules. From the root, the ignored cargo test --locked --manifest-path nvx-rs/Cargo.toml --no-default-features --test openvmm_vectors -- --ignored. Then the commands of check-nvx-rs for tests/runtime-adapter, protocol-only and host-only, and python scripts/check_markdown_links.py.
  • Linux: the same, plus --features guest, cargo check --locked --all-targets --all-features --target aarch64-apple-darwin, python3 scripts/nvx.py check-guest-binaries, and the runtime adapter's static musl guest configuration.
  • On both hosts, also cargo fmt --all --check and Clippy with -D warnings of nvx-rs (--all-targets, and --lib with and without default features) and of the runtime adapter's configurations, cargo test --locked --test host_modules, and on Linux the macOS check.
  • VMs: with the development release v0.1.0-dev.6464eb005bf6, which nvx-rs download installed, whose OpenVMM is d2338ea2 and whose guest artifacts' inputs are this head's, and with the guest agent built from this head, all 58 ignored tests of tests/runtime-adapter passed: vm_layered (43), vm_restart (3), vm_steps (3), and vm_template (9), on Windows/WHP and on Linux/MSHV. The Linux development host no longer needs an override of the CPU profile: OpenVMM's --cpu-profile auto presents amd.genoa.v2 there.
  • CI: run 40614457090, the pull request's CI at this head, passed: 28 jobs passed, among them the runtime adapter's VM tests on KVM, MSHV, and WHP, where all 58 passed on each, vm_template's 9 among them. It skipped OpenVMM's unit and VMM tests, whose inputs this pull request leaves unchanged, the debug kernel's tests on MSHV and WHP, which pull requests run on KVM alone, and the jobs that package, publish, and persist on dev.

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.

🔵 Needs a closer look

Cross-platform VM capture and recovery need final human review and confirmation of the backend validation listed as pending.

No open issues 🎉

What changed in this PR

This PR connects the runtime adapter to NVX’s template capture and publication APIs, completing the adapter integration portion of #841.

Changes:

  • Adds a host create command and capture requests for serving existing templates or capturing new generations.
  • Adds VM capture scenarios, command-validation tests, and harness support for capture recovery and diagnostics.
  • Reuses OpenVMM’s platform-token allowlist and strengthens command-line compatibility checks.
File Description
tests/​runtime-adapter/​tests/​vm_template.rs Adds VM capture, generation reuse, and network-policy scenarios.
tests/​runtime-adapter/​tests/​template_capture.rs Tests capture inputs and early command failures without a hypervisor.
tests/​runtime-adapter/​tests/​layered_launch.rs Tests rejected create options and arguments.
tests/​runtime-adapter/​tests/​common/​mod.rs Adds template creation, capture diagnostics, and recovery cleanup.
tests/​runtime-adapter/​src/​template.rs Uses OpenVMM’s allowlist excerpts and tests UTF-8 handling.
tests/​runtime-adapter/​src/​lib.rs Exposes and documents the host-only capture module.
tests/​runtime-adapter/​src/​capture.rs Builds capture plans, classes, artifacts, and disk geometries.
tests/​runtime-adapter/​src/​bin/​runtime-adapter-host.rs Implements create, its options, and temporary initramfs handling.
tests/​runtime-adapter/​README.md Documents template creation, outputs, and test scenarios.
nvx-rs/​tests/​vectors/​README.md Documents the adapter’s use of OpenVMM excerpts.
nvx-rs/​src/​host/​template/​plan/​tests.rs Checks that template tokens contain only ASCII and no kernel whitespace.

Review effort: Balanced

The runtime adapter's host program gets a create command. It stages the
placeholder distro, makes a capture class of the adapter plan that the
request names, and creates the template in an NVX template store, which
serves a compatible generation of the class, or captures one through the
supervisor in the adapter's template mode and publishes it.

New VM tests capture templates on each backend, without a NIC and with one
NIC per tested network policy, and check the published generation's key,
payload, and slot. Policies that no template takes are refused before any
VM starts.

The guest agent's template mode checks its kernel command line with
OpenVMM's platform allowlist, compiled from the excerpts that the template
plan tests of nvx compile, in place of a mirror of it.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 32eea669-a52c-4a53-87fa-521c498537e5
@esaurez
Enrique Saurez (esaurez) force-pushed the esaurez/841-pr3-captures-in-vms-20261024 branch from 8c127e4 to e021475 Compare October 28, 2026 01:20
Copilot AI balanced review requested due to automatic review settings October 28, 2026 01:20

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 approval of the template capture and publication changes.

No open issues 🎉

Review effort: Balanced

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