Skip to content

host: render cold boots from runtime and VM configuration - #1334

Merged
Pedro Henrique Penna (ppenna) merged 10 commits into
feature/nvx-refactorfrom
esaurez/slim-2.1.2-sl2.4c-20261107
Nov 8, 2026
Merged

Pedro Henrique Penna (ppenna) merged 10 commits into
feature/nvx-refactorfrom
esaurez/slim-2.1.2-sl2.4c-20261107

Conversation

@esaurez

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

Copy link
Copy Markdown
Contributor

Part of #1098 (SL2.4c).

Render a non-capture cold boot's complete OpenVMM argument list from Runtime and
VmConfig before any host state changes. The only additional inputs are
borrowed, already-selected control, report, and optional console output names;
the renderer opens no files, allocates no endpoints, and starts no process.

  • Render processors, full-width memory, kernel/initramfs and kernel command
    line, path-based block devices, blockless/layered roots, existing network and
    export arguments, both console attachments, CPU profile, and every
    LaunchOptions value. Never emit --microvm-lifecycle or
    --microvm-workload-identity.
  • Add VmConfig::check_command_line() on every host with the existing
    2048-unit reserve; check the complete rendered argv against the Windows
    UTF-16 limit without a reserve. Preserve quoting and terminating-NUL counting.
  • Move the public command-line counting helpers to host::config, retaining
    their existing host::launch aliases and shared legacy launch assembly.
    VmConfig::openvmm_arguments is temporarily public until SL2.8 integrates it
    into host::vm::create; individual device lowerings remain internal.
  • Update both public-API snapshots and document exact whole-millisecond
    authentication timeouts and status-bearing guest power-off behavior.

Based on feature/nvx-refactor at
aa6bb42bc0932e7e861da399df993db6e61ef00a, where #1332 landed by squash.
The old parent and landed base have the same tree. The initial nine-commit
replay needed no source changes; the follow-up below adds only narrow native
argument representability refusals. Opening devices, final-path resolution,
VM-directory creation, spawning, restore compatibility, and policy
normalization are not changed.

Tests

An inherited refactor moved the sandbox specification test module declaration
from nvx-rs/src/host/sandbox/mod.rs to
nvx-rs/src/host/sandbox/tests.rs, and its source from
nvx-rs/src/host/sandbox/specification.rs to
nvx-rs/src/host/sandbox/tests/specification.rs. The test cases were relocated
unchanged, not deleted; both sandbox test files are unchanged by this PR.

process_command_lines_are_measured_as_windows_quotes_them moves from
host::launch::tests to host::config::tests. Its five existing cases and
assertions are preserved, with empty-program/argument, tab, and supplementary
Unicode cases added. a_process_command_line_fits_while_it_leaves_its_reserve
moves to the same owner unchanged; no coverage is retired.

Focused renderer tests cover all rendered settings/options, both console
attachments, forbidden flags, full-width memory, layered paths and exports, a
deny-all NIC, exact timeout bounds, invalid required names, and portable
fitting/reserved/oversized command lines. The cold and values helpers are
local to these tests; the inherited runtime helper is reused with the same
paths and launch options instead of duplicated. Cold-only fixtures explicitly
set capture: None. Existing assertions, configuration, and legacy launch
behavior are retained.

The additional
cold_boot_arguments_refuse_disk_syntax_in_image_and_scratch_paths
regression covers comma/semicolon/unbalanced-bracket refusals for both paths
through both public entry points, plus literal paths with spaces and balanced
nested brackets. It failed on the original renderer before the fix and passes
after it. The correction reuses the existing pure disk-path validator, moved
to configuration ownership with an internal sandbox re-export to preserve
existing callers and avoid a module cycle. No host I/O or path resolution is
added.

cold_boot_command_lines_refuse_native_control_console_syntax additionally
covers double-quote and standalone -- refusals through both native-launch
entry points with either console attachment. It preserves caller-owned
VmConfig::check and kernel_command_line projection and accepts native
near-miss forms, including single quotes, embedded markers, and non-delimiter
names. This regression failed on 506ce49c before the correction and passes
after it. Only the cold renderer fixture and its exact expected argv replace
the unsupported quoted argument with nvx_arg=ab; the parent projection
fixtures and existing assertions are unchanged.

Two further focused regressions address native argument representability:
native_argument_listener_names_are_distinct rejects identical listener
names and ASCII-case aliases for the declared WHP runtime, retaining Linux
case-sensitive names and disconnected consoles.
native_argument_paths_require_unicode rejects invalid Unix bytes and
unpaired Windows UTF-16 image/scratch paths through both entry points while
retaining valid Unicode names, spaces, and balanced brackets. Both tests
failed on 1819ddaf before the correction and pass after it. Unicode refusal
is restricted to the new path-based device lowering; the legacy shared
disk-path validator, its aliases, and parent configuration/kernel projection
remain unchanged. No endpoint allocation or path canonicalization is added.

cold_boot_arguments_refuse_non_raw_block_extensions covers the pinned native
backend selection through both public entry points. Lower-case .vhd, .vhdx,
.vmgs, and .vmdk image and scratch paths are refused; lower-case .iso is
refused only for writable scratch. Read-only distro ISO paths and upper-case
extensions remain valid. The regression failed on public head d1d803a7 before
the correction.

Independent review found that the first correction, b059f8c0, also widened
the legacy sandbox wrapper to .vmdk.
legacy_container_path_preserves_its_extension_policy failed on that head.
a50e16fd keeps VMDK refusal on the new cold-boot renderer while restoring the
legacy sandbox, template, and clone set to .vhd, .vhdx, .vmgs, and .iso.
No path probing, canonicalization, or native policy change is added.

The rebase preserves the parent's capture and restore definitions, tests, and
public host::launch::COMMAND_LINE_BUDGET alias.
cold_boot_arguments_refuse_capture_configurations uses the inherited
captured() fixture: parent configuration checking and kernel projection
still succeed, while both temporary argument entry points refuse the capture
as Unsupported rather than silently omit its devices and resource capacities.
This regression failed on a919db3e before the pure shared guard; no capture
renderer or parent capture-policy change is added.

native_argument_exports_require_unicode covers a read-only export with an
empty bind source and no policy paths: parent configuration checking and kernel
projection remain valid, while both whole-config argument entry points refuse
a non-Unicode child root before inherited string lowering can replace its
characters. Valid Unicode and spaces retain the exact selected directory.
Parent filesystem checks and legacy export/launch behavior are unchanged.

native_argument_listener_names_refuse_serial_delimiters covers commas and
equals signs in both the selected control and boot-console names. The shared
pure guard refuses those native serial-option delimiters before formatting
listen=...; valid Unicode and spaces remain literal. Existing empty/NUL and
distinct-listener checks are retained. No endpoint allocation, canonicalization,
backend parser change, or new launcher framework is added.

Both new regressions failed before their guards, then all four selected native
argument tests passed on Windows after the fix. Existing fixtures, cases,
assertions, and public API snapshots are unchanged.

The current test-change inventory reports one modified test (relocated), one
unchanged relocation, and 18 added items; no coverage is retired.

Size: 378 core lines in 3 counted files, 9 changed paths, measured over the
complete change against aa6bb42bc093, including all moved argument assembly,
counting code, disk-path validation, and the shared native-launch checks.

Validation

Current head d86792ecfdea34dbc9ade4f8dd79d54759055dab has source tree
615cb660ea722165e09e046b69e2f12c633b026d and retains OpenVMM
14dc4116ec7e57567633c4b7b07892aca3a58522. The initial ancestry-only replay
was ac93c908665c2491e1b600a58fd8b59166b8abe2; this follow-up changes 11 core
lines in one counted file, plus its documentation and two new regressions.
API signatures, parent configuration/legacy paths, guest/runtime inputs, and
launch aliases are retained.

The actual Windows regression selector ran four tests: before the guards,
2 passed and the 2 new regressions failed; after the guards, all 4 passed,
with no ignored tests. Current verification, formatting, test layout, Markdown
links, exact-base test inventory, and diff checks passed. The full Windows
Rust/adapter action result remains pending in this publication report; no
completed full-action pass is asserted. This exact version is being published
as requested without waiting for that result.

The completed Ready-triggered CI run at ac93c908 was successful but remains
old-head evidence. A separate current-head CI run on this PR branch is used
for this correction; Draft-skipped runs, old-head results, and historical
independent/Copilot reviews are not promoted to current-head approval.

Historical exact-input execution evidence, not new full-action or VM runs:

Previous head efa7e62725ba512f48370efc6c8aa8d1665eee47 passed the complete
Rust/adapter actions on Windows (24 commands) and Linux (37 commands),
including warning-denied feature checks and documentation, MSRV, both public-API
snapshots, macOS, static guest checks, and all runtime-adapter configurations.
All 36 configuration cases passed on both hosts, including the capture
refusal, preserved capture behavior, and previous native-input regressions.
The all-feature library runs passed 1,257 tests on Windows (6 ignored) and
2,004 on Linux (33 ignored), with every integration target passing.

The retained Linux quality action passed all 14 commands, including 25 Specula
tests and all six PowerShell syntax checks. Test layout, the exact-base
test-change inventory, and diff checks passed. Both hosts also passed all
three OpenVMM protocol-vector comparisons and the CPU-profile comparison
against the unchanged native pin. Exact-head independent read-only review
reported no findings after the capture omission was corrected.

The complete CLI actions ran at a919db3e immediately before the capture
guard: 1,818 unit tests on each host (70 Windows / 39 Linux skips), 84
adversarial tests (11 Windows / 0 Linux skips), four host tests, and all
command-help checks. Those results are retained for their exact unchanged
CLI/script/guest input components, not relabeled as executions at the final
head. The new guard is used only by the two temporary whole-config methods;
Rust/adapter checks at that retained head covered the capture-guard source.

The native-launch syntax guard mirrors the pinned control-console builder's
double-quote and ASCII-whitespace-delimited -- rule. The portable reserve
checks the Windows UTF-16 budget, not all native kernel-byte or profile-token
limits. Already-selected listener names are compared without host I/O;
native backend-name validation and canonical endpoint checks are not replaced.
No direct native boot of the temporary whole-config renderer was run.

Historical runtime checks at
a7f9eaa9d4a79af82ef772974db7866c0d4a187e passed 11 selected cold-boot/argument
scenarios, 13 records per WHP/MSHV backend at one and two processors, including
all four public sandbox scenarios, with setup/teardown and no skipped
scenarios. They exercised the existing CLI/launch paths, not the new
whole-config entry point, and remain evidence of that original input rather
than proof of the rebased integration.

Those runs used each host's source-built CLI and guest artifacts with
hash-verified prebuilt OpenVMM
14dc4116ec7e57567633c4b7b07892aca3a58522 and matching kernel/configuration
inputs. Artifact-level source/ABI/hash provenance was verified; the native
producer's complete compiler/build recipe was not reconstructed.

Skipped tests remain skips. KVM, new-head VM matrices, unrelated full-group
distro/runtime-adapter VM suites, and performance checks were not run. The
retained runs do not claim current-head CI results. The observed Draft state
is preserved; current-branch CI and current-head review results remain separate
from these historical local executions. No merge or release publication is
part of this update.

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

github-actions Bot commented Nov 7, 2026 •

Copy link
Copy Markdown
Contributor

This pull request changes existing tests

It modifies or removes 1 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 test fn process_command_lines_are_measured_as_windows_quotes_them in host::launch::tests (moved) nvx-rs/src/host/launch/tests.rs:118 nvx-rs/src/host/config/tests.rs:1998

Relocated unchanged: 1; added: 18. Compared the merge base aa6bb42bc093 with d86792ecfdea.

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.

🟡 Changes recommended

Layered image and scratch paths lack disk-syntax validation, allowing configured filenames to be interpreted as OpenVMM options, including unintended scratch-file creation.

1 open issue
What changed in this PR

This PR advances #1098 by adding a pure cold-boot OpenVMM argument renderer based on Runtime and VmConfig, ahead of integration into VM creation.

Changes:

  • Render devices, boot inputs, consoles, and launch options without host-side effects.
  • Add portable command-line checks and move counting helpers into host::config, preserving legacy aliases.
  • Extend renderer tests, update API snapshots, and clarify timeout and guest shutdown documentation.
File Description
nvx-rs/​src/​host/​runtime/​mod.rs Clarify shutdown behavior and authentication timeout bounds.
nvx-rs/​src/​host/​launch/​tests.rs Move command-line counting tests to configuration ownership.
nvx-rs/​src/​host/​launch.rs Reuse shared argument assembly and retain public helper aliases.
nvx-rs/​src/​host/​config/​tests.rs Add renderer coverage and extend relocated counting tests.
nvx-rs/​src/​host/​config/​mod.rs Implement cold-boot rendering and portable command-line checks.
nvx-rs/​README.md Document rendering, validation, and compatibility behavior.
nvx-rs/​public-api/​windows.txt Record the new configuration APIs on Windows.
nvx-rs/​public-api/​linux.txt Record the new configuration APIs on Linux.

Review effort: Balanced

Comment thread nvx-rs/src/host/config/mod.rs Resolved

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.

🟡 Changes recommended

Rendering accepts kernel command lines containing double quotes or standalone -- that the pinned OpenVMM control-console path rejects, causing native cold-boot configuration failures.

1 open issue
1 resolved since last review

Review effort: Balanced

Comment thread nvx-rs/src/host/config/mod.rs Resolved

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

Configuration validation still accepts non-UTF-8 image or scratch paths and duplicate boot/control listener endpoints, producing arguments that OpenVMM rejects and preventing launch.

No open issues 🎉

2 previously missed issues

In code that hasn't changed since last review

Medium severity Reject duplicate listener endpoint names

nvx-rs/​src/​host/​config/​mod.rs:249

With ConsoleAttachment::Listener, passing the same name for endpoint and console_endpoint succeeds and renders two listeners for one endpoint. The pinned OpenVMM explicitly rejects this with “microVM boot and control consoles require distinct endpoints”, so this result cannot launch even when the endpoint's parent and all runtime files are valid. Reject identical names here (including case-insensitive named-pipe aliases on Windows); this can be checked without host I/O or final-path resolution.

Medium severity Reject paths with invalid UTF-8 bytes

nvx-rs/​src/​host/​config/​mod.rs:505

A layered image or scratch path containing invalid UTF-8 bytes passes both renderer checks because this guard validates replacement-decoded text, while the emitted argument preserves the original bytes. OpenVMM parses --microvm-sandbox-block through FromStr, so it cannot accept that argument and the cold boot fails. Reject paths for which path.to_str() returns None in this shared guard, covering both check_command_line() and openvmm_arguments() without host I/O.

1 resolved since last review

Review effort: Balanced

@esaurez

Copy link
Copy Markdown
Contributor Author

Addressed both additional native-argument issues from review 5810853245 in d1d803a.

The whole renderer rejects identical boot/control listener names and ASCII-case aliases for the declared WHP runtime, retaining case-sensitive Linux names and disconnected consoles. Shared path-based device lowering now refuses non-Unicode image and scratch paths before emitting OpenVMM's string-parser arguments. The legacy disk-path validator and aliases, and caller-owned configuration/kernel projection, are unchanged.

Both new regressions failed on 1819dda before the correction. All 25 configuration tests and the complete affected Windows/Linux Rust actions now pass, including valid Unicode paths and existing refusal/projection coverage. The Tests/Validation disclosure was updated without changing the rest of the PR.

This adds no host I/O, path canonicalization, native change, or blanket caller-token policy; it is not a claim of direct native-boot coverage for the temporary whole-config entry point.

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

Human assessment is needed because listener parsing can collapse distinct names into conflicting endpoints, while accepted scratch paths can select disk backends that reject writable use.

No open issues 🎉

Review effort: Balanced

@esaurez

Copy link
Copy Markdown
Contributor Author

Assessment of review 5811050114: the source remains d1d803a.

Native serial option parsing can collapse names containing , or =, and canonical socket aliases can still refer to the same endpoint. Native disk opening also selects a backend from the path and performs writable/format checks; for example, a lower-case .iso path cannot be opened writable. These are real native-input/backend constraints, not certified by this pure argument renderer.

General listener normalization, final-path resolution, and native file/backend admission remain deferred to later integration. The current Tests/Validation section explicitly states that native backend-name and canonical checks are not replaced and that no direct native boot of the temporary whole-config entry point was performed.

The four previously reported concrete issues were addressed, with the old High threads resolved and the preceding summary replied to. This assessment does not imply formal approval, complete native-input validation, or runtime coverage for the remaining constraints.

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.

🟡 Changes recommended

Block-path validation accepts filename extensions that cause writable attachment failures or route raw images to incompatible backends, requiring shared extension checks and regression coverage for both entry points.

1 open issue

Review effort: Balanced

Comment thread nvx-rs/src/host/config/mod.rs Resolved

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

Human assessment is needed because a moderate endpoint-parsing finding that can cause listener collisions and launch failures was omitted from the published review.

No open issues 🎉

1 resolved since last review

Review effort: Balanced

@esaurez

Copy link
Copy Markdown
Contributor Author

Assessment of review 5816061044 at a50e16fd0ee12e6ce2adfe36867ccb2a3dc35dc7: it reports no open issues and created no unresolved thread. The resolved block-extension finding is addressed in this head, with its published reply and exact-head validation recorded above.

The endpoint-parsing note repeats the native-input limitation previously assessed in this comment, rather than a new actionable review finding. Selected boot/control names are already checked for equality and WHP ASCII-case aliases. Broader serial delimiter normalization and canonical endpoint-alias checks remain later integration work; the PR still states that native listener/backend-name and canonical checks are not replaced and that no direct native boot of the temporary renderer was performed.

No source change is needed for this summary-only note. This assessment is not a formal approval or a claim of complete native-input/runtime coverage.

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 remain for the configuration-driven cold-boot argument renderer and related compatibility changes.

No open issues 🎉

Review effort: Balanced

Base automatically changed from esaurez/slim-2.1.2-sl2.4b-20261106 to feature/nvx-refactor November 8, 2026 17:51
Enrique Saurez and others added 9 commits November 8, 2026 10:27
Derive whole cold-boot arguments from Runtime and VmConfig, borrowing only the caller-chosen output names. Retain the console device and configured NIC, lower block devices by path, and check the complete Windows command-line limit on every host.

Move the portable counting helpers to config while retaining the legacy launch paths and shared argument assembly. Add the reserved configuration-only check and document status-bearing guest power-off behavior.

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

Copilot-Session: 0325d032-38a9-4c7f-9899-687a4ec93a51
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 0325d032-38a9-4c7f-9899-687a4ec93a51
Reuse the pure disk-path validator for layered image and scratch arguments before either configuration preflight or whole rendering returns. Move the shared guard into config and retain its sandbox re-export, preserving diagnostics and host module layering.

Add a regression for disk delimiters and bracket balance through both entry points, including valid literal paths.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 0325d032-38a9-4c7f-9899-687a4ec93a51
Reject double quotes and standalone -- only in the cold renderer and command-line preflight, which always describe a control-console launch. Preserve caller-owned configuration checking and kernel projection, and replace only the cold-renderer fixture with a compatible token.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 0325d032-38a9-4c7f-9899-687a4ec93a51
Require Unicode path-based block arguments and distinct boot/control listeners, using the declared WHP runtime for ASCII-case-insensitive pipe names. Preserve configuration/kernel projection and the legacy disk-path guard; add no host I/O or canonicalization.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 0325d032-38a9-4c7f-9899-687a4ec93a51
Reuse pure block-path validation in both configuration entry points. Reject lower-case container backend extensions, including VMDK, and reject ISO only for writable scratch while preserving native case-sensitive raw paths and the legacy sandbox alias.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 0325d032-38a9-4c7f-9899-687a4ec93a51
Keep VMDK rejection on the new cold-boot configuration renderer, where OpenVMM selects its VMDK backend, without broadening the established sandbox, template, and clone snapshot policy. Add a regression for the legacy wrapper.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 0325d032-38a9-4c7f-9899-687a4ec93a51
Reuse the inherited runtime fixture instead of defining it twice, and explicitly leave capture disabled in the native control-console refusal cases. Keep the existing paths, launch options and assertions.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 0325d032-38a9-4c7f-9899-687a4ec93a51
Refuse capture-bearing configurations in the shared pure path used by both temporary argument entry points rather than silently omit their devices and resource capacities. Preserve configuration validation and kernel projection, and cover both refusals with a regression.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 0325d032-38a9-4c7f-9899-687a4ec93a51

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.

🟡 Changes recommended

Validation still accepts non-Unicode child roots and endpoint names containing commas or equals signs, allowing downstream conversion or parsing to target the wrong directory or endpoint.

2 open issues

Review effort: Balanced

Comment thread nvx-rs/src/host/config/mod.rs Resolved
Comment thread nvx-rs/src/host/config/mod.rs Resolved
@esaurez
Enrique Saurez (esaurez) marked this pull request as draft November 8, 2026 18:50
Refuse non-Unicode export child roots before string lowering and serial
option delimiters in caller-selected control and boot-console names.
Keep parent configuration checks and legacy launch behavior unchanged.
Add focused regressions for both argument entry points and listener roles.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 0325d032-38a9-4c7f-9899-687a4ec93a51

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 cold-boot argument renderer and related configuration updates.

No open issues 🎉

2 resolved since last review

Review effort: Balanced

@ppenna
Pedro Henrique Penna (ppenna) merged commit fdd642f into feature/nvx-refactor Nov 8, 2026
145 checks passed
@ppenna
Pedro Henrique Penna (ppenna) deleted the esaurez/slim-2.1.2-sl2.4c-20261107 branch November 8, 2026 21:25
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