Repository navigation
sandbox: record the network's options and build its policy at each start (SL3.10c) - #1501
Pedro Henrique Penna (ppenna) wants to merge 8 commits into
Conversation
The download started its tools with supervisor::spawn_command, which holds the old supervisor's spawn lock while it creates a process, so that on Windows the tool inherits no handle of a VMM that another thread of the process starts meanwhile (#966). The CLI is to stop using the old supervisor, and needs no lock for its tools: run, sandbox run and sandbox start download before they launch, and no CLI command starts a VM on another thread while it downloads. tar, git and curl now start with Command::spawn, with the same standard streams, environment and working directory as before. Their errors stay as they were: a tool that does not run fails the download as unavailable, naming the program; a tool that fails reports its standard error; and the CLI checks for Ctrl-C once a tool exits, which reaches the tools as before, since they still share the CLI's console and process group. The library's tests, though, run the download beside tests that launch stand-in VMs, so #966's protection moves into them: each archive and GitHub test that runs tar or curl holds the tests' spawn lock, which host::tests::hold_spawns returns, while it runs them, and the archive tests' helper that packages a release spawns its own tar with host::tests::spawn_locked, which therefore builds wherever the CLI does. A new GitHub test checks the error of a curl that does not run, which the changed spawn produces. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
A managed cold run waits for its control endpoint with Session::connect_launched_cancellable, which ends the wait once OpenVMM exits, rather than at its timeout. It took the old supervisor's child type, spawn::Launched, which host::vm::Launched lent it through child_mut, and polled that child's status. It now takes the verified process of the run's host::vm::Launched, beside the endpoint and capability that the launch supplies, and asks that process whether it has exited. The process is the same OpenVMM, held through its pidfd or process handle, so the wait notices its exit as the child's status did, without reaping it: the foreground still reaps it through wait_status. A check that fails still keeps the wait going until the timeout. child_mut becomes private to host::vm, whose wait_status alone uses it, and the session's comments no longer name host::instance. sandbox exec and sandbox stop attach through Session::reattach, which verifies a saved VM through host::vm, and do not change. A new test gives the wait a process that runs and then exits: the wait goes on while the process runs, and ends as a closed endpoint once it exits, rather than at its timeout, on Linux and Windows. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
A sandbox's configuration can now name a snapshot of the CLI's named snapshot store: the snapshot, the store, and the workload that each restore runs, an entrypoint and its arguments. Each `sandbox start` of such a sandbox restores the snapshot in place of a cold boot, and `deprovision` removes the sandbox's view of the snapshot. SL3.8a2's `snapshot restore` provisions such sandboxes; until then `provision` records no snapshot. A start of a restored sandbox opens the store, takes the snapshot's exclusive lock, removes the view of an earlier start, and creates the VM with `host::vm::create` from the snapshot, with the snapshot's online processors, through the store's launch journal. The blocking restore driver then receives the restore-ready event of the verified process, activates the guest with the activation record of the start's own network policy, which gives the guest its DNS server and listener announcements, sends the sandbox's mapping table, and starts the workload. Closing the session that the driver returns at once can lose the workload's Start, as real KVM and MSHV restores showed, so the start keeps it until the workload ends, forwards its output, and fails unless it exits with status 0 within --timeout. The lock goes once the start ends, or once a failed start has verifiably ended the VM. Ctrl-C and --timeout cancel the driver and the wait. On Windows, OpenVMM opens a restore's scratch only while no other handle may write it, so the start closes the scratch claim's writable handle, and the VM inherits the claim's guard instead. A start whose command dies before it commits leaves its journal, whose recovery by the next command ends the VM. A spawn that cannot confirm that its VM ended has that recovery end the VM of a restore before the snapshot's lock goes; a start that cannot confirm that its VM ended at all leaves the journal to the next command. A closed control endpoint proves no exit, so, as for a cold start, OpenVMM then has the grace to exit by itself before the start ends it. A cold start takes the same launch path as before. A restore's guest accepts only a fresh upper, whose `upper` and `work` directories are missing or empty, so a later start of a restored sandbox with a scratch image refuses before it launches once the view of an earlier start shows that it gave the image to a guest. One with an upper in RAM restores again. `deprovision` removes a restored sandbox's `openvmm/` view, and on Linux its restore-ready socket, under the snapshot's lock, and refuses a view that is a link or holds anything else. Before a start or deprovision removes anything, it refuses a state directory in the snapshot store, once links are resolved, since the view there could be a snapshot's own files. A busy snapshot lock names the snapshot. The record is SL3.5a's typed configuration, format 9, which keeps `source_snapshot` and now records `source_store` and `workload` beside it, only for a restored sandbox. `Config::source` reads them back for start and deprovision, which ends the `expect(dead_code)` hook of the name's accessor, and `serialize_launch` takes the snapshot to record in place of `serialize_launch_with_snapshot`. The start is the production caller of SL4.3's restore driver, which ends its hook and its test-layout allowance. This is the first half of SL3.8a, which adapts the first implementation on esaurez/slim-3.2.2-sl3.8a-private-20261108 (e7d77fc), its restore start, source record, view removal under the lock, and restore-ready socket cleanup, to the CLI-owned lifecycle of SL3.5b, the typed configuration of SL3.5a, the restore creation of SL2.16, and the restore driver of SL4.3. Tests: fake-backed restores, whose checked launch spawns a fake OpenVMM and guest in place of OpenVMM, cover EROFS and GPT images with scratch and RAM uppers, the restore's own DNS server and published listeners in the activation record, the mapping table, and the workload; concurrent restores of one snapshot, the second of which spawns its VM only once the first one's has exited; failed restores, including a workload that exits with status 3, which end their VM and launch before the snapshot goes free, and a guest that hangs up after the workload's Start, whose VM exits by itself within its grace; a spawn that cannot confirm that its VM ended, whose VM the journal's recovery ends before the snapshot goes free; a later start, which restores again with an upper in RAM and refuses a scratch image that an earlier start gave to a guest; a command that dies before Ready, whose VM the next lock's recovery ends without any activation; deprovision, which waits for the snapshot's lock before it removes the view; the view removal's refusals, a VM directory in the store among them; and the record's source. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
`snapshot restore NAME --store-dir STORE --state-dir STATE` provisions a managed sandbox with the options of `sandbox provision` that a restore takes, and starts it from the named snapshot that `snapshot capture` published. The sandbox's configuration records the snapshot, its store, and its workload, the entrypoint and its arguments, so each later `sandbox start` restores the snapshot again, as SL3.8a1's start does. The command takes provision's `--layer-format` and `--ram-upper-percent`, so it restores an EROFS or a GPT image, with a scratch upper or a RAM upper and its cap, but none of the options that only an execution or a cold boot takes, which it leaves unrecognized. It opens the snapshot under its lock first, so a missing snapshot provisions nothing, and refuses a state directory in the snapshot store, whose files a start or deprovision could take for a view. A sandbox whose start fails stays provisioned, as after `sandbox provision`. No index of a snapshot's sandboxes or record of a restore in progress exists. `lifecycle::provision` takes the snapshot that it records, which only `snapshot restore` passes. The `snapshot` subcommand parser moves from the capture module to the snapshots module, which dispatches both commands. This is the second half of SL3.8a, from the first implementation on esaurez/slim-3.2.2-sl3.8a-private-20261108 (e7d77fc). Tests: the snapshot parser, which selects capture or a restore with the options of a provision, provision's image format and RAM upper cap among them, requires the snapshot, its store and the state directory, and leaves the options of an execution or a cold boot unrecognized; the capture parser, which now parses only the options after `capture`; and the refusal of a state directory in the store before anything is provisioned. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
`run --restore-snapshot PATH` handed a raw OpenVMM snapshot directory to OpenVMM with the options of a cold boot, outside the store, the locks, and the restore driver of the named snapshots that `snapshot capture` captures and `snapshot restore` restores. It now takes the name of a snapshot of `--store-dir` and restores it once, through the path of `snapshot restore`: `sandbox::restore_once` provisions a managed sandbox in `--state-dir`, starts it from the snapshot under the snapshot's lock, through the launch journal and the blocking restore driver, which forwards the workload's output, stops the VM once the workload has exited with status 0, deprovisions the sandbox once it is provisioned, whatever happened, and ends with the workload's status. The restore inputs are options of `snapshot restore`, taken from its own option list and parsed by `sandbox` for both: `--state-dir`, `--layer`, `--layer-format`, `--scratch`, `--upper`, `--ram-upper-percent`, `--entrypoint`, `--arg`, `--hostname`, `--workload-user`, and `--timeout`, so a restore of `run` takes none that `snapshot restore` refuses, such as the exec-only `--wait`; `--memory-mib` takes the sandbox's default for a restore. The restore links the snapshot's files into `--state-dir`, which must therefore be on the store's filesystem, and outside the store, which SL3.8a requires of every restored sandbox, at its provision, start, and deprovision. Since the run removes it, it must not exist, and an empty path, which names the working directory, is refused: a sandbox that it names is never removed. A cold boot refuses `--store-dir`, `--state-dir`, and the restore inputs, and a restore refuses the options of a cold boot that the snapshot or its sandbox fixes: `--guest`, `--memory-capacity-mib`, `--processors`, `--cpu-profile`, `--net`, the share options, `--outcome-report`, `--cmdline`, and `--dry-run`. A raw OpenVMM snapshot is refused before anything is read or launched: `--restore-snapshot` without `--store-dir`, or with a value that is no snapshot name, such as a path, fails with a message that says that the option names a snapshot of the store that `snapshot capture` captured. `--restore-processors`, `--restore-memory-mib`, `--restore-ready-path`, and `--restore-network-policy` only served the raw restore, and go: the named restore takes its processors from the snapshot's key and its memory from `--memory-mib`, owns its restore-ready endpoint, and always installs the restore's own network policy. A restored workload that exits with another status than 0 still fails the start, which ends its VM and launch, but the start that `run` asks for ends with that status, which `run` exits with: `snapshot restore`, and each later `sandbox start` of a restored sandbox, keep their error, "the restored workload ended with Exit status N", and status 1. The snapshot fixes the NIC. The restore of a snapshot with a NIC takes the NIC's address, and lowers the run's DNS server, egress, forwards, and published listeners, which need `--network-profile`, into the restore's own policy, as `sandbox` lowers them; that of a snapshot without one refuses network options before it provisions anything. `snapshot capture` gives its VM no NIC today, so only fake-backed tests cover the policy that reaches the guest of a networked restore. A `run` that dies before it removes its sandbox, as `kill -9` ends it, leaves `--state-dir` and its VM, which keeps running until a command of the sandbox ends it, and the snapshot's lock goes with the `run`. While the workload runs, the start is unfinished, and `sandbox deprovision` ends the VM, through the recovery of the start's launch journal, and removes the directory; once the workload has exited with status 0, `sandbox stop` must end the VM first, as it must after Ctrl-C while the run stops the VM. usage.md says so. The raw restore's code goes with it: the restore body and console reattachment of `run`, the OpenVMM arguments of the network options, and the reader of a snapshot manifest's attachments that only it used. The `run-console-restore` microVM scenario, which restored a raw snapshot with its boot console on the terminal, is retired with its shard entries. esaurez's partial implementation on esaurez/private-sl38b-0325-b2 (ef52ba6) restored blockless snapshots through unmerged prerequisites. This keeps its refusal of raw snapshots and of the options that a restore fixes, and restores through the layered sandbox path of SL3.8a instead. Evidence, on nvx-kvm-test (KVM, Azure Linux 3, kernel 6.6) and nvx-mshv-test (MSHV, kernel 6.18), virtual machines, and on WHP on a Windows 11 developer machine, with OpenVMM 14dc4116, the kernel of release v0.1.0-dev.53ad09678bc1, and this tree's Alpine initramfs: `snapshot capture` published `base`, and `run --restore-snapshot base` restored the release's Ubuntu EROFS layer and a GPT image of its tree, over a RAM upper and over a fresh scratch (GPT over a scratch on KVM and MSHV), as nobody and as daemon (`--workload-user 1:1`), forwarded the workload's output and its statuses 0, 7, and 1, and left no directory, VM, or link to the snapshot's files behind, while `snapshot restore` of /usr/bin/false still failed with its error and status 1. The raw snapshot directory, with and without `--store-dir`, network options for the snapshot without a NIC, a missing, existing, or in-store `--state-dir`, and `--wait` were refused before launch. On KVM and MSHV also: `--memory-mib 384` of a snapshot of 512 MiB capacity (MemTotal 372564 kB, against 241492 kB), three concurrent one-offs of one snapshot, SIGINT (status 130, the directory removed), and a state directory of 89 bytes, whose socket fails the VM's creation and which the run removes. A `run` that kill -9, or Stop-Process -Force on Windows, ended while its workload ran left its VM running 120 s later, while another restore of the snapshot succeeded; `sandbox deprovision` alone ended that VM and removed the directory, as `sandbox stop`, which then reports sandbox-not-running, and `deprovision` also did. A restored sandbox whose workload had exited with status 0 refused `deprovision` until `sandbox stop` ended it. Tests: unit tests parse the restore options of `run` as those of `snapshot restore`, give the restore of a snapshot the snapshot's NIC with the policy of the run's options, and refuse network options for a snapshot without a NIC; fake-backed restores install the run's network options as the restore's own policy, with the DNS server and published listeners of the activation record, and OpenVMM's egress, forward, and host-loopback options without `--net`, refuse network options for a snapshot without a NIC before they provision anything, and end with the status 3 of their workload, once the VM and its launch have ended, where `snapshot restore` keeps its error. CLI tests cover the raw refusals, a missing store, the state directory's refusals, the options that each kind of run refuses, the removed options and `--wait`, and the help. The dry runs and launches of raw restores, the proptest of a restore's policy paths, and the tests of the attachment reader are retired with the code that they tested. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
With SL3.4b's managed `sandbox run` and SL3.8b's named restore of `run` both applied, nothing calls the one-shot foreground launch any more: `host::cli::sandbox::one_shot` (`run_openvmm`), and on Windows `platform::spawn_foreground` and `standard_handle`, whose dead code fails the warning-denied Clippy build. SL3.8b's own rebase onto feature/nvx-refactor deletes them; this commit stands in for that deletion in the temporary local base of SL3.10b-d, and goes once SL3.8b's branch holds it. It also drops the Windows test of `spawn_foreground` and that function's line in the batch-file test. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…and plan Two of the shared sandbox modules still reached old APIs for values that the new interface already owns. `sandbox/mod.rs` named the artifacts' runtime identity through `host::store`, which only re-exports `host::runtime::RuntimeIdentity`, and `sandbox/options.rs` found the gateway of `--net` through `host::sandbox::plan::guest_gateway`, the old plan's wrapper around `net::guest_gateway`. `sandbox/mod.rs` now imports `RuntimeIdentity` from `host::runtime`. `sandbox_network` checks `--net` with `Ipv4Cidr::parse`, whose refusal is the plan's word for word, `guest network "ADDRESS" must be an IPv4 address with a /1 to /30 prefix that is not its network's network, broadcast, or gateway (first) address`, with the same code, and takes the gateway from `net::guest_gateway`, which finds one for every address that parses. The order of the refusals does not change, and `SandboxNetwork::new` still checks the network. This is the first step of SL3.10b, whose split was approved once its measured scope came to about ten times its estimate: SL3.10c moves the sandbox network to `NetworkConfig`, and SL3.10d moves the launch off `SandboxLaunch`, `SandboxSettings` and `SandboxUpper`. Tests: `network_policies_that_the_planner_refuses_fail_before_launch` in tests/cli.rs keeps checking, word for word, that `sandbox run --dry-run` and `sandbox provision` refuse `--net 10.0.0.1/24` before they launch or record anything. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
The sandbox's network was `host::sandbox::SandboxNetwork`, one of the old config types: `sandbox_network` returned it, the launch carried it, and `config.json` stored it in the serde form of the old plan's network, from which `start` read it back. `nvx-rs run` and `start` converted it into the `NetworkConfig` of `host::config` that their VMs take. `sandbox_network` now returns that `NetworkConfig`, after the checks that `SandboxNetwork::new` made: the guest network, and that OpenVMM's options can express the policy, with `host::network::openvmm_arguments`. The configuration records the CLI's own network options in place of the policy, as a `NetworkRecord`: `--net`, `--network-egress`, `--network-ingress`, `--host-loopback`, `--network-proxy` and the `--host-loopback-forward` options as given, and the egress rules in OpenVMM's form, as the rule options gave them or a policy file compiled them, so that no start reads that file again. Each start, and the configuration that `sandbox run` writes and reads back, rebuilds the options with the parser's own receiver and builds the network from them with `sandbox_network`, as provision did. `provision` and `sandbox run` pass the record in `ProvisionConfig`, beside the other options that provision records. The checks of the network, their order and their messages do not change. The record requires every field, an option that was not given as `null`, and `Config::new` builds the network as it reads the record, so a record whose options the parser or `sandbox_network` refuses fails as `sandbox configuration is malformed` when read, as the old plan's network did. The record changes form, so the configuration moves to format 10. Nothing in this workstream is deployed, so format 9 is refused rather than migrated, as format 8 was, and the refusal of an unsupported format now also says to deprovision the sandbox and provision it again. This is the second step of SL3.10b, whose split was approved once its measured scope came to about ten times its estimate: SL3.10d moves the launch off `SandboxLaunch`, `SandboxSettings` and `SandboxUpper`. Tests: the CLI's lifecycle cases of a network with a policy file, host loopback and forwards, and of a proxy-only network, check the new record, and their starts still launch OpenVMM with the same network options; `old_configuration_formats_are_refused_without_migration` refuses a format-9 configuration with the advice, which it lacked before; the format checks of `malformed_configuration`, `configurations_of_every_format_start_and_exec` and the `sandbox-ram-upper` scenario take format 10, as does the fake `nvx-rs` of that scenario's tests, whose old format is now 9; `malformed_configuration` also refuses network records without a field, of a gateway address, with another egress or with a broken rule as malformed, all of which the record would otherwise read or refuse later; and the restore test of `run`'s network options takes the `NetworkConfig` directly. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This pull request changes existing testsIt modifies or removes 71 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 12 more, which the job's summary lists. End-to-end tests
CI test wiring
Relocated unchanged: 0; added: 61. Compared the merge base |
There was a problem hiding this comment.
🟡 Changes recommended
Deprovisioning a stopped format-9 sandbox with an existing restored openvmm/ view fails with format-unsupported before cleanup, blocking the recommended deprovision/reprovision recovery path.
1 open issue
What changed in this PR
This PR advances #1112 by replacing the sandbox CLI’s old network-plan type with NetworkConfig and CLI-owned network records. The supplied diff also includes stacked changes for named snapshot restores and removal of old supervisor dependencies.
Changes:
- Record network options in format 10 and rebuild validated policies at each start.
- Reject older configuration formats with reprovisioning advice, updating tests and documentation.
- Include prerequisite snapshot-restore, process-handling, and obsolete raw-restore cleanup changes.
| File | Description |
|---|---|
scripts/test-layout-allowlist.json |
Remove exemptions for hooks now used in production. |
scripts/test_microvm_tests.py |
Update format fixtures and remove raw-restore tests. |
scripts/nvx_tools/sandbox_ram_upper_tests.py |
Expect configuration format 10. |
scripts/nvx_tools/microvm_tests.py |
Remove the raw console-restore scenario. |
scripts/nvx_tools/microvm_test_scripts/run-console-restore.sh |
Delete the obsolete scenario script. |
scripts/nvx_tools/microvm_shards.json |
Remove the scenario and rebalance shards. |
nvx-rs/tests/cli/validation.rs |
Update refusals for named snapshot restores. |
nvx-rs/tests/cli/usage.rs |
Check restore options and removed flags. |
nvx-rs/tests/cli/openvmm.rs |
Remove raw snapshot test helpers. |
nvx-rs/tests/cli/one_shot.rs |
Remove obsolete raw-restore cases. |
nvx-rs/tests/cli/lifecycle.rs |
Check network records and malformed configurations. |
nvx-rs/tests/cli/formats.rs |
Check format 10 and older-format recovery advice. |
nvx-rs/tests/cli/dry_run.rs |
Remove unsupported restore dry-run cases. |
nvx-rs/tests/cli/download.rs |
Check restore refusals before downloads. |
nvx-rs/tests/cli.rs |
Adapt restore-related diagnostic coverage. |
nvx-rs/src/host/vm/tests.rs |
Add a prepared-launch substitution helper. |
nvx-rs/src/host/vm.rs |
Make owned-child access private. |
nvx-rs/src/host/tests.rs |
Add shared spawn-lock test helpers. |
nvx-rs/src/host/template/mod.rs |
Remove the attachment-reader re-export. |
nvx-rs/src/host/snapshot/manifest/tests.rs |
Test attachments through the strict manifest reader. |
nvx-rs/src/host/snapshot/manifest.rs |
Remove the raw-restore attachment reader. |
nvx-rs/src/host/restore_driver.rs |
Remove the unused-code allowance. |
nvx-rs/src/host/platform/windows/tests.rs |
Remove tests for the deleted foreground launcher. |
nvx-rs/src/host/platform/windows/spawn.rs |
Delete obsolete foreground-spawn helpers. |
nvx-rs/src/host/platform/windows/mod.rs |
Remove the foreground-spawn re-export. |
nvx-rs/src/host/cli/tests.rs |
Validate the composed run-option list. |
nvx-rs/src/host/cli/snapshots/tests.rs |
Cover restore parsing and locked view cleanup. |
nvx-rs/src/host/cli/snapshots/capture/tests.rs |
Adapt tests to capture-only parsing. |
nvx-rs/src/host/cli/snapshots/capture.rs |
Delegate subcommand selection to the snapshot parser. |
nvx-rs/src/host/cli/snapshots.rs |
Add restore dispatch and snapshot-view management. |
nvx-rs/src/host/cli/session/tests.rs |
Check connection waits against process exit. |
nvx-rs/src/host/cli/session.rs |
Use verified processes instead of supervisor children. |
nvx-rs/src/host/cli/sandbox/state/tests.rs |
Check restored-source record round trips. |
nvx-rs/src/host/cli/sandbox/state.rs |
Introduce format-10 network records and validation. |
nvx-rs/src/host/cli/sandbox/options.rs |
Build and validate NetworkConfig directly. |
nvx-rs/src/host/cli/sandbox/one_shot.rs |
Delete the obsolete one-shot launcher. |
nvx-rs/src/host/cli/sandbox/mod.rs |
Pass network records and coordinate restores. |
nvx-rs/src/host/cli/sandbox/lifecycle/stop.rs |
Remove restored views under snapshot locks. |
nvx-rs/src/host/cli/sandbox/lifecycle/start.rs |
Drive restores and carry network records into runs. |
nvx-rs/src/host/cli/sandbox/lifecycle/mod.rs |
Carry network and source metadata through provision. |
nvx-rs/src/host/cli/run/tests.rs |
Cover shared restore parsing and snapshot NIC policy. |
nvx-rs/src/host/cli/network.rs |
Remove direct OpenVMM argument emission. |
nvx-rs/src/host/cli/mod.rs |
Dispatch snapshot capture and restore commands. |
nvx-rs/src/host/cli/download/github/tests.rs |
Guard concurrent spawns and check missing-curl errors. |
nvx-rs/src/host/cli/download/github.rs |
Spawn curl directly. |
nvx-rs/src/host/cli/download/git.rs |
Spawn Git directly. |
nvx-rs/src/host/cli/download/archive/tests.rs |
Protect archive-test spawns with the shared lock. |
nvx-rs/src/host/cli/download/archive.rs |
Spawn tar directly. |
nvx-rs/README.md |
Document network records and named restore behavior. |
doc/run.md |
Update format references and direct OpenVMM restore examples. |
Review effort: Balanced

Part of #1112: SL3.10b, step 2 of 3 (the CLI no longer uses the old launch, store or config APIs). Needs #1491 and #1489 (with #1486 and #1487), and is stacked on #1497.
What and why
SL3.10b removes the last uses of
nvx's old launch, store and config APIs from the CLI's four shared sandbox modules:host/cli/sandbox/{mod,options,state}.rsandsandbox/lifecycle/mod.rs. Its measured scope came to about ten times its estimate of 20 core lines, sinceSandboxLaunch,SandboxSettings,SandboxUpperandSandboxNetworkstill carry provision, start and the sandbox's record. The split of SL3.10b into three stacked pull requests, each with one goal, was approved for Pedro Henrique Penna (@ppenna):NetworkConfig, and the record to format 10.SandboxLaunch,SandboxSettingsandSandboxUpperleave the four modules for the CLI's record and aVmConfig.This step:
sandbox_network(sandbox/options.rs) returns thehost::config::NetworkConfigthat the VMs take, rather than the old plan'shost::sandbox::SandboxNetwork, after the checks thatSandboxNetwork::newmade, in the same order and with the same messages: the guest network, and that OpenVMM's options can express the policy (host::network::openvmm_arguments).nvx-rs runtakes it directly, andstartno longer converts one into the other.config.jsonrecords the CLI's own network options, as aNetworkRecord, in place ofSandboxNetwork's serde form, which it does not copy:--net,--network-egress,--network-ingress,--host-loopback,--network-proxyand the--host-loopback-forwardoptions as given, and the egress rules in OpenVMM's form, as the rule options gave them or a policy file compiled them, so no start reads that file again. Each start, and the record thatsandbox runwrites and reads back, rebuilds the options with the parser's own receiver,NetworkOptions::take, and builds the network from them withsandbox_network, as provision did.provisionandsandbox runpass the record inProvisionConfig.nullfor an option not given, andConfig::newbuilds the network as it reads the record, so a record whose options the parser orsandbox_networkrefuses fails assandbox configuration is malformedwhen it is read, as the old plan's network did.Record format 10. The record changes form, so the configuration moves from format 9 to format 10. #1076 is not backward compatible ("a deploy starts from fresh state"), and nothing that this workstream changes is deployed, so a format-9 record is refused rather than migrated, as format 8 was:
startfails withformat-unsupported,sandbox configuration has an unsupported format: PATH; deprovision the sandbox and provision it again, anddeprovisionstill removes the sandbox. The advice is new, for every unsupported format. The README's state-directory section anddoc/run.mdsay so. Format 9 and restored sandboxes exist only onfeature/nvx-refactor, which is not deployed:devrecords formats 1, 7 and 8 and restores no sandbox. Sodeprovisiondoes not read an older record either, not even the source of a format-9 sandbox restored by a build of this workstream, whose view of its snapshot it removes only once it reads that source; a cold format-9 sandbox, which has no view, deprovisions.Size. 119 core lines, 6 counted files:
sandbox/state.rs84,sandbox/mod.rs16,sandbox/options.rs11,sandbox/lifecycle/mod.rs3,sandbox/lifecycle/start.rs3 andcli/run.rs2. The public API,BOOT_CONTRACT_VERSIONandCONTROL_CONTRACT_REVISIONdo not change.Stack. #1491 (SL3.10a) and #1489 (SL3.8b, on #1487 and #1486) have not merged, so this branch sits on a temporary local base:
origin/agents/slim-sl3-10a-downloads-session(5fda1863414), with SL3.8a1 (8c9847b7b09), SL3.8a2 (bf63b6aaf7f) and SL3.8b (d2a2ef3266d) cherry-picked on top, conflicts resolved (f51ed641759,cd5f2f841a6,2b4bec6c983), and one local stand-in,0ecbfe0750c, that deletessandbox::one_shotand Windowsspawn_foreground/standard_handle, which SL3.4b and SL3.8b leave unused and SL3.8b's own pull request deletes. Then #1497's commit (e908c5b9e44), and this one. Review only the last commit,d5fdcc648f0; the branch is rebased onto the merged inputs before it leaves Draft.Validation
At this head (
d5fdcc648f0), on the temporary base above, from this branch's action definitions:cargo fmt --check; Clippy with-D warnings(--all-targets --all-features,--lib,--lib --no-default-features,--lib --bins --features cli,--lib --bins --no-default-features --features testing);cargo test --all-features(lib 1478,cli110) andcargo test; the--lib --no-default-featuresbuild and tests; the bundled-artifacts test;cargo docwith-D warnings; MSRV 1.89; the runtime adapter's protocol-only and host-only configurationshost::cli::snapshots::capture::tests::a_capture_ack_and_successful_output_without_timely_exit_are_stopped_but_never_finished, which fails at the temporary base too (SL3.10a's; #1495 fixes it)compileall, the 22scripts/test_*.pymodules (1830 tests),test_adversarial.py,test_hosts.py,nvx.pyhelpnvx-rsof thesandbox-ram-uppertests, which still recorded format 9; fixed herecheck_test_layout.py,check_markdown_links.pyguest::unit tests ofcargo test --all-features(lib 2291 passed,cli119) and the 26 ofnvx.py check-guest-binaries, which fail on that host at the base too; none touches the CLInvx.py test-microvm --backend kvmwith the public sandbox scenariosmanaged-exec-config,sandbox-lifecycle,sandbox-proxy-onlyandsandbox-ram-uppernvx-rsand the Alpine initramfs built at this head; OpenVMM, the kernel and the scratch template of releasev0.1.0-dev.53ad09678bc1, which pins the same OpenVMM; the Ubuntu distro layer offeature/nvx-refactord4edeeb9ab9's CI run, whose guest inputs this branch keepsA code review found that a hand-edited record could leave out a network field, such as
egress, which then defaulted to allow, and that a network that its checks refuse failed only later, with another code. The record now requires every field and builds the network when it is read, as above, andmalformed_configurationcovers both.Left to CI: MSHV and WHP.
Tests modified
check_test_changes.py --base e908c5b9e44lists 12 changes to existing tests, for the record's new form and format:minimal_configandconfigurations(tests/cli/lifecycle.rs): the expected records take format 10, and the network and proxy-only cases theNetworkRecord; their starts still launch OpenVMM with the same network options.malformed_configuration: the format cases take 10 ({"format": 11},{"format": 10.0}), and four new cases refuse network records without a field, of a gateway address, with another egress, or with a broken rule as malformed. Without the check when the record is read, start accepted the record withoutegress, and allowed egress.configurations_of_every_format_start_and_exec(tests/cli/formats.rs): asserts format 10.old_configuration_formats_are_refused_without_migration: adds format 9 and the advice, which it lacked before.RamUpperAcceptance.check_managed(scripts/nvx_tools/sandbox_ram_upper_tests.py) expects format 10, and the fakenvx-rsof its tests (_FakeRamUpperSandboxCli._provision,scripts/test_microvm_tests.py) records 10, and 9 as its old format.a_one_off_restore_installs_the_network_options_of_run_as_its_own_policy(start/tests.rs) takes theNetworkConfigdirectly; it anddeprovision_removes_a_restored_sandboxs_view_only_under_its_snapshots_lock,run_checks_again_that_its_shares_do_not_overlapandrestored_sandbox_records_round_trip_only_their_own_sourcegiveProvisionConfigitsnetwork: None, and the imports follow.