Repository navigation
Description
Parent: #1085, in #1076. Needs: #1105, #1113, #1115, #1116. Unblocks: #1110, #1111, #1114, #1118, #1123, #1130.
Goal. nvx-init serves NVXC's capture request: it refuses while an execution runs or, when the request asks, kills the process groups and sweeps; then it calls snapshot::capture, following the transport rule. A restored nvx-init takes the session's reset, attaches again and accepts the activate message; then, in order: Activation::new, whose deadline counts from the repair's acknowledgement, its space's apply, the runtime mounts, the announcer when listeners are published, the switch, complete and Ready. The host then sends MAPS and Start. A Fresh capture VM's nvx-init assembles no root and waits for the capture request; only a restore's activation applies a root. Then the initramfs includes nvx-init, and the shell /init hands it each VM with nvx_sandbox=1 and no OpenVMM lifecycle token: the new launches' layered roots and the capture VMs. The old CLI's layered launches carry that token, and keep the old layered init until #1110 and #1111 replace them and #1122 removes the route.
Notes.
- The transport rule. The guest answers the capture request, then sends nothing until
capturereturns. AfterRestored, it takes the session's reset and attaches again; afterContinuedorResumed, it reports on the same session. AfterMustEnd { status }, it starts nothing and powers off with that status. - The test adapter's guest moves from
/sbin/nvx-init-agentto/sbin/nvx-init, until nvx-rs slimming 4.1.2: the test adapter is gone #1119. - The old CLI's launches keep the old guest path. Only they pass OpenVMM's lifecycle token, so the shell
/initstill hands both kinds of layered root to the old layered init. The oldsandbox starttakes its managed invocation into the managed agent's sandbox mode; the oldsandbox runtakes its one-shot invocation through the container helpers. Both remain until their callers are replaced. VMs withoutnvx_sandbox=1, such asnvx-snapshot's tests and benchmarks, keep their blockless path.
PRs, in order. Each PR has one goal, leaves dev green, and names in its description each old test of its area as kept, rewritten or retired, with each change that check_test_changes.py reports. Its tests follow the repository's test layout: a module's unit tests, and the code that only they use, sit in its tests.rs or tests/ and move with it. The estimates count core lines (code, not comments, docs or tests) and counted files; each PR records its measured values. Each PR does what its Scope says and no more: a case, input or layout that its Scope doesn't name, and whatever "Not in this PR" lists, is out of scope. Address every review comment within the scope, and ask before acting on one that asks for more. A PR whose measured core lines pass the stop that its Estimate names (twice the estimate, at most 600) stops and asks before continuing.
-
SL7.7a:
nvx-initcaptures a snapshot when the host asks.- Objective:
nvx-initserves the host's capture request and gives a Fresh capture VM a boot path that waits without constructing a root. It refuses unsafe captures, optionally kills and sweeps workloads, calls the snapshot library once, and follows the required session behavior for every result. - Contents: It serves NVXC's capture request (SL4.2): it refuses while an execution runs, or, when the request asks, kills the process groups and sweeps; then
snapshot::capture, following the transport rule. AfterMustEnd { status }, it starts nothing and powers off with that status. A Fresh capture VM, whose command line holdsnvx_snapshot_tier=platformand no root, view, mapping or workload token, enters this loop at boot: nvx-init mounts no image, scratch or export, assembles and switches no root, and waits for the request; only a restore's activation applies a root (SL7.7b). - Scope:
- Capture-request handling and the Fresh capture boot entry in
guest::init. - Refusal while an exec runs unless the request asks to kill, followed by process-group termination and SL7.5c's repeated sweep.
- One call to
snapshot::captureafter the guest acknowledges the request, with no guest message sent until it returns. ContinuedandResumedreport on the same session;Restoredtakes the session reset and attaches again.MustEnd { status }starts nothing and powers off directly with that status.
- Capture-request handling and the Fresh capture boot entry in
- Not in this PR:
- Applying and switching a restored root, activation replay, Ready, MAPS, and Start, which SL7.7b adds.
- Freezing, thawing, renewing, or coordinating workspaces:
nvx-inithas none. - Capturing while an exec continues, checkpointing process state, or preserving detached processes: the request is refused or all unregistered processes are killed.
- Root-token fallbacks for Fresh capture VMs: their command line has
nvx_snapshot_tier=platformand no root, view, mapping, or workload token. - Mounting an image, scratch, export, shares, or runtime root before a Fresh capture: only restore activation creates that space.
- Approach: Extend the shared loop with the one capture request and call the existing
snapshot::captureAPI. Track whether an exec is active; either refuse or invoke the existing group kill and sweep before capture. Select the Fresh entry from the fixed capture command line and bypass cold-root construction entirely. Do not add workspace machinery, process checkpointing, or another snapshot layer. - Done when:
- A capture is refused while an exec runs, while a kill request ends its process group and sweeps every unregistered process.
- The guest acknowledges the request, sends nothing until
snapshot::capturereturns, and reportsContinuedandResumedon the same session. - A restore takes the session reset and attaches again;
MustEndpowers off with its status without starting work. - A Fresh capture command line reaches the capture loop without mounting image, scratch or export, assembling a root, or switching.
- Needs: SL7.6b, in nvx-rs slimming 3.3.2: the managed agent's direct mode runs on nvx-init's exec core #1116; SL7.4b, in nvx-rs slimming 2.4.2: activation holds no fence, and a capture is one guest call #1105; SL4.2, in nvx-rs slimming 3.2.1: NVXC asks for a capture and activates a restore, and a blocking driver restores #1113.
- Estimate: 300 core lines, 2 counted files. Past 600 core lines, stop and ask before continuing.
- Objective:
-
SL7.7b: A restored
nvx-initactivates, switches and reports Ready.- Objective: After snapshot repair,
nvx-initaccepts the restore activation, applies and switches the requested space once, and reports Ready before serving MAPS, Start, and exec. Retries after a lost session join the same activation, whose timeout remains anchored to the repair acknowledgement. - Contents: It takes the session's reset and attaches again; accepts the activate message, where a retry with the same bytes on a later session joins the activation in progress; then
Activation::new(&repaired, timeout, now), whose deadline counts from the repair's acknowledgement and doesn't restart with a new session, and the space'sapply, with the restore's own network policy (its DNS and published listeners),mount_runtime, the announcer when listeners are published,switch,completeand Ready, in that order; then the host sendsMAPSand Start. nvx-init has no workspace, so it has nothing to thaw or renew. It keepsApplied, the mapper and itsMappingTable, the source root, the helpers and theActivation. - Scope:
- The restored-session and activation state in
guest::init, integrated with the shared NVXC loop. - A same-bytes activate retry on a later session joins the activation already in progress without applying the space twice.
Activation::new(&repaired, timeout, now)uses a deadline counted from the repair acknowledgement, not from a replacement session.- The ordered steps are space apply with the restore's DNS and published listeners, runtime mounts, optional announcer, switch, complete, and Ready.
- The live state retains
Applied, the mapper and publicMappingTable, source root, helpers, andActivation; MAPS and Start then permit an exec.
- The restored-session and activation state in
- Not in this PR:
- Workspace thaw, renewal, or
after_restorehooks:nvx-inithas no workspace. - Applying the same activation twice, restarting its timeout on reconnect, or accepting different activate bytes as a retry.
- Starting an announcer without published listeners, or using detached
nvx-ingress start: SL7.5d supplies the retained helper step. - Cold-boot root assembly, whose tokens and sequence belong to SL7.5b.
- Host restore orchestration or new protocol messages: this PR implements the guest side of the existing activate, Ready, MAPS, and Start sequence.
- Workspace thaw, renewal, or
- Approach: Keep one activation object and one in-progress result across guest sessions. Feed the repaired snapshot and original acknowledgement time to the existing sans-I/O
Activation, then call the space andguest::initannouncer steps in their fixed order. Retain the resources the later MAPS and exec paths use. Do not add a workspace abstraction, retry database, or second restore state machine. - Done when:
- A restored guest resets and reattaches, and the activation deadline remains based on the repair acknowledgement.
- A same-bytes retry after session loss joins the in-progress activation and does not apply or switch twice.
- Tests observe apply, runtime mounts, optional announcer, switch, complete, and Ready in order.
- After Ready, MAPS and Start complete and an exec runs through the shared core.
- The restored root and upper are applied and switched exactly once.
- Needs: SL7.7a, above; SL7.3, in nvx-rs slimming 2.4.2: activation holds no fence, and a capture is one guest call #1105; SL7.5d, in nvx-rs slimming 3.3.1: nvx-init boots a layered root, and runs each exec as a plain process #1115.
- Estimate: 300 core lines, 2 counted files. Past 600 core lines, stop and ask before continuing.
- Objective: After snapshot repair,
-
SL7.8a: Layered roots and capture VMs boot through
nvx-init.- Objective: Guest images contain
nvx-init, and the shell/initroutes only the new layered launches and Fresh capture VMs to it. Old CLI layered launches and ordinary blockless VMs keep their current paths, while the test adapter overlays the new binary path. - Contents: The initramfs build includes nvx-init. The shell
/inithands nvx-init, with the helpers' process IDs (the time daemon's, and the announcer's when listeners are published), each VM whose command line holdsnvx_sandbox=1and no OpenVMM lifecycle token: the new launches' layered roots, and Fresh capture VMs, which reach its capture entry (SL7.7a). A layered root with OpenVMM's lifecycle token comes only from the old CLI'ssandbox startorsandbox run, which SL3.5b and SL3.4b replace; it still goes tonvx-init-agent, until SL6.3 removes that route. A VM withoutnvx_sandbox=1keeps its blockless path, sonvx-snapshot's tests and benchmarks don't change. The test adapter, which lives until SL5.2, overlays its own guest at/sbin/nvx-initinstead of/sbin/nvx-init-agent(tests/runtime-adapter/src/initramfs.rs). - Scope:
scripts/nvx_tools/build.pyinstalls thenvx-initRust binary into each applicable initramfs.guest/common/initroutesnvx_sandbox=1without an OpenVMM lifecycle token to/sbin/nvx-initand passes the time daemon's process ID plus the announcer's when present.- Fresh capture VMs on that route reach SL7.7a's rootless capture entry.
- Layered roots carrying the old OpenVMM lifecycle token still run
/sbin/nvx-init-agent; VMs withoutnvx_sandbox=1retain the blockless path. tests/runtime-adapter/src/initramfs.rsoverlays its layered guest at/sbin/nvx-init, with its archive tests updated.
- Not in this PR:
- Deleting
/sbin/nvx-init-agent, the container helpers, or the managed agent's sandbox mode; SL7.8b removes them after the old route disappears. - Routing every
nvx_snapshot_tier=platformVM tonvx-init: blocklessnvx-snapshottests and benchmarks must keep their path. - Teaching
nvx-initthe old CLI's lifecycle tokens or aggregate-share format: those launches stay on the old init until their callers change. - Changing the old
sandbox startmanaged invocation orsandbox runone-shot invocation. - Changing the adapter's guest protocol or archive format: only its overlaid init path changes.
- Deleting
- Approach: Add the already-built binary to the existing fixed guest-binary installation list, then make one explicit shell routing test from
nvx_sandboxand the presence of the old lifecycle token. Pass the known helper PIDs as fixed arguments. Update the adapter's existing symlink target constant; do not add command-line discovery, compatibility translation, or another launcher. - Done when:
- The built initramfs contains
/sbin/nvx-init. - The shell hands
nvx-initthe time daemon's process ID and the announcer's process ID when listeners are published. - A tokenless layered root and a Fresh capture VM boot through
nvx-init, while an old-token layered root still usesnvx-init-agent. - A VM without
nvx_sandbox=1keeps its blockless path, includingnvx-snapshottests and benchmarks. - The runtime adapter's initramfs tests expect its layered overlay at
/sbin/nvx-init.
- The built initramfs contains
- Needs: SL7.7b, above.
- Estimate: 100 core lines, 3 counted files. Past 200 core lines, stop and ask before continuing.
- Objective: Guest images contain
Tests. A capture is refused while an execution runs. A capture that asks kills the executions' process groups, then sweeps every other process but PID 1 and the registered helpers. The guest answers the request, then sends nothing until capture returns; it reports Continued and Resumed on the same session, and powers off with the status of MustEnd. A restore takes the session's reset and attaches again, and its activation deadline stays counted from the repair's acknowledgement. A retry of the activate message with the same bytes, after a lost session, joins the activation in progress without applying the space twice. The activation's steps run in order to Ready; nvx-init then takes MAPS and Start, and runs an exec. The built initramfs holds /sbin/nvx-init, and the shell /init hands it the time daemon's process ID, and the announcer's when listeners are published. A layered root without OpenVMM's lifecycle token boots through it; one with the token still boots through the old layered init: the old sandbox start uses its managed invocation and the managed agent's sandbox mode, and the old sandbox run its one-shot invocation and the container helpers; and a VM without nvx_sandbox=1 keeps its blockless path. A VM booted with a Fresh capture's command line (nvx_sandbox=1 and nvx_snapshot_tier=platform, with no root, view, mapping or workload token) reaches nvx-init's capture loop: no image, scratch or export is mounted and no root is switched before the capture, and its restore applies the requested root and upper and switches once before Ready. The test adapter's initramfs tests expect /sbin/nvx-init.
Done when: every PR above has merged, with dev green.
Activity
esaurez commentedon Nov 10, 2026
Workstream source/progress checkpoint - 2026-11-10 UTC
Checked boxes below mean merged scope, not merely an implemented first iteration. Implementation branches are source checkpoints, not automatic qualification, Ready or merge approval. Some starting inputs are frozen/anonymous commits rather than standalone branches; their exact SHAs and known merged producer refs are recorded explicitly.
SL7.7a - First implementation committed; not merged.
esaurez/slim-3.3.3-sl7.7a-20261108; exact headf61c8708e84074bbd42fef9aad73f28bef8ca84c.ddd62a60d043f8e7ce12065d0d07e0d1794c7fd4.3ad5e49df09ff3e1d5a702260ba127fc521d962d;esaurez/slim-3.3.2-sl7.6b-e7-20261107atc126635f797706afb1f3dcc5d9ce5359f93458d8.SL7.7b - First implementation committed; not merged.
esaurez/slim-3.3.3-sl7.7b-20261108; exact headcc6e468b106615d07cff536a45b8f3ec061d0398.f401af803aa2ac8f308c588e664e64bdb8f40616.SL7.8a - First implementation committed; not merged.
esaurez/slim-3.3.3-sl7.8a-private-20261108; exact headd580123a8bc7f6b1a75de9a658c8a0b4c715d23e.esaurez/slim-3.3.3-sl7.7b-20261108; exact commitcc6e468b106615d07cff536a45b8f3ec061d0398.The original technical scope remains authoritative, supplemented only by any portable technical clarification in this issue. No machine-specific execution policy is part of this checkpoint.
ppenna commentedon Nov 11, 2026
All three PRs of this group have merged into
feature/nvx-refactor: SL7.7a (#1431), SL7.7b (#1447) and SL7.8a (#1453).The feature branch's post-merge CI run at
394c89025e, which contains all of them, passed: https://github.com/microsoft/nvx/actions/runs/42952780739. Closing this group as complete;devreceives it whenfeature/nvx-refactorlands there.