Repository navigation
sandbox: run a workload once through the managed VM API (SL3.4b) - #1490
Merged
Pedro Henrique Penna (ppenna) merged 2 commits intoNov 11, 2026
Merged
Pedro Henrique Penna (ppenna) merged 2 commits into
Pedro Henrique Penna (ppenna) merged 2 commits into
Conversation
Contributor
This pull request changes existing testsIt modifies or removes 84 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
... and 14 more, which the job's summary lists. End-to-end tests
Test doublesCI test wiringRelocated unchanged: 0; added: 28. Compared the merge base |
Contributor
There was a problem hiding this comment.
🟡 Changes recommended
A STOP endpoint closure can bypass the configured shutdown grace period, forcing OpenVMM down before shutdown or outcome reporting completes.
3 open issues
What changed in this PR
Migrates sandbox run to the managed VM API as part of the CLI refactor: nvx-init boots the layered root, executes one workload over NVXC, and stops the VM without persistent sandbox state.
Changes:
- Adds managed execution options, EROFS/GPT images, capped RAM uppers, protected-path checks, and temporary VM cleanup.
- Removes unused one-shot launch code while preserving the public API.
- Updates regression tests, platform smoke checks, and documentation for the managed run behavior.
| File | Description |
|---|---|
scripts/test-layout-allowlist.json |
Removes retired plan test-hook exemptions. |
scripts/test_microvm_tests.py |
Updates acceptance fakes and regression expectations. |
scripts/nvx_tools/sandbox_ram_upper_tests.py |
Checks managed runs, default RAM caps, and reports. |
scripts/nvx_tools/sandbox_lifecycle_tests.py |
Expects identity rejection during managed startup. |
nvx-rs/tests/cli/validation.rs |
Updates execution-option validation cases. |
nvx-rs/tests/cli/sandbox_run.rs |
Adds managed-run integration coverage. |
nvx-rs/tests/cli/openvmm.rs |
Adds managed-run expectations and cleanup assertions. |
nvx-rs/tests/cli/one_shot.rs |
Removes obsolete sandbox one-shot cases. |
nvx-rs/tests/cli/lifecycle.rs |
Shares lifecycle fixtures with run tests. |
nvx-rs/tests/cli/dry_run.rs |
Expects managed launch commands. |
nvx-rs/tests/cli/download.rs |
Exercises workload status through NVXC. |
nvx-rs/tests/cli.rs |
Registers run tests and updates launch checks. |
nvx-rs/src/host/sandbox/tests/specification.rs |
Tests managed share rendering instead of boot tokens. |
nvx-rs/src/host/sandbox/tests.rs |
Updates share and command-line contract tests. |
nvx-rs/src/host/sandbox/prepared.rs |
Removes the private one-shot preparation path. |
nvx-rs/src/host/sandbox/plan/tests.rs |
Removes one-shot rendering assertions. |
nvx-rs/src/host/sandbox/plan.rs |
Removes one-shot renderers and boot-token delivery. |
nvx-rs/src/host/sandbox/options/tests.rs |
Tests run execution options and managed shares. |
nvx-rs/src/host/sandbox/options.rs |
Allows execution options for run and exec. |
nvx-rs/src/host/cli/session.rs |
Extracts exec payload validation for preflight use. |
nvx-rs/src/host/cli/sandbox/tests.rs |
Updates image-option eligibility tests. |
nvx-rs/src/host/cli/sandbox/options.rs |
Documents expanded run options in CLI help. |
nvx-rs/src/host/cli/sandbox/mod.rs |
Routes runs through the managed lifecycle. |
nvx-rs/src/host/cli/sandbox/lifecycle/start/tests.rs |
Checks share overlap during configuration reconstruction. |
nvx-rs/src/host/cli/sandbox/lifecycle/start.rs |
Implements temporary launch, exec, stop, and cleanup. |
nvx-rs/src/host/cli/sandbox/lifecycle/mod.rs |
Exposes the managed run implementation internally. |
nvx-rs/README.md |
Describes managed run behavior and share delivery. |
doc/usage.md |
Updates sandbox options and execution semantics. |
doc/ci.md |
Documents nvx-init smoke checks and mapping refusals. |
.github/workflows/run-nvx-microvm-tests.yml |
Switches sandbox probes to the nvx-init profile. |
Review effort: Balanced
Base automatically changed from
agents/slim-sl3-5c-own-files
to
feature/nvx-refactor
November 11, 2026 19:28
Session::exec checked a workload's arguments, working directory, and environment, and encoded its request, once it had attached to the VM. Those checks and the encoding move to Session::exec_payload, which exec still calls first, so that a caller can refuse a request that exec would refuse before it starts a VM. exec keeps the check of its response timeout, which concerns the exchange alone. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Pedro Henrique Penna (ppenna)
force-pushed
the
agents/slim-sl3-4b-sandbox-run
branch
from
November 11, 2026 19:30
279679d to
b09ec61
Compare
Pedro Henrique Penna (ppenna)
marked this pull request as ready for review
November 11, 2026 19:31
sandbox run still booted a one-shot VM: it passed its shares and its workload as boot tokens, and ran OpenVMM on the terminal with its lifecycle option, so that the shell /init booted the layered root through the old one-shot init, and it exited with OpenVMM's status. A run now launches the VM that a provision and a start of the same options would launch, without a state directory. It serializes the configuration that provision records, reads it back as start does, and launches it through host::vm in a temporary VM directory, with nvx_sandbox=1 and no OpenVMM lifecycle option, so that nvx-init boots its root. Once nvx-init is ready and has mapped the shares, the run executes its workload once over NVXC, with exec's --cwd, --environment, --environment-file, and --inherit-default-environment, asks nvx-init to stop the VM, waits up to --timeout for it to exit before it forces it down, as a stop does, also when its control endpoint closes as it is asked to stop, then writes the workload's output and exits with its status. Once the VM has exited, it removes the VM directory, with the staging file of a report that OpenVMM did not finish writing. A run takes provision's --layer-format, for an EROFS or a GPT image, and --ram-upper-percent, for a RAM upper's cap, 50 percent by default. It refuses --state-dir, and checks its command line, as the launch checks it too, and its request before it downloads or launches anything. It refuses the shares that start refuses, with its temporary VM directory in place of a state directory, through which the workload could change what OpenVMM writes there, and those of the OpenVMM that it runs, which NVX_OPENVMM may name instead of the artifact root's; provision and start refuse a share of that one too (#818). --outcome-report forwards OpenVMM's report of the run, which keeps its owner's permissions whatever the umask. The one-shot plan, its boot tokens, and its prepared launch, which nothing else used, are gone. The CLI tests of the run cover each format and upper, exec's options, shares, the refusal of the sandbox's own files, of its VM directory, and of the OpenVMM that NVX_OPENVMM names, a guest that exits during startup, a workload that the guest refuses, a VM that does not stop, a VM whose endpoint closes as it stops, which the fake OpenVMM's new fake_drop_stop=1 emulates, a command line that the launch refuses, which downloads nothing, and the outcome report under restrictive umasks; a unit test covers the removal of a report's staging file; the dry-run, validation, and one-shot tests take the managed run's command and refusals. The public sandbox scenarios and the CI smoke steps run the smoke probe with the init profile, which a managed execution has, and expect a caller-owned share to fail the run before its workload, as it fails a start. This replays esaurez's first implementation, a734c60, adapted to the typed record, the CLI-owned lifecycle, and SL3.4a's cold boot. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Pedro Henrique Penna (ppenna)
force-pushed
the
agents/slim-sl3-4b-sandbox-run
branch
from
November 11, 2026 19:48
b09ec61 to
5d0f26d
Compare
Pedro Henrique Penna (ppenna)
merged commit Nov 11, 2026
d4edeeb
into
feature/nvx-refactor
48 checks passed
Pedro Henrique Penna (ppenna)
deleted the
agents/slim-sl3-4b-sandbox-run
branch
November 11, 2026 20:13
This was referenced Nov 11, 2026
Pedro Henrique Penna (ppenna)
added a commit
that referenced
this pull request
Nov 11, 2026
The first draft of the guidelines predates the nvx-init that feature/nvx-refactor now holds: #1453 routes the new sandbox boots to it, #1431 serves capture requests, #1447 activates repaired sessions, #1439 keeps a restore's announcer as a helper, and #1490 runs sandbox run through it too. Check each statement against that code, and correct those that did not hold: - an execution takes the VM's one workload identity, which nvx-init resolves, or creates, once before its switch, not an account mode of its own request, which nothing selects yet; - the child also drops its capability bounding set, and nvx-init kills an execution's process group when its leader ends; - nvx-init captures only the Fresh boot of a platform capture, refuses a session with a root with ENOTSUP, and shares one 30-second deadline among its checks, its sweep and the capture; - the restored broker restarts at its first epoch with a reset queued, and nvx-init fails on anything but that reset; - the host sends no MAPS for an empty mapping table, which no nvx_maps token announces; - no launch of NVX's CLI carries OpenVMM's older lifecycle token, which still routes a layered launch to the older init agent; - the crate still keeps older calls that start processes, which nvx-init does not use. Quote, and compile, the space's steps in the order of nvx-init's cold boot and restore, and replace the capture excerpt with one that handles each outcome and disposition. The steps compile in SL5.1a's unit test of nvx-init's boot, the_reference_space_steps_compile, which now holds them as the guidelines quote them, and the guidelines link SL5.1a's guest-workflows example. Organize the page by ownership, the space, the executions, the capture, the transport, the restore, failures and replay. Trim design 4.2 and 4.3 to the architecture and boundaries of nvx-init and of the older layered and blockless roots, which still run. Link the guidelines from the rustdoc of guest::activation too, list the page in the project structure, and give the case matrix the doc tests that the guidelines quote, and the lines to which the links move two others. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This was referenced Nov 11, 2026
Pedro Henrique Penna (ppenna)
added a commit
that referenced
this pull request
Nov 11, 2026
The first draft of the guidelines predates the nvx-init that feature/nvx-refactor now holds: #1453 routes the new sandbox boots to it, #1431 serves capture requests, #1447 activates repaired sessions, #1439 keeps a restore's announcer as a helper, and #1490 runs sandbox run through it too. Check each statement against that code, and correct those that did not hold: - an execution takes the VM's one workload identity, which nvx-init resolves, or creates, once before its switch, not an account mode of its own request, which nothing selects yet; - the child also drops its capability bounding set, and nvx-init kills an execution's process group when its leader ends; - nvx-init captures only the Fresh boot of a platform capture, refuses a session with a root with ENOTSUP, and shares one 30-second deadline among its checks, its sweep and the capture; - the restored broker restarts at its first epoch with a reset queued, and nvx-init fails on anything but that reset; - the host sends no MAPS for an empty mapping table, which no nvx_maps token announces; - no launch of NVX's CLI carries OpenVMM's older lifecycle token, which still routes a layered launch to the older init agent; - since #1494, no call of nvx starts the announcer: nvx-init forks it and runs /sbin/nvx-ingress itself, and nvx-ingress start runs it for an agent that cannot hold it; - the crate still keeps older calls that start processes, which nvx-init does not use. Quote, and compile, the space's steps in the order of nvx-init's cold boot and restore, and replace the capture excerpt with one that handles each outcome and disposition. The steps compile in SL5.1a's unit test of nvx-init's boot, the_reference_space_steps_compile, which now holds them as the guidelines quote them, and the guidelines link SL5.1a's guest-workflows example. Organize the page by ownership, the space, the executions, the capture, the transport, the restore, failures and replay. Trim design 4.2 and 4.3 to the architecture and boundaries of nvx-init and of the older layered and blockless roots, which still run. Link the guidelines from the rustdoc of guest::activation too, list the page in the project structure, and give the case matrix the doc tests that the guidelines quote, and the lines to which the links move two others. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Pedro Henrique Penna (ppenna)
added a commit
that referenced
this pull request
Nov 11, 2026
The first draft of the guidelines predates the nvx-init that feature/nvx-refactor now holds: #1453 routes the new sandbox boots to it, #1431 serves capture requests, #1447 activates repaired sessions, #1439 keeps a restore's announcer as a helper, and #1490 runs sandbox run through it too. Check each statement against that code, and correct those that did not hold: - an execution takes the VM's one workload identity, which nvx-init resolves, or creates, once before its switch, not an account mode of its own request, which nothing selects yet; - the child also drops its capability bounding set, and nvx-init kills an execution's process group when its leader ends; - nvx-init captures only the Fresh boot of a platform capture, refuses a session with a root with ENOTSUP, and shares one 30-second deadline among its checks, its sweep and the capture; - the restored broker restarts at its first epoch with a reset queued, and nvx-init fails on anything but that reset; - the host sends no MAPS for an empty mapping table, which no nvx_maps token announces; - no launch of NVX's CLI carries OpenVMM's older lifecycle token, which still routes a layered launch to the older init agent; - since #1494, no call of nvx starts the announcer: nvx-init forks it and runs /sbin/nvx-ingress itself, and nvx-ingress start runs it for an agent that cannot hold it; - the crate still keeps older calls that start processes, which nvx-init does not use. Quote, and compile, the space's steps in the order of nvx-init's cold boot and restore, and replace the capture excerpt with one that handles each outcome and disposition. The steps compile in SL5.1a's unit test of nvx-init's boot, the_reference_space_steps_compile, which now holds them as the guidelines quote them, and the guidelines link SL5.1a's guest-workflows example. Organize the page by ownership, the space, the executions, the capture, the transport, the restore, failures and replay. Trim design 4.2 and 4.3 to the architecture and boundaries of nvx-init and of the older layered and blockless roots, which still run. Link the guidelines from the rustdoc of guest::activation too, list the page in the project structure, and give the case matrix the doc tests that the guidelines quote, and the lines to which the links move two others. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
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 #1111 (SL3.4b, "
sandbox runboots a layered root through the new APIs: a cold boot, one exec and a stop"). Parent #1083, umbrella #1076.Base:
feature/nvx-refactor7bc238eb, which includes SL3.5c (#1485).What and why
sandbox runstill booted a one-shot VM. It passed its shares and its workload as boot tokens and ran OpenVMM on the terminal with--microvm-lifecycle one-shot, so the shell/initbooted the layered root through the old one-shot init. It then exited with OpenVMM's status. After this PR, nvx-init boots every layered root that the CLI starts.A run now launches the VM that a
provisionand astartof the same options would launch, without a state directory:provisionrecords and reads it back asstartdoes, then launches it throughhost::vm::{create, spawn}in a temporary VM directory,nvx-sandbox-run-<random>in the system's temporary directory. The command line holdsnvx_sandbox=1and no OpenVMM lifecycle option.exec's options:--cwd,--environment,--environment-file,--inherit-default-environmentand--exec-timeout-ms.--timeoutfor OpenVMM to exit. A VM that hasn't exited by then is forced down, assandbox stopforces down only the verified process. The run warns that it did, and still exits with the workload's status.start. Ctrl-C forces the VM down and exits with 130.provision's--layer-format {erofs,gpt}, and--upper ramwith--ram-upper-percent, 50 by default.--state-dir. Before it downloads or launches anything, it checks its kernel command line and its exec request, throughSession::exec_payload, which the first commit splits out ofSession::exec. A dry run prints the command and launches nothing. The VM directory is removed once OpenVMM's exit is confirmed, and kept only if it isn't.--outcome-reportforwards OpenVMM's report of the run (operationrun), asnvx-rs rundoes. The report keeps its owner's permissions whatever the umask.nvx-rs sandbox#818). A run refuses the shares thatstartrefuses: of its image, its scratch image when it has one, and the artifact root's OpenVMM, kernel and Alpine initramfs. In place of a state directory, it also refuses a share of its temporary VM directory, through which the workload could change what OpenVMM writes there. It also refuses a share of the OpenVMM that it runs, whichNVX_OPENVMMmay name instead of the root's.provisionandstartshare the check, so they refuse a share of that OpenVMM too.SandboxPlan::one_shot_openvmm_arguments,SandboxPlan::one_shot_kernel_command_line,Delivery::BootTokens,PreparedLaunch::one_shot, and the CLI'srun_planandprepare_run. All of them were crate-private.run-nvx-microvm-tests.yml, the sandbox run steps pass--arg init, the smoke probe's profile for an execution of nvx-init. The caller-owned share step now expects the run to fail while it maps its share (could not mount a mapped host path (error 1)), before its workload, as astartfails.doc/run.md,doc/usage.md,doc/ci.mdandnvx-rs/README.md.The public API doesn't change: everything that this PR deletes was crate-private, and
scripts/public_api.pypasses.BOOT_CONTRACT_VERSIONandCONTROL_CONTRACT_REVISIONdon't change either.Readings of the Scope
NVX_OPENVMMnames. That is what SL3.5c (sandbox: refuse shares of a sandbox's own files (SL3.5c) #1485, nvx-rs slimming 3.1.5: the sandbox lifecycle runs on the new interface and nvx-init #1110) calls the "artifacts". Protecting the whole artifact root would refuse every share inside a checkout, CI's own shares underbuild/among them, since a checkout is its own artifact root.--timeout, assandbox stopdoes, keeps the workload's status, and warns.Size
365 core lines, 16 of them help text, against the estimate of 300 (stop 600), measured against
feature/nvx-refactor7bc238eb. The fake OpenVMM,nvx-rs/src/testing/fake_openvmm.rs, also gains 27 lines for the test of a review fix (fake_drop_stop=1). It is test infrastructure behind thetestingfeature, counted with the tests.7 counted files:
nvx-rs/src/host/cli/sandbox/lifecycle/start.rs(260)nvx-rs/src/host/cli/sandbox/mod.rs(44).github/workflows/run-nvx-microvm-tests.yml(20)nvx-rs/src/host/cli/sandbox/options.rs(16, help text)nvx-rs/src/host/cli/session.rs(16)nvx-rs/src/host/sandbox/options.rs(8)nvx-rs/src/host/cli/sandbox/lifecycle/mod.rs(1)That is within #1076's "6 or 7, where a split would be harder to follow".
nvx-rs/src/host/sandbox/plan.rsandnvx-rs/src/host/sandbox/prepared.rsonly delete the one-shot code that this change leaves dead. The PR rules require this PR to delete it ("deletes consumers before their providers, and with them the crate-private code that the deletion leaves unused"), so they are leaving code and don't count. The tests and docs don't count.The two commits stay in one PR. The first only prepares the second:
sandbox runis the one caller that needsSession::exec_payloadapart fromSession::exec. A PR of its own would need anexpect(dead_code)hook and would be harder to follow.History: the first implementation
Enrique Saurez (@esaurez)'s first implementation is on
esaurez/slim-3.1.6-sl3.4b-private-20261109(headd7b739fc). The main commit replays itsa734c60c659with Enrique Saurez (@esaurez) as its author, adapted to:The run itself is rewritten on
start's launch, and the outcome report is OpenVMM's. The branch's other commits are outside this slice's Scope.Validation
feature/nvx-refactorhas noscripts/local_gates.py, sodev's copy selected the gates. They ran with this branch's own action commands and its pinned toolchain (1.95.0, MSRV 1.89).The full validation ran at
1008a3e0, this patch on #1485's earlier head5caac3f9. The rebase onto #1485's head09a64b6a, which includes SL3.9 (#1469), conflicted in three places, all next to SL3.9's--wait:doc/usage.md: this PR's rows, with SL3.9's--waitrow kept after--timeout;lifecycle/start.rs: both sides kept;exec_workload's call insandbox/mod.rs: it now takes this PR's sharedExecRequestand SL3.9'soptions.wait.git range-diffshows only those changes. At the head,279679d1, the narrow checks passed again:cargo fmt --check;--all-targets --all-features,--lib --no-default-featuresand--lib --bins --features cli, with-D warnings;clisuite (109 passed, 2 ignored);scripts/test_microvm_tests.py(343 tests);check_test_layout.pyandcheck_markdown_links.py;nvx-kvm-test, the VM qualification below (165/165) and the sixtest-microvmscenarios below.Once #1485 merged, the branch was rebased onto
feature/nvx-refactor7bc238eb(git rebase --onto origin/feature/nvx-refactor 09a64b6a).git range-diffshows both commits unchanged, and the head's tree,b09ec616, is identical to279679d1's, so the checks above stand.rebase_check.py verifyreports only that SL3.5c's09a64b6awas dropped: it merged as7bc238ebwith the same patch.Review fixes. Copilot's review of the draft found three gaps, fixed in
5d0f26d9:EndpointClosednow gets a stop's grace period before the run forces the VM down.check_command_line()now runs with the checks that precede the download, so a balanced double quote in--cmdlinedownloads nothing.remove_vm_directoryalso removes a report's staging file (StateFile::owns_temporary).Each fix has a test that fails without it:
sandbox_run::a_run_waits_for_a_vm_whose_endpoint_closes_as_it_stops, which uses the fake's newfake_drop_stop=1, a new case indownload::commands_download_nothing_for_options_that_they_refuse, and the unit testlifecycle::start::tests::a_run_removes_its_vm_directory_with_a_report_s_staging_file.At
5d0f26d9these checks pass:cargo test --all-featuresfor the lib (1464 passed),cli(110 passed, 2 ignored),fake_openvmm,fake_openvmm_behaviorandmanaged_lifecycle;nvx-kvm-test: Clippy--all-targets --all-featuresand--features testing, the fake's suites, andcli.clihad 118 passed and 1 failed:one_shot::one_shot_runs_exit_with_the_workload_or_openvmm_statuslost the fake's console output under load (load average 5). This is thenvx-rs runconsole race that sandbox: refuse shares of a sandbox's own files (SL3.5c) #1485 documents. It passed 3 of 3 runs alone, and this PR doesn't touch that path.nvx.py verify;cargo fmt --check; the five Clippy runs of the Lint step with-D warnings, among themcargo clippy -p nvx --lib --no-default-features;cargo test --all-features --no-fail-fastandcargo test; the lib build and tests without default features; the artifact bundling test;cargo doc --all-featureswith-D warnings; MSRV 1.89; the runtime adapter's protocol-only and host-only configurationshost::restore_driver::tests::ready_has_sixty_seconds_and_start_thirty_from_ready_for_each_pending_accept_and_read(fixed since by the SL4.3 follow-up), and passed on rerunnvx-clisuite (validate-nvx's Windows step, without itspip install),test_adversarial.py, eachnvx.py ... --help, Ruff lint and format, Pyright (Linux and Windows),check_test_layout.py,check_markdown_links.pycargo test --all-features(cli113 passed) andcargo test; the lib without default features; bundling; doc; MSRV 1.89; the macOS check; the public API snapshots; the guest binaries' lint, build and tests; the runtime adapter's protocol-only, host-only and guest-only configurationsSIGINT, which failed every interrupt test, and was discardedsandbox run, belownvx.py test-microvm --scenario managed-exec-config --scenario sandbox-lifecycle --scenario sandbox-proxy-only --scenario sandbox-ram-upper --scenario sandbox-blocks --scenario managed-lifecycleThe VM qualification ran
sandbox runwith the Ubuntu distro layer: EROFS, and a GPT disk whose second partition holds an ext4 copy of it, each with a scratch upper, a RAM upper at the default 50% and one capped at 37%. For each of the six, it checked:nvx_sandbox=1and no--microvm-lifecycleon the command line, and the image's identity and the upper's tokens;--cwd;--environmentand--environment-fileenvironments, withoutPATH;--inherit-default-environment, and the default environment;Once each, it also checked:
--state-dir;NVX_OPENVMMnames, and a run of that OpenVMM;The hosts can't reach the Ubuntu archives, so the distro layer came from the base's CI run 42994995631. This PR doesn't change its inputs. The kernel and initramfs were built from the branch. WHP ran an OpenVMM built locally from the pinned
14dc4116.Left to CI: the full default
test-microvmsuite and its shards. The Linux unit gates ran on MSHV rather than onnvx-kvm-test, whose kernel fails 28guest::lib tests at the base too.Changes to existing tests
check_test_changes.py --base origin/feature/nvx-refactorreports 76 changes to existing tests and 25 additions, so this PR hastests-modified. By area:--mount, an aggregate at/run/nvx/shareswith digest-named children, andnvx_share=boot tokens. They now check the managed rendering that remains, with their refusals and budgets: the aggregate at/run/nvx/hostfs/rootwith indexed children,nvx_maps=N, and the export's command-line fragment. The script also lists the helpersShares::runandrenderingsand these tests' imports.host::sandbox::tests:launch_contract_rejects_duplicates_and_reserved_tokens,launch_contract_attaches_mount_and_reserves_bootstrap_tokens,launch_contract_attaches_several_shares_as_an_aggregate,launch_bounds_shares_by_the_kernel_command_lineandlaunch_contract_attaches_a_file_as_an_aggregate_child.host::sandbox::tests::specification:launch_arguments_follow_the_openvmm_contract,accepted_launch_shapes_keep_their_arguments_and_kernel_tokens,shares_follow_the_openvmm_and_guest_contracts,caller_parameters_follow_linux_and_guest_rules,the_reproduction_of_microsoft_nvx_723_is_refused, and the proptestskernel_command_line_stays_within_1024_bytes,reserved_kernel_tokens_are_always_refusedandaccepted_values_stay_one_kernel_parameter.host::sandbox::options::tests:sandbox_command_forwards_mount_to_openvmm,sandbox_command_shares_a_file,sandbox_command_shares_host_paths_with_commas,sandbox_command_forwards_mount_owner,sandbox_command_hides_a_share_root_behind_its_allowed_pathsandsandbox_command_attributes_mount_deny_to_the_preceding_mount.host::sandbox::plan::tests:the_managed_lifecycle_exports_the_shares_and_announces_their_mapping_table.sandbox_exec_rejects_ambiguous_or_one_shot_environmentis renamedsandbox_run_and_exec_alone_take_the_execution_options:runnow takes the execution options, and every other operation refuses them with the new message.managed_non_launch_operations_reject_network_policy_optionstakes--outcome-report's new message.host::cli::sandbox::tests,provision_options_do_not_change_other_commandsis renamedimage_options_are_only_valid_for_run_and_provision, sinceruntakes--layer-formatand--ram-upper-percentnow.run_checks_again_that_its_shares_do_not_overlapmoves tolifecycle/start/tests.rs, beside therecordstep that it now checks.dry_run::dry_runs_print_the_openvmm_command_and_launch_nothingand its helpersandbox_dry_runsexpect the managed command of a start. A--cmdlinethat holds double quotes is now refused, asstartrefuses one.validation'ssandbox_refusalsmoves the execution-option refusals offrun, and adds a relative--cwdand a nameless--environmentforrun.one_shot::one_shot_runs_exit_with_the_workload_or_openvmm_statuskeepsnvx-rs runonly. The sandbox runs that it covered move totests/cli/sandbox_run.rs, with the helpersandbox_run, and their helperssandbox_launchesandworkloadare retired.tests/cli.rs:a_distro_manifest_path_whose_lookup_fails_refuses_provision_and_startexpects the run's dry run to fail asprovisiondoes;tcp_forwards_take_any_egress_policyandnetwork_policy_files_compile_into_the_typed_policyanchor the network rendering on--single-process, since the run has no lifecycle option;a_running_sandbox_claims_its_scratch_image,a_run_passes_openvmm_no_handle_of_its_callerandinterrupting_a_run_kills_openvmm_and_exits_with_130(withsleeping_run) run workloads that the fake OpenVMM executes over NVXC, and the last also checks that the VM directory is gone;a_run_refuses_a_batch_file_as_openvmm(withbatch_openvmm) expectshost::vm's spawn error.download::sandbox_run_reads_a_packaged_layer_once_no_download_replaces_itruns/bin/sh -c "exit 7"over NVXC.openvmm.rs'sassert_checked_blocks,assert_checked_distro,checked_distroanddescriptor: the checked one-shot handoff is gone, and the run's blocks are checked as a start's are.dry_run.rs'sworkload.host/sandbox/plan.rs, with their allowlist entry.scripts/test_microvm_tests.py's fakes_FakeSandboxCli._runand_FakeRamUpperSandboxClimodel the managed run.PublicSandboxLifecycleTests.test_acceptance_detects_lifecycle_regressionsandPublicSandboxRamUpperTests.test_acceptance_detects_ram_upper_regressionsadd faults for a dropped fixture, a lifecycle option and another cap.LifecycleAcceptance.check_identity_admissionruns the probe with--arg=init, and expects the run of an identity that the image lacks to fail as a managedstartfails, with status 1 and the guest's status from the outcome report, without running its workload.RamUpperAcceptance.run,check_run_reportandcheck_one_shot, nowcheck_run, check the managed run's command line, the default cap, the forwarded report, and that nothing remains.--arg init, and the caller-owned step expects the run to fail before its workload, as above.Added:
tests/cli/sandbox_run.rs, with these tests:exec's options;NVX_OPENVMMnames;openvmm.rsadds themanaged_runfixture andnormalized_run_outputs. The tests of the two refusals that the review added fail without the fix.