Skip to content

nvx-rs: parse fake OpenVMM --mount-child values with one function - #613

Merged
Pedro Henrique Penna (ppenna) merged 1 commit into
devfrom
nvx-rs-quality/fake-mount-child
Oct 20, 2026
Merged

Pedro Henrique Penna (ppenna) merged 1 commit into
devfrom
nvx-rs-quality/fake-mount-child

Conversation

@ppenna

Copy link
Copy Markdown
Contributor

Summary

The fake OpenVMM (nvx::testing::fake_openvmm) parsed --mount-child NAME,HOST,MODE[,file] values with two copies of the same parser: one in sandbox_shares, for the children of a sandbox's aggregate at /run/nvx/shares, and one in mapped_children, for the children of the host mapping table's export. This change keeps that parser once, in the private function mount_child_host, so that the fake's two option paths accept the same syntax by construction. The production --mount-child producers and OpenVMM itself are untouched.

Changes

All in nvx-rs/src/testing/fake_openvmm.rs:

  • mount_child_host(child, index) returns the host path of a --mount-child value, or fails with invalid --mount-child VALUE unless the host path is a directory or, with the file flag, a regular file, the mode is ro or rw, and, if index is given, the name is that index.
  • The sites that now share it:
    • sandbox_shares calls it without an index, for the children of a sandbox's aggregate, whose names are digests;
    • mapped_children calls it with each child's index, for the numbered children of the host mapping table.
  • The unit test mount_children_resolve_to_hosts_of_their_kind covers the accepted directory and file children, a child without an index, and each refusal: another name, a file without the flag, a directory with it, a missing host path, another mode, a missing mode, and a value with only a name.

Behavior

Nothing observable changes:

  • Every refusal keeps its message, invalid --mount-child VALUE, and every other message of the fake is untouched.
  • The parser takes the same steps in the same order: it splits off the name, strips the file flag, splits off the mode, probes the host path with is_file or is_dir, and then checks the name, the kind, and the mode, as the condition of mapped_children did.
  • mapped_children still requires the names 0, 1, ... in order, and sandbox_shares still accepts any name.
  • The fake is test-only, behind the testing feature. No public API, ErrorKind, protocol byte, golden fixture, guest binary, or nvx-rs CLI changes; the CLI build (--features cli) doesn't compile this module.

Existing tests drive both callers: the CLI golden lifecycle scenarios lifecycle: several shares and lifecycle: file share, in both the POSIX and Windows sections of tests/fixtures/cli.json, run the fake with directory and file children of a sandbox aggregate, and aci_edge_sandboxes/tests/openvmm_fake.rs maps directories and files through the host mapping table.

Follow-ups

The survey turned these up, and this change leaves them alone.

  • Suspected bug: sandbox_shares accepts --mount-aggregate /run/nvx/shares without any --mount-child, and repeated child names, while OpenVMM's MicrovmFilesystemConfig::new_aggregate refuses both (InvalidChildCount and DuplicateChildName), and mapped_children refuses an aggregate without children. The fake's sandbox path is thus more lenient than OpenVMM. Making it strict changes what the fake accepts, so it wants its own change.
  • In host/session.rs, features, map_host_paths, and next_exec_event repeat the request-ID check with the same message, map_host_paths and next_exec_event truncate an error category to 64 characters the same way, and ping and stop differ only in their request and reply kinds and their message.
  • In host/sandbox/mount.rs, MountAccess, MountOwner, and MountKind repeat from_name with the same message form, unsupported sandbox mount WHAT 'NAME'; choose A or B, and host/sandbox/mount/tests.rs and host/sandbox/tests.rs define the same policy test helper.
  • These follow-ups of earlier runs remain:
    • Instance::runtime and Instance::launch in host/instance.rs;
    • the option-values test helper of host/filesystem.rs, host/network/mod.rs, and host/sandbox/options/tests.rs;
    • the fixture of a Python process whose main thread exits first, in host/process.rs and host/cli/sandbox/identity.rs;
    • the managed-agent test fixtures, the entry convention of the nine guest programs, the failure-reporting closures of console_pending.rs and mmio_write.rs, run_file and run_network in device_io.rs, the device_io helper in tests/guest_tools.rs, and the time tools' watcher-violation sites and port-window lock failures.

Validation

  • BASE: 2fc63e7465decee7a7764e937472d0f7416d9c82, origin/dev when the run started.
  • TREE: b976a1f3140a207ae31bcd82ddb439e72150c20a, the tree of this commit, applied as a patch on BASE on each host.
  • Release: v0.1.0-dev.ff95973ba9da, which nvx.py download installed on each host as the nearest released first-parent ancestor of BASE, with OpenVMM d0bdbed8f6e3b86271277dc22658109e2e633b2d, the pinned revision.
  • Guest artifacts: prometheus30 rebuilt the guest binaries from TREE with build-guest-binaries, ran test-guest-binaries on them, and built the Alpine initramfs from them with NVX_GUEST_BINARIES. All three hosts ran the same initramfs.cpio.gz (SHA-256 b5832af0e8e9985ed4d0e684253be3ec03956f960b36c133ac26daa2e900598b), package manifest, and provenance. Each host also rebuilt the nvx-rs CLI from TREE and recorded its provenance before its hypervisor tests.
  • Local checks, on Windows: cargo fmt --check; Clippy with -D warnings for all targets and features and for the library without default features; cargo test with all features and with the defaults; and rustdoc with -D warnings. This machine also ran the steps for which the hosts lack a toolchain or target: the Rust 1.89 MSRV check of both crates on Windows, and the aarch64-apple-darwin check of both crates, which CI runs on Linux.
Host profile Backend Host type check-nvx-rs check-aci-edge-sandboxes Guest binaries and initramfs test-aci-edge-sandboxes test-microvm (default suite)
prometheus32 kvm baremetal Linux steps pass, including MSRV 1.89, the bundled-release test, and check-guest-binaries Linux steps pass, including MSRV 1.89 and agent bundling — pass, 18 of 18 pass
prometheus30 mshv baremetal — — build-guest-binaries, test-guest-binaries, and build-initramfs pass pass, 18 of 18 pass
prometheus28 whp baremetal Windows steps pass, including the bundled-release test; MSRV ran locally Windows steps pass, including agent bundling; MSRV ran locally — pass, 18 of 18 pass

directories_on_another_volume_are_mapped passes by skipping on hosts without a second volume, as on all three.

Left to CI: the test-microvm scenarios that run only when named (smp-lapic, managed-exec-config, and sandbox-lifecycle), the Ubuntu and Azure Linux guests, the OpenVMM suites, guest determinism, benchmarks, and check-quality and validate-nvx, which this change doesn't affect: it changes no Python, shell, or Markdown file, and adds, moves, or deletes none.

The fake OpenVMM reads --mount-child NAME,HOST,MODE[,file] values on
two paths: sandbox_shares, for the children of a sandbox's aggregate at
/run/nvx/shares, and mapped_children, for the children of the host
mapping table's export. Each repeated the same parser: split off the
name, strip the file flag, split off the mode, check that the host path
is a directory or, with the flag, a regular file, check that the mode
is ro or rw, and fail with "invalid --mount-child VALUE". The copies
differed only in that mapped_children also requires each name to be
the child's index.

mount_child_host now holds that parser once and takes the index that
the name must match, if any. Both loops shrink to one line each, and
the two option paths can no longer drift apart in the syntax that they
accept.

Behavior is unchanged. Every refusal keeps its message, the checks and
the filesystem probes run in the same order, mapped_children still
requires each name to be its index, and sandbox_shares still accepts
any name. A new unit test pins the accepted children and each refusal,
which no existing test reaches. The lifecycle scenarios of the CLI
golden tests share directories and a file through a sandbox aggregate,
and the aci_edge_sandboxes fake-OpenVMM tests map directories and
files, so existing tests drive both callers.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot AI balanced review requested due to automatic review settings October 19, 2026 23:44

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

The focused refactor preserves existing behavior, with regression coverage and no identified blocking issues.

No open issues 🎉

What changed in this PR

Consolidates duplicate --mount-child parsing in the test-only fake OpenVMM while preserving both callers’ validation and error messages.

Changes:

  • Extracts mount_child_host and uses it for sandbox shares and mapped children.
  • Adds regression coverage for valid inputs and validation failures.
File Description
nvx-rs/​src/​testing/​fake_openvmm.rs Shares mount-child parsing between callers and adds focused tests.

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.

2 participants