From 6480fa77f2af202559a965b351c4d061514bcfcc Mon Sep 17 00:00:00 2001 From: Enrique Saurez Date: Thu, 22 Oct 2026 02:39:57 -0700 Subject: [PATCH 1/2] guest: map host paths beneath a managed sandbox's root The managed agent's sandbox mode gains the host mapping table of its direct mode. When the kernel command line announces mappings with nvx_maps=, the agent applies the ordered MAPS batches through the descriptor-rooted mapper beneath the container's assembled root, from the export that the guest mounts at /run/nvx/hostfs/root, with the direct mode's ordering and latching. It refuses the targets that the container runtime keeps, admits no workload until the whole table is mounted, and keeps refusing workloads after a failed mapping. When its session ends, the agent unmounts the mappings in reverse order before it returns to the init agent, which then unmounts the root, and reports each mapping that stays mounted. No launch announces mappings to a sandbox yet, so the agent does not advertise the feature in this mode until one does. Part of #622 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: e4de0d1f-0989-4804-ab6b-3c2891554406 --- nvx-rs/README.md | 10 +- nvx-rs/src/guest/managed_agent/diagnostics.rs | 9 + nvx-rs/src/guest/managed_agent/dispatch.rs | 177 +++++++++++++-- nvx-rs/src/guest/managed_agent/mappings.rs | 204 ++++++++++++++++-- nvx-rs/src/guest/managed_agent/mod.rs | 69 ++++-- 5 files changed, 409 insertions(+), 60 deletions(-) diff --git a/nvx-rs/README.md b/nvx-rs/README.md index 66c63bdbf..dcf51c843 100644 --- a/nvx-rs/README.md +++ b/nvx-rs/README.md @@ -89,7 +89,7 @@ nvx-rs/ | `nvx::testing::fake_openvmm` | A fake OpenVMM that serves the control console and runs scripted workloads without a VM, for direct launches and for the managed and one-shot sandboxes of `nvx-rs sandbox` and `nvx.py sandbox` | | `nvx::host::cli` | Feature `cli`: the `nvx-rs` executable; see [The nvx-rs CLI](#the-nvx-rs-cli) | | `nvx::guest` | The programs that run in Linux guests; see [Guest binaries](#guest-binaries) | -| `nvx::guest::mappings` | `Mapper`: applies host mappings for any guest init or agent beneath the descriptor of a `TargetRoot`, the root of a mount of a whole file system, which `statmount` tells from a bind of a directory below it, such as a layered root's overlay or a guest's `/`, from a `SourceRoot`, such as the guest's mount of the host's export. A `Mapping` names a relative source, an absolute target, its `Access`, and optionally the `Kind` that its source must have. The mapper opens each component with `openat2`, through no symbolic link or magic link, creates what a target lacks only on the root's own mounts, which `statx` tells apart by their unique mount IDs, never inside another mapping, and checks kinds, overlaps, and the targets that the root profile's `Reserved` set holds, with the `/run/nvx/time` tree and its ancestors always. It attaches each mapping as a detached copy of its source's mount, `open_tree`, restricted `nosuid`, `nodev`, and read-only when asked, `mount_setattr`, before `move_mount` puts it at its target, then checks that it is there. Zero mappings do no work; the first that fails is reported with its index as an `ApplyError`, and latches the mapper. `Mapper::teardown` detaches a mapping that a rename moved and that the attach failed to detach, then unmounts the mappings in reverse order, and reports each failure. `bind` applies one runtime bind through the same walk and attach. Linux 6.8 or later. NVX's managed agent applies its host mapping table through it beneath `/`, and a layered `Root` its live shares and mappings | +| `nvx::guest::mappings` | `Mapper`: applies host mappings for any guest init or agent beneath the descriptor of a `TargetRoot`, the root of a mount of a whole file system, which `statmount` tells from a bind of a directory below it, such as a layered root's overlay or a guest's `/`, from a `SourceRoot`, such as the guest's mount of the host's export. A `Mapping` names a relative source, an absolute target, its `Access`, and optionally the `Kind` that its source must have. The mapper opens each component with `openat2`, through no symbolic link or magic link, creates what a target lacks only on the root's own mounts, which `statx` tells apart by their unique mount IDs, never inside another mapping, and checks kinds, overlaps, and the targets that the root profile's `Reserved` set holds, with the `/run/nvx/time` tree and its ancestors always. It attaches each mapping as a detached copy of its source's mount, `open_tree`, restricted `nosuid`, `nodev`, and read-only when asked, `mount_setattr`, before `move_mount` puts it at its target, then checks that it is there. Zero mappings do no work; the first that fails is reported with its index as an `ApplyError`, and latches the mapper. `Mapper::teardown` detaches a mapping that a rename moved and that the attach failed to detach, then unmounts the mappings in reverse order, and reports each failure. `bind` applies one runtime bind through the same walk and attach. Linux 6.8 or later. NVX's managed agent applies its host mapping table through it, beneath `/` in direct mode and beneath the container's assembled root in sandbox mode, and a layered `Root` its live shares and mappings | | `nvx::guest::nvxs` | `GuestConnection`: the guest's role of the NVXS session over a byte stream, such as the control console, on which NVX's managed agent and other guest agents run their sessions. It never reads past the record in progress, so a caller that polls the stream between records sees every record that it has not returned | | `nvx::guest::terminal` | `Terminal`: the terminal on which a guest agent serves its session, such as the VM's control console, as a byte stream. It opens the terminal, waiting while the kernel sets it up during boot, puts it in raw mode, so that it passes the session's bytes as they are, and drains it, so that it sends what the agent wrote before the agent ends the VM. NVX's managed agent and other guest agents serve their sessions on it | | `nvx::guest::spawn` | `Command`: starts a program in a new process for any guest init or agent, with its arguments, environment, root and working directories, standard streams, inherited descriptors, cgroup, process group or new session, a `Barrier` at which the program waits until the caller releases it, and an `entry::Prepared` execution to enter, without NVX's control protocol, managed agent, or workload identity. Its `LaunchReport` tells whether the program started, or which `LaunchStage` failed and why. NVX's managed agent is one caller | @@ -906,9 +906,11 @@ shares and mappings in it through `mappings`, and tears it down. `nvx-managed-agent` opens its control terminal, and launches, drives, collects, and settles its workloads, through them, has each sandbox workload enter its execution through `entry`, and applies its host mapping table through -`mappings`, beneath `/`, from its mount of the host's export, and any other -guest init or agent can use them too. Any guest init or agent can also run the -steps of `nvx-time` and `nvx-reseed` in its own process, through the +`mappings`, from its mount of the host's export, beneath `/` in direct mode and +beneath the container's assembled root in sandbox mode, where it unmounts the +table before it returns to the init agent, and any other guest init or agent +can use them too. Any guest init or agent can also run the steps of `nvx-time` +and `nvx-reseed` in its own process, through the `nvx::guest::time` and `nvx::guest::reseed` calls, on which both programs run. Nor is the `gpt` library a program: it reads the partition table of a GPT disk's block device. diff --git a/nvx-rs/src/guest/managed_agent/diagnostics.rs b/nvx-rs/src/guest/managed_agent/diagnostics.rs index d802aeb2d..c34bb2e79 100644 --- a/nvx-rs/src/guest/managed_agent/diagnostics.rs +++ b/nvx-rs/src/guest/managed_agent/diagnostics.rs @@ -15,6 +15,15 @@ pub(crate) fn mapping_error(system: &mut impl System, status: i32, entry: u32) { write_stderr(message.as_bytes()); } +/// Reports a host mapping that stays mounted after the table's teardown through both +/// diagnostic channels. +pub(crate) fn unmapping_error(system: &mut impl System, status: i32, entry: u32) { + error(system, "host-unmapping", status); + let message = + format!("NVX-MANAGED-ERROR: stage=host-unmapping status={status} entry={entry}\n"); + write_stderr(message.as_bytes()); +} + /// Writes a diagnostic to the process's standard error, ignoring write failures. pub(crate) fn write_stderr(message: &[u8]) { sys::write_standard_error(message); diff --git a/nvx-rs/src/guest/managed_agent/dispatch.rs b/nvx-rs/src/guest/managed_agent/dispatch.rs index fe989ee52..4f406d6e0 100644 --- a/nvx-rs/src/guest/managed_agent/dispatch.rs +++ b/nvx-rs/src/guest/managed_agent/dispatch.rs @@ -175,6 +175,7 @@ mod tests { use std::io::{Read, Write}; use std::os::unix::ffi::OsStrExt; use std::os::unix::net::UnixStream; + use std::path::Path; use std::thread; use crate::protocol::{ @@ -222,29 +223,29 @@ mod tests { harness } + /// Starts a sandbox agent whose assembled root is `rootfs`, with a table of + /// `expected_mappings` announced mappings, and resets its session. + fn in_sandbox(rootfs: &Path, system: TestSystem, expected_mappings: u32) -> Self { + let mut harness = Self::spawn_at(Some(rootfs), system, expected_mappings); + harness.reset(1, 7); + harness + } + /// Starts the agent, which attaches and waits for the broker's first RESET. - fn spawn(direct: bool, mut system: TestSystem, expected_mappings: u32) -> Self { + fn spawn(direct: bool, system: TestSystem, expected_mappings: u32) -> Self { + let rootfs = (!direct).then_some(Path::new("/rootfs")); + Self::spawn_at(rootfs, system, expected_mappings) + } + + /// Starts a direct agent, or a sandbox agent whose assembled root is `rootfs`, which + /// attaches and waits for the broker's first RESET. + fn spawn_at(rootfs: Option<&Path>, mut system: TestSystem, expected_mappings: u32) -> Self { let (host, guest) = UnixStream::pair().unwrap(); let descriptor = FileDescriptor::from_owned(guest.into()); + let config = AgentConfig::for_test(rootfs); let thread = thread::spawn(move || { - let config = AgentConfig { - rootfs: CString::new(if direct { "-" } else { "/rootfs" }).unwrap(), - hostname: c"test".to_owned(), - uid: c"1000".to_owned(), - gid: c"1000".to_owned(), - user: c"workload".to_owned(), - home: c"/home/workload".to_owned(), - direct, - // The test system prepares each sandbox execution itself. - entry: (!direct).then(|| { - crate::guest::entry::Entry::new( - "/rootfs", - crate::guest::entry::Identity::new(1000, 1000), - ) - }), - }; let mut session = Session::new(descriptor); - let mut mappings = HostMappings::announced(expected_mappings); + let mut mappings = HostMappings::announced_for(&config, expected_mappings); let outcome = run(&mut system, &mut session, &config, &mut mappings); (outcome, system) }); @@ -667,6 +668,146 @@ mod tests { assert_eq!(system.spawn_calls, 0); } + /// Returns a system with a host export, and the canonical path of a sandbox's assembled root + /// beside it, which is the root of a mount. + fn sandbox_root() -> (tempfile::TempDir, TestSystem, std::path::PathBuf) { + let (temporary, system) = TestSystem::with_host_export(); + let rootfs = temporary.path().canonicalize().unwrap().join("rootfs"); + std::fs::create_dir(&rootfs).unwrap(); + system.kernel.add_mount(&rootfs); + (temporary, system, rootfs) + } + + #[test] + fn sandbox_mappings_mount_in_order_beneath_its_root_and_unblock_workloads() { + let (_temporary, system, rootfs) = sandbox_root(); + let export = system.paths.hostfs_dir.join("root").canonicalize().unwrap(); + // The targets are the container's paths, below its assembled root, even below the + // runtime's exact paths, such as `/etc`. + let first = maps_payload( + 0, + &[ + (b"0/src", b"/workspace", protocol::MAP_READ_ONLY), + (b"0/notes.txt", b"/etc/app/notes.txt", 0), + ], + None, + ); + let second = maps_payload(2, &[(b"1", b"/out", 0)], None); + let mut harness = Harness::in_sandbox(&rootfs, system, 3); + let mut replies = Vec::new(); + replies.extend(harness.request_all(1, APP_EXEC, &[])); + replies.extend(harness.request_all(2, APP_MAPS, &first)); + replies.extend(harness.request_all(3, APP_EXEC, &[])); + replies.extend(harness.request_all(4, APP_MAPS, &second)); + replies.extend(harness.request_all(5, APP_EXEC, &[])); + assert_eq!( + replies, + vec![ + response(APP_ERROR, 1, Errno::EAGAIN as i32, b"mappings-incomplete"), + response(APP_READY, 2, 0, b""), + response(APP_ERROR, 3, Errno::EAGAIN as i32, b"mappings-incomplete"), + response(APP_READY, 4, 0, b""), + // With the table complete, the request reaches its decoder. + response(APP_ERROR, 5, Errno::EINVAL as i32, b"invalid-request"), + ] + ); + + let system = harness.stop(); + let [workspace, notes, out] = + ["workspace", "etc/app/notes.txt", "out"].map(|target| rootfs.join(target)); + let expected: Vec<_> = [ + (export.join("0/src"), &workspace, Access::ReadOnly), + (export.join("0/notes.txt"), ¬es, Access::ReadWrite), + (export.join("1"), &out, Access::ReadWrite), + ] + .into_iter() + .flat_map(|(from, to, access)| attach_calls(&from, to, access)) + .collect(); + assert_eq!(system.kernel.calls(), expected); + assert!(workspace.is_dir() && notes.is_file() && out.is_dir()); + assert_eq!(system.spawn_calls, 0); + } + + #[test] + fn sandbox_mappings_refuse_the_targets_of_the_container_runtime() { + // The runtime's trees, their ancestors, and its exact paths. + for target in [ + &b"/proc"[..], + b"/dev/shm", + b"/.nvx-agent", + b"/etc/machine-id", + b"/run/nvx/time/state", + b"/run/nvx", + b"/run", + b"/etc", + ] { + let (_temporary, system, rootfs) = sandbox_root(); + let mapping = maps_payload(0, &[(b"0/src", target, 0)], None); + let mut harness = Harness::in_sandbox(&rootfs, system, 1); + let mut replies = Vec::new(); + replies.extend(harness.request_all(1, APP_MAPS, &mapping)); + replies.extend(harness.request_all(2, APP_EXEC, &[])); + assert_eq!( + replies, + vec![ + response(APP_ERROR, 1, Errno::EPERM as i32, b"mapping-failed"), + response(APP_ERROR, 2, Errno::EAGAIN as i32, b"mappings-incomplete"), + ], + "{}", + String::from_utf8_lossy(target) + ); + let system = harness.stop(); + assert!(system.kernel.calls().is_empty()); + assert_eq!(std::fs::read_dir(&rootfs).unwrap().count(), 0); + } + } + + #[test] + fn a_failed_sandbox_mapping_keeps_refusing_workloads() { + let (_temporary, system, rootfs) = sandbox_root(); + let missing = maps_payload(0, &[(b"0/missing", b"/workspace", 0)], None); + let valid = maps_payload(0, &[(b"0/src", b"/workspace", 0)], None); + let mut harness = Harness::in_sandbox(&rootfs, system, 2); + let mut replies = Vec::new(); + replies.extend(harness.request_all(1, APP_MAPS, &missing)); + replies.extend(harness.request_all(2, APP_EXEC, &[])); + replies.extend(harness.request_all(3, APP_MAPS, &valid)); + replies.extend(harness.request_all(4, APP_EXEC, &[])); + assert_eq!( + replies, + vec![ + response(APP_ERROR, 1, Errno::ENOENT as i32, b"mapping-failed"), + response(APP_ERROR, 2, Errno::EAGAIN as i32, b"mappings-incomplete"), + response(APP_ERROR, 3, Errno::EINVAL as i32, b"invalid-request"), + response(APP_ERROR, 4, Errno::EAGAIN as i32, b"mappings-incomplete"), + ] + ); + let system = harness.stop(); + assert!(system.kernel.calls().is_empty()); + assert_eq!(system.spawn_calls, 0); + } + + #[test] + fn a_sandbox_without_mappings_maps_nothing_and_admits_workloads() { + let (_temporary, system, rootfs) = sandbox_root(); + let mapping = maps_payload(0, &[(b"0/src", b"/workspace", 0)], None); + let mut harness = Harness::in_sandbox(&rootfs, system, 0); + let mut replies = Vec::new(); + replies.extend(harness.request_all(1, APP_MAPS, &mapping)); + replies.extend(harness.request_all(2, APP_EXEC, &[])); + assert_eq!( + replies, + vec![ + response(APP_ERROR, 1, Errno::EINVAL as i32, b"invalid-request"), + // No table holds the request back, so it reaches its decoder. + response(APP_ERROR, 2, Errno::EINVAL as i32, b"invalid-request"), + ] + ); + let system = harness.stop(); + assert!(system.kernel.calls().is_empty()); + assert_eq!(std::fs::read_dir(&rootfs).unwrap().count(), 0); + } + #[test] fn sandbox_does_not_launch_when_an_environment_export_fails() { let mut system = TestSystem::new(Paths::default()); diff --git a/nvx-rs/src/guest/managed_agent/mappings.rs b/nvx-rs/src/guest/managed_agent/mappings.rs index c51c5a02f..50c15c15d 100644 --- a/nvx-rs/src/guest/managed_agent/mappings.rs +++ b/nvx-rs/src/guest/managed_agent/mappings.rs @@ -1,6 +1,6 @@ -use std::ffi::OsString; +use std::ffi::{OsStr, OsString}; use std::io::{self, Read}; -use std::os::unix::ffi::OsStringExt; +use std::os::unix::ffi::{OsStrExt, OsStringExt}; use std::os::unix::fs::MetadataExt; use std::path::{Path, PathBuf}; @@ -10,6 +10,8 @@ use crate::guest::mappings::{ use crate::guest::sys::{self, Errno, Mode}; use crate::protocol::{self, GuestHostMap}; +use super::AgentConfig; +use super::diagnostics; use super::seam::{System, path_c_string}; /// The direct root's own mounts besides `/`'s, on which the table's mapper may create what a @@ -27,11 +29,23 @@ pub(crate) struct HostMappings { pub(crate) applied: u32, /// Whether a prior mount failure permanently refused the remaining table. pub(crate) failed: bool, + /// The root beneath which the table maps. + root: TableRoot, /// The table's mapper and the export's root, once the first batch has opened them. table: Option, } -/// The mapper of the host mapping table beneath the agent's root, `/`, and the root of the host's +/// The root beneath which an agent maps its host mapping table. +#[derive(Debug, Default, PartialEq, Eq)] +enum TableRoot { + /// The direct agent's own root, `/`. + #[default] + Direct, + /// The sandbox agent's `ROOTFS`, the container's assembled root. + Sandbox(PathBuf), +} + +/// The mapper of the host mapping table beneath the table's root, and the root of the host's /// export, below which the table's sources are. struct Table { /// The mapper, which tracks and latches the table's mappings. @@ -40,15 +54,43 @@ struct Table { export: SourceRoot, } +impl HostMappings { + /// Returns the state of the table of the agent that `config` configures, before + /// [`prepare`] reads its announcement: the direct agent maps beneath `/`, and the sandbox + /// agent beneath `ROOTFS`. + pub(crate) fn new(config: &AgentConfig) -> Self { + let root = if config.direct { + TableRoot::Direct + } else { + let rootfs = OsStr::from_bytes(config.rootfs.as_bytes()); + TableRoot::Sandbox(PathBuf::from(rootfs)) + }; + Self { + root, + ..Self::default() + } + } +} + #[cfg(test)] impl HostMappings { - /// Returns the state of a table of `expected` announced mappings, none applied yet. + /// Returns the state of a direct agent's table of `expected` announced mappings, none + /// applied yet. pub(crate) fn announced(expected: u32) -> Self { Self { expected, ..Self::default() } } + + /// Returns the state of the table of `expected` announced mappings of the agent that + /// `config` configures, none applied yet. + pub(crate) fn announced_for(config: &AgentConfig, expected: u32) -> Self { + Self { + expected, + ..Self::new(config) + } + } } /// Failure returned while validating or applying one MAPS request. @@ -65,7 +107,7 @@ pub(crate) enum MappingError { }, } -/// Reads the announced mapping count and validates the host export mount. +/// Reads the announced mapping count and validates the host export mount, in either mode. pub(crate) fn prepare(system: &mut impl System, mappings: &mut HostMappings) -> Result<(), Errno> { let mut command_line = [0u8; 4096]; let count = std::fs::File::open(&system.paths().proc_cmdline) @@ -93,11 +135,14 @@ pub(crate) fn prepare(system: &mut impl System, mappings: &mut HostMappings) -> /// Validates and applies one ordered batch of host mappings. /// /// The agent keeps the table's bookkeeping: the count that the kernel command line announced, -/// and the order of the batches. A [`Mapper`] beneath the agent's root, `/`, applies each entry, -/// from the host export's mount, `hostfs_dir/root`, and latches the table at the first entry that -/// fails, as the [mappings](crate::guest::mappings) module describes: it creates what a target -/// lacks only on `/`'s mount and the tmpfs at `/tmp`, which a mapping may also cover, never inside -/// another mapping. The first batch opens them, so that a table of zero mappings does no work. +/// and the order of the batches. A [`Mapper`] beneath the table's root applies each entry, from +/// the host export's mount, `hostfs_dir/root`, and latches the table at the first entry that +/// fails, as the [mappings](crate::guest::mappings) module describes. The direct agent's table +/// root is its own, `/`, on whose mount and the tmpfs at `/tmp`, which a mapping may also cover, +/// the mapper creates what a target lacks. The sandbox agent's is `ROOTFS`, the container's +/// assembled root, on whose mount alone it creates what a target lacks, and whose runtime's +/// targets it refuses: [`Reserved::container_root`]. Either creates nothing inside another +/// mapping. The first batch opens them, so that a table of zero mappings does no work. pub(crate) fn apply_request( system: &mut impl System, mappings: &mut HostMappings, @@ -125,7 +170,7 @@ pub(crate) fn apply_request( .map_err(|_| MappingError::Invalid)?; let table = match mappings.table.take() { Some(table) => table, - None => match open_table(system) { + None => match open_table(system, &mappings.root) { Ok(table) => table, Err(error) => { mappings.failed = true; @@ -158,25 +203,56 @@ pub(crate) fn apply_request( } } -/// Opens the table's mapper beneath the agent's root, `/`, whose own mounts are `/`'s and those -/// of [`OWN_MOUNTS`] that exist, and the root of the host's export. -fn open_table(system: &mut impl System) -> Result { +/// Opens the table's mapper beneath `root`, as [`apply_request`] describes, and the root of the +/// host's export. +fn open_table(system: &mut impl System, root: &TableRoot) -> Result { let errno = |error: io::Error| sys::errno_of(&error); - let mut root = TargetRoot::open_with(system.kernel(), Path::new("/")).map_err(errno)?; - for own in OWN_MOUNTS { - match root.add_mount_with(system.kernel(), Path::new(own)) { - Ok(()) => {} - Err(error) if error.kind() == io::ErrorKind::NotFound => {} - Err(error) => return Err(errno(error)), + let (root, reserved) = match root { + TableRoot::Direct => { + let mut root = TargetRoot::open_with(system.kernel(), Path::new("/")).map_err(errno)?; + for own in OWN_MOUNTS { + match root.add_mount_with(system.kernel(), Path::new(own)) { + Ok(()) => {} + Err(error) if error.kind() == io::ErrorKind::NotFound => {} + Err(error) => return Err(errno(error)), + } + } + (root, Reserved::default()) } - } + TableRoot::Sandbox(rootfs) => ( + TargetRoot::open_with(system.kernel(), rootfs).map_err(errno)?, + Reserved::container_root(), + ), + }; let export = SourceRoot::open(&system.paths().hostfs_dir.join("root")).map_err(errno)?; Ok(Table { - mapper: Mapper::new(root, Reserved::default()), + mapper: Mapper::new(root, reserved), export, }) } +/// Unmounts the table's mappings in reverse order, as the sandbox agent does before it returns +/// to the init agent, which then unmounts the root that holds them. It attempts each, whatever +/// failed before, reports each failure with its zero-based entry, and returns the error of the +/// first failure, after which those mappings stay mounted. +pub(crate) fn teardown(system: &mut impl System, mappings: &mut HostMappings) -> Result<(), Errno> { + let Some(mut table) = mappings.table.take() else { + return Ok(()); + }; + let failures = table.mapper.unmount_with(system.kernel()); + let mut first = None; + for (entry, failure) in failures { + let status = failure.error().raw_os_error(); + // The table holds at most `MAX_HOST_MAPPINGS` entries, whose indices fit in a `u32`. + diagnostics::unmapping_error(system, status, entry as u32); + first.get_or_insert(status); + } + match first { + Some(status) => Err(Errno::from_raw(status)), + None => Ok(()), + } +} + /// Returns the library's mapping of one decoded entry, which the decoder's path rules let /// through unchanged. /// @@ -222,6 +298,90 @@ mod tests { .join(relative) } + /// Returns a system with a host export, the state of a sandbox agent's table of `expected` + /// mappings, and the canonical path of the agent's assembled root, which is the root of a + /// mount. + fn sandbox(expected: u32) -> (tempfile::TempDir, TestSystem, HostMappings, PathBuf) { + let (temporary, system) = TestSystem::with_host_export(); + let rootfs = temporary.path().canonicalize().unwrap().join("rootfs"); + fs::create_dir(&rootfs).unwrap(); + system.kernel.add_mount(&rootfs); + let config = AgentConfig::for_test(Some(&rootfs)); + let mappings = HostMappings::announced_for(&config, expected); + (temporary, system, mappings, rootfs) + } + + /// Applies three mappings of a sandbox's table: a read-only directory at `/workspace`, a file + /// at `/data/notes.txt`, and a directory at `/out`, whose paths below `rootfs` it returns. + fn map_three( + system: &mut TestSystem, + mappings: &mut HostMappings, + rootfs: &Path, + ) -> [PathBuf; 3] { + let request = payload( + 0, + &[ + (b"0/src", b"/workspace", protocol::MAP_READ_ONLY), + (b"0/notes.txt", b"/data/notes.txt", 0), + (b"1", b"/out", 0), + ], + None, + ); + apply_request(system, mappings, &request).unwrap(); + ["workspace", "data/notes.txt", "out"].map(|target| rootfs.join(target)) + } + + #[test] + fn a_sandbox_table_unmounts_in_reverse_order() { + let (_temporary, mut system, mut mappings, rootfs) = sandbox(3); + let [workspace, notes, out] = map_three(&mut system, &mut mappings, &rootfs); + assert_eq!(mappings.applied, 3); + teardown(&mut system, &mut mappings).unwrap(); + let shown = |path: &PathBuf| path.display().to_string(); + assert_eq!( + system.kernel.unmounts(), + [&out, ¬es, &workspace].map(shown) + ); + for target in [&workspace, ¬es, &out] { + assert_eq!(system.kernel.mount_at(target), None); + } + // The teardown forgot the table, so another has nothing to do. + teardown(&mut system, &mut mappings).unwrap(); + assert_eq!(system.kernel.unmounts().len(), 3); + assert!(system.diagnostics.is_empty()); + } + + #[test] + fn a_sandbox_table_reports_each_mapping_that_stays_mounted() { + let (_temporary, mut system, mut mappings, rootfs) = sandbox(3); + let [workspace, notes, out] = map_three(&mut system, &mut mappings, &rootfs); + system.kernel.fail(Operation::Unmount, ¬es, Errno::EBUSY); + assert_eq!(teardown(&mut system, &mut mappings), Err(Errno::EBUSY)); + // Every mapping is attempted, in reverse order, and only the busy one stays mounted. + let shown = |path: &PathBuf| path.display().to_string(); + assert_eq!( + system.kernel.unmounts(), + [&out, ¬es, &workspace].map(shown) + ); + assert!(system.kernel.mount_at(¬es).is_some()); + assert_eq!(system.kernel.mount_at(&workspace), None); + assert_eq!(system.kernel.mount_at(&out), None); + assert_eq!( + String::from_utf8_lossy(&system.diagnostics), + format!( + "NVX-MANAGED-ERROR: stage=host-unmapping status={}\n", + Errno::EBUSY as i32 + ) + ); + } + + #[test] + fn a_table_without_mappings_has_nothing_to_tear_down() { + let (_temporary, mut system, mut mappings, _rootfs) = sandbox(0); + teardown(&mut system, &mut mappings).unwrap(); + assert!(system.kernel.calls().is_empty()); + } + fn payload(first: u32, entries: &[(&[u8], &[u8], u16)], count: Option) -> Vec { let mut payload = Vec::new(); payload.extend_from_slice(&first.to_le_bytes()); diff --git a/nvx-rs/src/guest/managed_agent/mod.rs b/nvx-rs/src/guest/managed_agent/mod.rs index bbf0e48a1..e4b2ce26d 100644 --- a/nvx-rs/src/guest/managed_agent/mod.rs +++ b/nvx-rs/src/guest/managed_agent/mod.rs @@ -2,16 +2,18 @@ //! which serves NVX's authenticated control session on `CONTROL_TTY` and runs one workload at a //! time as `UID` and `GID`. //! -//! With `ROOTFS` `-`, the direct agent runs as PID 1: it applies the host mapping table, launches -//! each workload in its own cgroup and process group, reaps orphaned processes, and powers the VM -//! off after `STOP`. Otherwise the sandbox agent has each workload enter `ROOTFS` as an -//! [`entry`](crate::guest::entry) execution, as `UID` and `GID` with their existing account, with -//! `HOSTNAME`, held at a barrier until the agent has placed it in its cgroup, and returns to the -//! init agent after `STOP`. When it starts, it generates the workload's machine ID and binds it, -//! with the guest's time status, into `ROOTFS` in a mount namespace of its own, of which each -//! execution's starts as a copy, so that the binds end with the agent. Both keep the C agent's -//! command lines, wire behavior, status and error categories, 1 MiB output and receive windows, -//! and timeout and cancellation behavior. +//! With `ROOTFS` `-`, the direct agent runs as PID 1: it applies the host mapping table beneath +//! its own root, `/`, launches each workload in its own cgroup and process group, reaps orphaned +//! processes, and powers the VM off after `STOP`. Otherwise the sandbox agent applies the host +//! mapping table beneath `ROOTFS`, the container's assembled root, has each workload enter +//! `ROOTFS` as an [`entry`](crate::guest::entry) execution, as `UID` and `GID` with their existing +//! account, with `HOSTNAME`, held at a barrier until the agent has placed it in its cgroup, and +//! after `STOP` unmounts the table and returns to the init agent. When it starts, it generates the +//! workload's machine ID and binds it, with the guest's time status, into `ROOTFS` in a mount +//! namespace of its own, of which each execution's starts as a copy, so that the binds end with +//! the agent, and it maps the table in that namespace too. Both refuse workloads until the table +//! is complete, and both keep the C agent's command lines, wire behavior, status and error +//! categories, 1 MiB output and receive windows, and timeout and cancellation behavior. //! //! `nvx-managed-agent --exec-config-fd FD -- WORKLOAD...` is the direct agent's internal //! execution helper. The launch runs it once the workload's identity applies, and it applies the @@ -146,6 +148,34 @@ pub(crate) struct AgentConfig { entry: Option, } +#[cfg(test)] +impl AgentConfig { + /// Returns the configuration of a test agent of the workload `1000:1000`, named `workload` + /// and homed in `/home/workload`: a direct agent, or a sandbox agent whose assembled root is + /// `rootfs`. + pub(crate) fn for_test(rootfs: Option<&std::path::Path>) -> Self { + let rootfs = rootfs.map_or(c"-".to_owned(), |rootfs| { + CString::new(rootfs.as_os_str().as_bytes()).expect("a test path has no NUL") + }); + let direct = rootfs.as_bytes() == b"-"; + // The test system prepares each sandbox execution itself. + let entry = (!direct).then(|| { + let path = std::ffi::OsStr::from_bytes(rootfs.as_bytes()); + Entry::new(path, Identity::new(1000, 1000)) + }); + Self { + direct, + rootfs, + hostname: c"test".to_owned(), + uid: c"1000".to_owned(), + gid: c"1000".to_owned(), + user: c"workload".to_owned(), + home: c"/home/workload".to_owned(), + entry, + } + } +} + /// Runs `nvx-managed-agent` with the process's arguments. It exits with 0, or 125 when the agent /// or its execution helper fails. pub fn main() -> ExitCode { @@ -215,18 +245,25 @@ fn serve( Ok(fd) => fd, Err(error) => return Err(fatal(system, "control-open", error)), }; - let mut mappings = HostMappings::default(); - if config.direct - && let Err(error) = mappings::prepare(system, &mut mappings) - { + let mut mappings = HostMappings::new(config); + if let Err(error) = mappings::prepare(system, &mut mappings) { return Err(fatal(system, "host-mappings", error)); } if let Err(error) = tty::configure(system, &fd) { return Err(fatal(system, "control-tty", error)); } let mut session = Session::new(fd); - match dispatch::run(system, &mut session, config, &mut mappings) { - Ok(dispatch::Outcome::Stopped) => Ok(()), + let served = dispatch::run(system, &mut session, config, &mut mappings); + // The sandbox agent unmounts its mappings before it returns to the init agent, which then + // unmounts the root, and the direct agent powers the VM off with its mappings in place. + let unmapped = if config.direct { + Ok(()) + } else { + mappings::teardown(system, &mut mappings) + }; + match served { + // The teardown reported each mapping that stays mounted. + Ok(dispatch::Outcome::Stopped) => unmapped.map_err(|_| CommandError::Agent), Err(error) => Err(fatal(system, "control-session", error)), } } From a3edbd3b54638c589cc282b20d30e3dfa4ac7a4a Mon Sep 17 00:00:00 2001 From: Enrique Saurez Date: Thu, 22 Oct 2026 02:40:04 -0700 Subject: [PATCH 2/2] sandbox: deliver managed live shares as a host mapping table A managed layered sandbox now receives its live shares as the blockless root receives its host directories. OpenVMM exports every share as a child of one aggregate, which the init agent mounts at /run/nvx/hostfs/root, in a directory that only root can enter, and the kernel command line announces only the number of mappings. Once the guest agent answers, start sends the plan's ordered mapping table as MAPS requests before the launch commits. A mapping that the guest refuses fails the start, after the guest shuts down as a stop has it do, unmounting what it mapped, the export, the overlay, and the scratch disk, and OpenVMM is terminated only if the guest does not shut down. start requires the host mapping table, which the sandbox agent now advertises, and the kernel command line no longer bounds the number of a managed sandbox's shares. The one-shot lifecycle keeps its nvx_share= boot tokens, as do /init's plain path and the restore probe, and the init agent's managed branch refuses them. SandboxPlan and PreparedLaunch render the managed lifecycle, and their one-shot renderings, with which the CLI's run prepares its launch, become crate-private. With --mount-owner caller, the guest agent reaches the shares as guest root, which OpenVMM squashes to their owner, before any workload runs, so a managed sandbox whose OpenVMM cannot assume that identity no longer starts. The microVM workflow's caller-owned test, whose runner grants OpenVMM neither CAP_SETUID nor CAP_SETGID, checks that now. Part of #622 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: e4de0d1f-0989-4804-ab6b-3c2891554406 --- .github/workflows/run-nvx-microvm-tests.yml | 20 ++- .../4.1-guest-filesystem-and-image-model.md | 36 ++-- .../4.4-host-guest-control-interface.md | 7 +- .../5.2-readiness-and-runtime-control.md | 2 +- doc/run.md | 74 ++++++--- doc/usage.md | 2 +- guest/common/nvx-init-agent | 88 +++++++++- nvx-rs/README.md | 18 +- nvx-rs/src/guest/managed_agent/mappings.rs | 4 +- nvx-rs/src/host/cli/sandbox/lifecycle.rs | 42 ++++- nvx-rs/src/host/cli/sandbox/mod.rs | 16 +- nvx-rs/src/host/cli/session.rs | 45 ++++- nvx-rs/src/host/sandbox/golden.rs | 6 +- nvx-rs/src/host/sandbox/mount.rs | 56 +++++-- nvx-rs/src/host/sandbox/options/tests.rs | 5 +- nvx-rs/src/host/sandbox/plan.rs | 139 ++++++++++++---- nvx-rs/src/host/sandbox/plan/tests.rs | 155 +++++++++++++++--- nvx-rs/src/host/sandbox/prepared.rs | 66 ++++++-- nvx-rs/src/host/sandbox/tests.rs | 115 ++++++++----- nvx-rs/src/protocol/features.rs | 11 +- nvx-rs/src/protocol/tests.rs | 18 +- nvx-rs/src/testing/fake_openvmm.rs | 100 +++++++---- nvx-rs/tests/cli.rs | 102 ++++++++++-- nvx-rs/tests/fixtures/cli.json | 22 +-- scripts/test_nvx_tools.py | 113 ++++++++++++- 25 files changed, 990 insertions(+), 272 deletions(-) diff --git a/.github/workflows/run-nvx-microvm-tests.yml b/.github/workflows/run-nvx-microvm-tests.yml index 330c69c3c..d3cdd7e3c 100644 --- a/.github/workflows/run-nvx-microvm-tests.yml +++ b/.github/workflows/run-nvx-microvm-tests.yml @@ -500,7 +500,10 @@ jobs: --workload-user 65534:65534 \ --memory-mib 256 test "$(ls -A "${share}")" = nvx-host-marker - # A managed sandbox persists the ownership mode and applies it on start. + # A managed sandbox persists the ownership mode and applies it on + # start. Its guest agent reaches the share as guest root, which the + # mode squashes to the share's owner, before any workload runs, so + # that request fails with EPERM too, and the sandbox never starts. cp --reflink=auto build/ubuntu-smoke-scratch.ext4 "${scratch}" python3 scripts/nvx.py sandbox provision \ --state-dir "${state}" \ @@ -519,13 +522,14 @@ jobs: if config["format"] != 7 or config["export"]["owner"] != "caller": sys.exit(f"managed sandbox did not persist caller ownership: {config}") EOF - python3 scripts/nvx.py sandbox start --state-dir "${state}" - python3 scripts/nvx.py sandbox exec \ - --state-dir "${state}" \ - --entrypoint /sbin/nvx-sandbox-smoke \ - --arg /workspace \ - --arg eperm - python3 scripts/nvx.py sandbox stop --state-dir "${state}" + if python3 scripts/nvx.py sandbox start --state-dir "${state}"; then + echo "the caller-owned managed sandbox reached its share as the runner" >&2 + exit 1 + fi + grep -q 'virtio-fs request cannot run as its caller; failing it with EPERM' \ + "${state}/openvmm.log" + grep -q 'NVX-MANAGED-ERROR: stage=host-mappings' "${state}/openvmm.log" + test ! -e "${state}/runtime.json" test "$(ls -A "${share}")" = nvx-host-marker python3 scripts/nvx.py sandbox deprovision --state-dir "${state}" rm -rf "${share}" "${scratch}" diff --git a/doc/design/4.1-guest-filesystem-and-image-model.md b/doc/design/4.1-guest-filesystem-and-image-model.md index 0a4257819..56578c9de 100644 --- a/doc/design/4.1-guest-filesystem-and-image-model.md +++ b/doc/design/4.1-guest-filesystem-and-image-model.md @@ -27,9 +27,11 @@ layer with one private ext4 scratch device. /run/nvx/scratch/upper (ext4) -----------> upper directory /run/nvx/scratch/work (same ext4) ------> work directory overlay --> /run/nvx/rootfs -virtio-fs tag microvm (optional share) ---> /run/nvx/rootfs/TARGET +one-shot: virtio-fs tag microvm (optional share) ---> /run/nvx/rootfs/TARGET or an aggregate ---> /run/nvx/shares, each child bound at /run/nvx/rootfs/TARGET +managed: the aggregate export ---> /run/nvx/hostfs/root, each mapping of the + table mounted at /run/nvx/rootfs/TARGET ``` **Figure 4.1.** Layered sandbox root assembly. @@ -74,10 +76,12 @@ The guest agents assemble the root in this order: 5. Mount the overlay with the `distro` layer as its lower directory, metadata-only copy-up, and extended inode numbers. 6. Verify the workload identity in the assembled root, mount each live share - at its target inside that root, and write the workload's machine ID to a - runtime file. + of a one-shot sandbox at its target inside that root, or the host's export + of a managed sandbox, and write the workload's machine ID to a runtime + file. 7. Start the workload behind a barrier and place it in the workload cgroup - before releasing it. + before releasing it; a managed sandbox's agent first maps the shares from + the export, as their mapping table orders. 8. Wait for the workload, unmount the shares in reverse order and then the overlay, the `distro` layer, and scratch, and report the workload's status. @@ -110,11 +114,12 @@ after its index and a digest of its guest target, so a snapshot pins every target, and a restore that requests another target fails before the guest runs. Before launch, the launcher rejects policy paths outside their share or on a shared file, guest targets or host paths that equal or contain one -another, and shares whose boot tokens exceed the command-line budget. +another, and one-shot shares whose boot tokens exceed the command-line budget. -The machine profile announces the export through its host filesystem tokens, -and the launcher adds one share token per child that names the child, its -guest target, its mode, and whether it is a file. The guest agents then: +A one-shot sandbox receives its shares at boot. The machine profile announces +the export through its host filesystem tokens, and the launcher adds one share +token per child that names the child, its guest target, its mode, and whether +it is a file. The guest agents then: - Parse every share token and create every target before mounting anything, so a malformed bootstrap mounts nothing. @@ -131,9 +136,18 @@ guest target, its mode, and whether it is a file. The guest agents then: The workload's mount namespace inherits these mounts, and teardown unmounts the binds in reverse order before the aggregate. Any refusal or mount failure -aborts the sandbox instead of starting the workload without its shares. A -managed sandbox records its shares when it is provisioned and reattaches them -on every start. +aborts the sandbox instead of starting the workload without its shares. + +A managed sandbox records its shares when it is provisioned, and on every +start receives them as the blockless root receives its host directories (see +4.1.3): the host exports every share as a numbered child of one aggregate, +which the guest agents mount at the same root-only location, and delivers the +mapping table once the managed agent is ready. The agent maps each entry +beneath the assembled root, whose own mount is the overlay, and refuses the +targets that the container runtime keeps, as the boot tokens' targets are +refused. A mapping that fails ends the start, after the guest shuts down as +stop has it do: it unmounts the mappings in reverse order before the export +and the overlay. ## 4.1.3 Blockless Managed Root diff --git a/doc/design/4.4-host-guest-control-interface.md b/doc/design/4.4-host-guest-control-interface.md index 592735f72..6cc854e2e 100644 --- a/doc/design/4.4-host-guest-control-interface.md +++ b/doc/design/4.4-host-guest-control-interface.md @@ -86,9 +86,10 @@ therefore returns a four-byte little-endian bit mask of control features. | 6 | Host mapping table | The blockless managed root provides all six features; the layered sandbox -root provides cancellation and per-execution environments. Its workloads run -as an account that the image already has, so it does not create accounts. A -feature bit is added together with the behavior it names. +root provides cancellation, per-execution environments, and the host mapping +table. Its workloads run as an account that the image already has, so it does +not create accounts. A feature bit is added together with the behavior it +names. Hosts ignore unknown bits and trailing bytes, read an `unsupported-operation` refusal as no features, and terminate a guest that lacks a feature they need instead of running workloads without the policy they requested. diff --git a/doc/design/5.2-readiness-and-runtime-control.md b/doc/design/5.2-readiness-and-runtime-control.md index a8f067b25..9bb4ac654 100644 --- a/doc/design/5.2-readiness-and-runtime-control.md +++ b/doc/design/5.2-readiness-and-runtime-control.md @@ -48,7 +48,7 @@ operations. | Operation | Effect | | --- | --- | | Provision | Records the sandbox's configuration, including its host shares | -| Start | Launches the VMM with a freshly generated control capability, reattaches the recorded shares, and waits for guest readiness | +| Start | Launches the VMM with a freshly generated control capability and the recorded shares' export, waits for guest readiness, and delivers the shares' mapping table | | Exec | Runs one workload over the control channel | | Stop | Shuts down the VM and releases its runtime resources | | Deprovision | Removes the sandbox's state | diff --git a/doc/run.md b/doc/run.md index 38a88b231..4468bb17b 100644 --- a/doc/run.md +++ b/doc/run.md @@ -837,28 +837,49 @@ Guest mount flags are not a security boundary: OpenVMM rejects every write to an `ro` share with `EROFS`, whichever mount or link inside the guest reaches it. After it assembles the container overlay and verifies the workload identity, -the guest agent creates each target inside the container root and mounts the -share there with `nosuid,nodev` before the workload enters its private mount -namespace. With several shares, or a shared file, it mounts the aggregate at -`/run/nvx/shares`, outside the container root, and binds each child at its -target with its mode and `nosuid,nodev`, in order, as the -`nvx_share=NAME,TARGET,MODE[,file]` tokens that NVX adds to the kernel command -line describe. It binds a shared file at a regular file, which it creates when -the container root has nothing at the target. The number of shares is bounded -only by the sandbox's 1024-byte kernel command-line budget. A one-shot -workload exit, a managed `stop`, and any failure after a share is mounted -unmount the binds in reverse order, then the aggregate, before the overlay is -unmounted or the VM powers off. Each target must be an absolute, canonical -path; `/`, `/etc`, `/run`, and `/run/nvx`, and the `/etc/machine-id`, -`/proc`, `/sys`, `/dev`, `/.nvx-agent`, and `/run/nvx/time` trees, are -reserved for the container runtime, which replaces `/etc/machine-id` with the -workload's machine ID, creates `/run` and `/run/nvx`, and binds its time state -over `/run/nvx/time`. +the guest mounts the shares inside the container root with `nosuid,nodev`, +before any workload enters its private mount namespace. How it learns of them +depends on the lifecycle. + +A one-shot `sandbox run` delivers them at boot. The guest agent creates each +target inside the container root and mounts the share there. With several +shares, or a shared file, it mounts the aggregate at `/run/nvx/shares`, outside +the container root, and binds each child at its target with its mode, in +order, as the `nvx_share=NAME,TARGET,MODE[,file]` tokens that NVX adds to the +kernel command line describe. It binds a shared file at a regular file, which +it creates when the container root has nothing at the target. The number of +shares is bounded only by the sandbox's 1024-byte kernel command-line budget. + +A managed sandbox delivers them once its guest agent is ready. OpenVMM exports +every share as a child of one aggregate, which the guest mounts at +`/run/nvx/hostfs/root`, where only root can enter, and the kernel command line +announces only the number of mappings, as `nvx_maps=COUNT`. Once the guest +agent answers, `start` sends it the mapping table, in order, in as many +requests as it takes. The agent mounts each entry at its target with its mode, +and creates a missing target only on the container overlay, never inside +another mapping, as a directory or, for a shared file, a regular file. It +refuses every workload until it has mounted the whole table. A mapping that +the guest refuses or cannot mount fails `start`, after the guest shuts down as +`stop` has it do, so the sandbox never runs with part of its shares; `start` +terminates OpenVMM only if the guest does not shut down within `--timeout`. +The kernel command line does not bound the number of a managed sandbox's +shares; the 256 children of one aggregate do. + +A one-shot workload exit, a managed `stop`, and any failure after a share is +mounted unmount the binds or mappings in reverse order, then the aggregate or +the export, before the overlay is unmounted or the VM powers off, unless the +guest stops answering, or `start` is interrupted, and OpenVMM is terminated +first. Each target +must be an absolute, canonical path; `/`, `/etc`, `/run`, and `/run/nvx`, and +the `/etc/machine-id`, `/proc`, `/sys`, `/dev`, `/.nvx-agent`, and +`/run/nvx/time` trees, are reserved for the container runtime, which replaces +`/etc/machine-id` with the workload's machine ID, creates `/run` and +`/run/nvx`, and binds its time state over `/run/nvx/time`. The guest refuses a target whose path crosses a symbolic link in a container layer, a target that a container layer holds as another kind of file than the -share's, a repeated child, and overlapping targets, and any validation or mount -failure aborts the sandbox with status 125 instead of starting the workload -without its shares. +share's, and overlapping targets, and a one-shot guest a repeated child. Any +validation or mount failure aborts a one-shot sandbox with status 125, and +fails a managed `start`, instead of starting the workload without its shares. An `rw` share supports the symbolic links that package managers and language toolchains create; see @@ -991,7 +1012,10 @@ A service manager can grant the same set, such as systemd's operation succeeds only if its caller has OpenVMM's user and primary group and OpenVMM's user belongs to no other group; every other operation fails with `EPERM`. Hosts commonly grant access to `/dev/kvm` or `/dev/mshv` through such -a group, so `caller` usually needs both capabilities. Grant OpenVMM no other +a group, so `caller` usually needs both capabilities. A managed sandbox's guest +agent maps the shares before any workload runs, as guest root, which `caller` +squashes to the owner of the host directory, so a managed sandbox whose +OpenVMM cannot assume that identity fails to start. Grant OpenVMM no other capabilities: `CAP_SETUID` lets it assume any host identity, which `caller` mode confines to its export. @@ -1246,9 +1270,11 @@ and should not be used for secrets. These options apply only to managed private mount, PID, and UTS namespaces of its own, as the first process of its PID namespace, through the guest agent's execution entry, which also makes every mount but `/dev` and its devpts instance `nodev`. The workload sees one -machine ID for the life of the VM. On `stop`, the guest agent unmounts the live share, -overlay, layers, and scratch in dependency order before the VM powers off, as it -does when a one-shot workload exits. The legacy operation-less `sandbox` +machine ID for the life of the VM. On `stop`, the guest agent unmounts the +mappings of the live shares, and the guest then unmounts the host export, +overlay, layers, and scratch in dependency order before the VM powers off, as +it unmounts the shares when a one-shot workload exits. The legacy +operation-less `sandbox` form is `sandbox run`; it remains one-shot and rejects `--state-dir` or any request to retain VM state. diff --git a/doc/usage.md b/doc/usage.md index 8c6e377cc..847b07857 100644 --- a/doc/usage.md +++ b/doc/usage.md @@ -1198,7 +1198,7 @@ wins over a value that `nvx-rs` would refuse, even when that value comes first. | `--environment-file PATH` | omitted | Read the exact managed `exec` environment from a UTF-8 JSON array of `KEY=VALUE` strings, limited to 1 MiB of input. An empty array requests an empty environment. This option is mutually exclusive with `--environment`; omitting both preserves guest defaults. | | `--inherit-default-environment` | off | Layer the managed `exec` environment from `--environment` or `--environment-file` over the guest default environment instead of replacing it; an entry replaces the default variable of the same name. Without either option the workload already receives the defaults, so the flag has no effect. | | `--hypervisor {auto,whp,kvm,mshv}` | `auto` | Select the host hypervisor. | -| `--mount GUEST_TARGET,HOST_PATH[,ro\|rw]` | none | Live-share a host directory, or a single regular host file without its directory, at the absolute target inside the container rootfs for `run` or `provision`; defaults to `ro`. The mode follows the last comma, so `HOST_PATH` may contain commas when the mode is given. Repeat to attach more shares, each with its own target and mode, for example a read-write workspace and a read-only tool cache, as the children of an aggregate that the guest binds at their targets; a shared file always uses the aggregate. Targets and host paths must not overlap, and the shares' kernel command-line tokens count toward the sandbox's 1024-byte budget. An `rw` share accepts guest-created symbolic links, which the host never follows. `/`, `/etc`, `/run`, and `/run/nvx`, and the `/etc/machine-id`, `/proc`, `/sys`, `/dev`, `/.nvx-agent`, and `/run/nvx/time` trees, are reserved. | +| `--mount GUEST_TARGET,HOST_PATH[,ro\|rw]` | none | Live-share a host directory, or a single regular host file without its directory, at the absolute target inside the container rootfs for `run` or `provision`; defaults to `ro`. The mode follows the last comma, so `HOST_PATH` may contain commas when the mode is given. Repeat to attach more shares, each with its own target and mode, for example a read-write workspace and a read-only tool cache, as the children of an aggregate that the guest binds at their targets; a shared file always uses the aggregate, and so does every share of a managed sandbox. Targets and host paths must not overlap. A one-shot `run` describes its shares in kernel command-line tokens that count toward the sandbox's 1024-byte budget; a managed sandbox announces only their number and sends their mapping table once its guest agent is ready, for at most 256 shares. An `rw` share accepts guest-created symbolic links, which the host never follows. `/`, `/etc`, `/run`, and `/run/nvx`, and the `/etc/machine-id`, `/proc`, `/sys`, `/dev`, `/.nvx-agent`, and `/run/nvx/time` trees, are reserved. | | `--mount-deny HOST_PATH` | none | Hide one existing file or directory inside a `--mount` host directory; relative paths are resolved inside it. It may name the directory itself when `--mount-allow` paths inside it remain. With several shares, it applies to the `--mount` before it, which must share a directory. Repeat to deny multiple paths. | | `--mount-allow HOST_PATH` | none | Expose one existing file or directory inside a `--mount-deny` path of the same share again, for example a readable `mcp-payloads` directory inside hidden logs. The hidden directories on the way list only the entries that lead to it, and the workload cannot modify them. Relative paths are resolved inside the share; with several shares, it applies to the `--mount` before it. Repeat to allow multiple paths. See [Access policy](run.md#access-policy). | | `--mount-write HOST_PATH` | none | Make one existing file or directory one of the only writable parts of an `rw` share; the workload's writes anywhere else in the share fail with `EROFS`. Relative paths are resolved inside the share; with several shares, it applies to the `--mount` before it, which must be `rw`. Repeat to declare multiple writable paths. `provision` persists the denied, allowed, and writable paths. | diff --git a/guest/common/nvx-init-agent b/guest/common/nvx-init-agent index 4241868e2..42a0ae295 100644 --- a/guest/common/nvx-init-agent +++ b/guest/common/nvx-init-agent @@ -7,8 +7,11 @@ runtime=/run/nvx layers=$runtime/layers scratch=$runtime/scratch rootfs=$runtime/rootfs -# Mounted live shares, one per line and most recent first, so that teardown -# unmounts them in reverse mount order. +# The host export of a managed sandbox goes at $hostfs/root, where only root +# can enter, as in the guest's plain path. +hostfs=$runtime/hostfs +# Mounted live shares, or the host export of a managed sandbox, one per line +# and most recent first, so that teardown unmounts them in reverse mount order. share_mountpoints= unmount_live_shares() { @@ -488,8 +491,77 @@ mount_live_shares() { set +f } -# Unmount in dependency order: the live shares are children of the overlay, -# and the overlay uses the layers and scratch. +# Mounts the host's virtio-fs export of a managed sandbox, from which its +# guest agent maps host paths into the container rootfs as the mapping table +# that the host sends once the control session is ready orders them. OpenVMM +# appends one virtfs_dir=, virtfs_tag=, virtfs_mode= triplet and +# virtfs_aggregate=1 for the export, whose root lists one child per host +# directory or file. It goes at $hostfs/root, where only root can enter, so +# that a workload reaches host paths only through their mappings. The agent +# reads the nvx_maps= count itself, and nvx_share= tokens, which place the +# children of a one-shot sandbox, are refused. Every token is checked before +# anything is mounted. +mount_host_export() { + export_dir= + export_tag= + export_mode= + export_fields=0 + export_aggregate=false + # Kernel command-line tokens are deliberately split on spaces. + # shellcheck disable=SC2086 + set -f + for token in $cmdline; do + case "$token" in + virtfs_dir=?*) + export_dir=${token#*=} + export_fields=$((export_fields + 1)) + ;; + virtfs_tag=?*) + export_tag=${token#*=} + export_fields=$((export_fields + 1)) + ;; + virtfs_mode=?*) + export_mode=${token#*=} + export_fields=$((export_fields + 1)) + ;; + virtfs_dir=* | virtfs_tag=* | virtfs_mode=*) + set +f + fatal "host export bootstrap is incomplete" + ;; + virtfs_aggregate=1) export_aggregate=true ;; + nvx_share=*) + set +f + fatal "a managed sandbox maps its live shares from the host's mapping table, not from nvx_share= tokens" + ;; + esac + done + set +f + if [ "$export_fields" -eq 0 ] && [ "$export_aggregate" = false ]; then + return 0 + fi + [ "$export_fields" -eq 3 ] && [ "$export_aggregate" = true ] || + fatal "host export bootstrap is incomplete" + [ "$export_dir" = "$hostfs/root" ] || + fatal "the host export must be mounted at $hostfs/root" + case "$export_tag" in + '' | *[!A-Za-z0-9_-]*) fatal "host export tag is invalid" ;; + esac + case "$export_mode" in + ro | rw) ;; + *) fatal "host export mode is unsupported: $export_mode" ;; + esac + if ! (umask 077 && mkdir "$hostfs") || ! mkdir "$export_dir"; then + fatal "failed to create the host export directory" + fi + mount -t virtiofs -o "$export_mode,nosuid,nodev" "$export_tag" "$export_dir" || + fatal "failed to mount the host export $export_tag" + record_live_share "$export_dir" + echo "NVX-SANDBOX-EXPORT: mode=$export_mode tag=$export_tag" +} + +# Unmount in dependency order: the live shares are children of the overlay, as +# are the mappings that a managed sandbox's agent unmounts in its own mount +# namespace before it returns, and the overlay uses the layers and scratch. teardown() { status=$1 rm -f "$runtime/container.pid" "$runtime/workload-machine-id" @@ -587,7 +659,13 @@ case "$workload_lifecycle" in *) fatal "unsupported workload lifecycle: $workload_lifecycle" ;; esac -mount_live_shares +# A one-shot sandbox binds its live shares now, as their boot tokens place +# them, and a managed sandbox's agent maps them from the host export once the +# host sends their mapping table. +case "$workload_lifecycle" in + managed) mount_host_export ;; + *) mount_live_shares ;; +esac if [ "$workload_lifecycle" = managed ]; then # The managed agent enters each execution itself, as the first process of diff --git a/nvx-rs/README.md b/nvx-rs/README.md index dcf51c843..2b0bf0b34 100644 --- a/nvx-rs/README.md +++ b/nvx-rs/README.md @@ -85,7 +85,7 @@ nvx-rs/ | `nvx::host::supervisor` | The supervisor of a sandbox's VMM, beneath the CLI, `Instance`, and external orchestrators, which keep the configuration, the authorization, and the application protocol. `launch` runs the store's launch steps under the sandbox's lock: it writes the journal's marker, spawns OpenVMM with the claimed log, records its `ProcessRef` right after, and returns a `Starting` launch that the caller commits once the VMM serves its control endpoint, or abandons. A launch that fails never leaves an unrecorded VMM running. `VmmCommand::inherit` lists the descriptors (Linux) or handles (Windows) that the VMM inherits under their numbers, besides its standard streams, and it inherits nothing else of the caller's: on Linux, they must be close-on-exec, a flag that only the VMM's own process clears; on Windows, they join the VMM's explicit handle list. `Vmm::stop` runs one graceful step of the caller's and waits for the VMM's exit event until a deadline, and takes a bounded forced step through the VMM's verified identity only on request. `Vmm::terminate` takes that forced step alone, within the caller's bound, for a VM whose guest the caller must not ask anything, such as one of another runtime identity. `reattach` recovers an interrupted launch, and holds the recorded VMM again after the orchestrator restarts within the same host boot: `Live`, `Mismatched` with another runtime identity, `Exited`, or `Indeterminate` | | `nvx::host::seal` | `FileSeal`: what the host reports about an open file from its metadata alone, without reading it: the platform scheme, the device or volume serial number, the file ID, the kind, the length, the modification time, and on Linux the change time, with a versioned serde form. A seal detects accidental change, not tampering; see [Distro bindings](#distro-bindings) | | `nvx::host::session`, `platform`, `report` | The authenticated control session, which carries NVX's control protocol, `NVXC`, one frame per DATA record of a `HostConnection`; Linux and Windows primitives; and OpenVMM's outcome report | -| `nvx::host::sandbox` | The launch profile of `nvx.py sandbox`, ported from the one that `scripts/nvx_tools/sandbox.py` held: `SandboxLaunch`, with the EROFS distro `SandboxLayer`, the one layer that a sandbox takes, the ext4 scratch disk, the entrypoint, arguments, hostname, workload identity, and resource limits, and the `SandboxPlan` that it makes of them. `plan`: `SandboxPlan`, the typed plan of a cold layered launch, which is persistable in a versioned serde form: one read-only `distro` block device, an EROFS filesystem or a GPT disk with the identity that the guest expects of it, if any, an upper, the ext4 scratch disk or RAM, the launch settings, the `ExportPlan` of its live shares, and optionally a `SandboxNetwork`, the guest network and its typed `NetworkPolicy`, whose proxy's URL as the guest sees it the plan reports. A plan knows only the `distro` and `scratch` `BlockRole`s, and gives, for every combination, its `--microvm-sandbox-block` and `--microvm-workload-identity` arguments, with no scratch block device for a RAM upper, and those of its network, which `nvx::host::network` lowers, and its kernel command line, with the boot tokens of `nvx::protocol::root`, within the 1024-byte budget that OpenVMM leaves it, refusing one whose root tokens the guest's parser refuses. `mount`: `SandboxMount` requests of live shares of host directories and files, their guest targets and the reserved ones, their access policies and owner, and the checks of their host paths; `plan_mounts`, which plans them through `nvx::host::filesystem` for the container root, and `boot_shares`, which renders a plan as the OpenVMM arguments and boot tokens of one share or of the aggregate of several. `options`: the checks that `nvx.py sandbox` and `nvx.py run` apply to their options: the attribution of `--mount-deny`, `--mount-allow`, and `--mount-write` to shares, the systemd entrypoint check and the explicit verification of the distro layer, the targets of `nvx.py run` shares, and the managed exec environment; see [Python parity](#python-parity). `distro`: the `DistroBinding` of a distro layer, which explicit verification makes or a staging caller imports, and its check from metadata alone, which returns the layer open; see [Distro bindings](#distro-bindings). `scratch`: the `ScratchBinding` of a scratch image, its identity, kind, and length, and its check from metadata alone, which claims the image for one sandbox at a time and returns it open. `prepared`: `PreparedLaunch`, the launch of a plan with the checked files of its block devices, which renders the plan's OpenVMM arguments and kernel command line, naming the checked files as `/proc/self/fd/N` on Linux and by their final paths on Windows, and lists the descriptors that the VMM inherits through `VmmCommand::inherit`; see [Checked handoff](#checked-handoff) | +| `nvx::host::sandbox` | The launch profile of `nvx.py sandbox`, ported from the one that `scripts/nvx_tools/sandbox.py` held: `SandboxLaunch`, with the EROFS distro `SandboxLayer`, the one layer that a sandbox takes, the ext4 scratch disk, the entrypoint, arguments, hostname, workload identity, and resource limits, and the `SandboxPlan` that it makes of them. `plan`: `SandboxPlan`, the typed plan of a cold layered launch, which is persistable in a versioned serde form: one read-only `distro` block device, an EROFS filesystem or a GPT disk with the identity that the guest expects of it, if any, an upper, the ext4 scratch disk or RAM, the launch settings, the `ExportPlan` of its live shares, and optionally a `SandboxNetwork`, the guest network and its typed `NetworkPolicy`, whose proxy's URL as the guest sees it the plan reports. A plan knows only the `distro` and `scratch` `BlockRole`s, and gives, for every combination, its `--microvm-sandbox-block` and `--microvm-workload-identity` arguments, with no scratch block device for a RAM upper, and those of its network, which `nvx::host::network` lowers, and its kernel command line, with the boot tokens of `nvx::protocol::root`, within the 1024-byte budget that OpenVMM leaves it, refusing one whose root tokens the guest's parser refuses. Both deliver the live shares as the managed lifecycle does: the arguments export them at `nvx::host::filesystem::GUEST_EXPORT`, the command line announces the number of their mappings with `nvx_maps=`, and `mapping_table` gives the ordered table that `start` sends once the guest agent is ready; the CLI's one-shot `run` still renders them as boot tokens. `mount`: `SandboxMount` requests of live shares of host directories and files, their guest targets and the reserved ones, their access policies and owner, and the checks of their host paths; `plan_mounts`, which plans them through `nvx::host::filesystem` for the container root, and `boot_shares`, which renders a plan as the OpenVMM arguments and boot tokens of one share or of the aggregate of several, as the one-shot lifecycle delivers them. `options`: the checks that `nvx.py sandbox` and `nvx.py run` apply to their options: the attribution of `--mount-deny`, `--mount-allow`, and `--mount-write` to shares, the systemd entrypoint check and the explicit verification of the distro layer, the targets of `nvx.py run` shares, and the managed exec environment; see [Python parity](#python-parity). `distro`: the `DistroBinding` of a distro layer, which explicit verification makes or a staging caller imports, and its check from metadata alone, which returns the layer open; see [Distro bindings](#distro-bindings). `scratch`: the `ScratchBinding` of a scratch image, its identity, kind, and length, and its check from metadata alone, which claims the image for one sandbox at a time and returns it open. `prepared`: `PreparedLaunch`, the launch of a plan with the checked files of its block devices, which renders the plan's OpenVMM arguments and kernel command line, naming the checked files as `/proc/self/fd/N` on Linux and by their final paths on Windows, and lists the descriptors that the VMM inherits through `VmmCommand::inherit`; see [Checked handoff](#checked-handoff) | | `nvx::testing::fake_openvmm` | A fake OpenVMM that serves the control console and runs scripted workloads without a VM, for direct launches and for the managed and one-shot sandboxes of `nvx-rs sandbox` and `nvx.py sandbox` | | `nvx::host::cli` | Feature `cli`: the `nvx-rs` executable; see [The nvx-rs CLI](#the-nvx-rs-cli) | | `nvx::guest` | The programs that run in Linux guests; see [Guest binaries](#guest-binaries) | @@ -634,17 +634,21 @@ switch too, since this build finds no VM in that sandbox. After the guest answers, `start` asks it for its control features and requires `GuestFeatures::LAYERED_SANDBOX`, the features that its launches use: per-execution environments (bit 4), since `exec` sends a working directory and -an environment. It needs neither cancellation (bit 0), since the CLI never -cancels a workload, and Ctrl-C ends the session, nor workload account creation -(bit 2), since a layered sandbox runs its workloads as an account of the image. -A guest image that lacks a required feature, or that predates the request, is -stopped as a failed start is, and the start fails with +an environment, and host path mapping tables (bit 6), since `start` then sends +the mapping table of the sandbox's shares, which the guest agent mounts before +it runs any workload; a mapping that it refuses fails the start, after the +guest shuts down as `stop` has it do. It needs neither cancellation (bit 0), +since the CLI never cancels a workload, and Ctrl-C ends the session, nor +workload account creation (bit 2), since a layered sandbox runs its workloads +as an account of the image. A guest image that lacks a required feature, or +that predates the request, is stopped as a failed start is, and the start +fails with `the guest image lacks control features that layered sandboxes need (...)`, which names the missing features. `nvx.py` does not ask; this, the checks of the [distro binding](#distro-bindings) and of the [scratch binding](#checked-handoff), and the claim of the scratch image are the intended changes of behavior. The -guest agents of NVX advertise bits 0 and 4 in sandbox mode. +guest agents of NVX advertise bits 0, 4, and 6 in sandbox mode. #### Other differences from nvx.py diff --git a/nvx-rs/src/guest/managed_agent/mappings.rs b/nvx-rs/src/guest/managed_agent/mappings.rs index 50c15c15d..ec588e164 100644 --- a/nvx-rs/src/guest/managed_agent/mappings.rs +++ b/nvx-rs/src/guest/managed_agent/mappings.rs @@ -107,7 +107,9 @@ pub(crate) enum MappingError { }, } -/// Reads the announced mapping count and validates the host export mount, in either mode. +/// Reads the announced mapping count and validates the host export mount, in either mode: the +/// guest's init mounts the export for the direct agent, and the init agent for the sandbox +/// agent, at the same place. pub(crate) fn prepare(system: &mut impl System, mappings: &mut HostMappings) -> Result<(), Errno> { let mut command_line = [0u8; 4096]; let count = std::fs::File::open(&system.paths().proc_cmdline) diff --git a/nvx-rs/src/host/cli/sandbox/lifecycle.rs b/nvx-rs/src/host/cli/sandbox/lifecycle.rs index 96b195d30..6153a224c 100644 --- a/nvx-rs/src/host/cli/sandbox/lifecycle.rs +++ b/nvx-rs/src/host/cli/sandbox/lifecycle.rs @@ -31,7 +31,9 @@ //! network options that `sandbox_lifecycle.py` recorded: it refuses to start a sandbox that //! `nvx.py` or an earlier `nvx-rs` provisioned, which has no bindings or no typed network. It //! records shares as the export plan that `provision` made, whose host objects [`start`] checks -//! again. +//! again. [`start`] exports the shares, and once the guest agent is ready sends it the plan's +//! mapping table, which it mounts in order before any workload runs; a mapping that fails ends the +//! start, after the guest shuts down as a stop has it do. //! //! Every transition but provision finds the sandbox's VM with [`supervisor::reattach`], as an //! orchestrator does after it restarts: it ends a start that was interrupted, holds a recorded @@ -564,15 +566,36 @@ fn start_locked( }) .map_err(error_with_cause)?; let pid = starting.process().reference().pid; - let Err(error) = check_ready(starting.endpoint(), pid, &capability, timeout) else { + let maps = prepared.plan().mapping_table(); + // Whether the guest agent acknowledged a request to shut down after a mapping failed. + let mut stopping = false; + let ready = + check_ready(starting.endpoint(), pid, &capability, timeout).and_then(|mut session| { + // Workloads run only once the guest agent has mapped every share in order, so a + // mapping that fails ends the start. A sandbox without shares maps nothing. + if maps.is_empty() { + return Ok(()); + } + session.map_host_paths(&maps, timeout).inspect_err(|error| { + // The agent then refuses workloads, so the guest shuts down as a stop has it do: + // it unmounts what it mapped, the export, the overlay, and the scratch disk before + // the VM powers off. A failed transfer closed the session, so a guest that stopped + // answering is terminated at once. + if !matches!(error, Exit::Interrupted) { + stopping = session.stop(timeout).is_ok(); + } + }) + }); + let Err(error) = ready else { // The guest is ready, so OpenVMM holds the images: the checked files can go, which // releases their guards, while OpenVMM keeps the scratch image's claim. drop(prepared); return starting.commit().map(drop).map_err(error_with_cause); }; // OpenVMM closes the control endpoint as it tears the VM down, before it publishes its - // outcome report and exits, so only a closed endpoint warrants waiting for it. - let grace = if matches!(error, Exit::EndpointClosed) { + // outcome report and exits, so only a closed endpoint, or a guest that shuts down, warrants + // waiting for it. + let grace = if stopping || matches!(error, Exit::EndpointClosed) { timeout } else { 0.0 @@ -588,7 +611,9 @@ fn start_locked( // The checked files can go too, which releases their guards and the scratch image's claim. drop(prepared); let error = match status { - Some(status) if !matches!(error, Exit::Interrupted) => { + // A guest that shut down after a mapping failed exits as a stopped one does, so the + // mapping's failure tells why the start failed. + Some(status) if !stopping && !matches!(error, Exit::Interrupted) => { Exit::error(startup_exit_message(&outcome_path, status)?) } _ => error, @@ -618,13 +643,14 @@ fn binding_error(error: crate::Error) -> Exit { } /// Waits until the guest of a VM that starts answers on `endpoint`, which OpenVMM process `pid` -/// serves, and checks that it provides the features of [`REQUIRED_FEATURES`]. +/// serves, checks that it provides the features of [`REQUIRED_FEATURES`], and returns the session, +/// on which the caller sends the guest what it needs before the launch commits. fn check_ready( endpoint: &str, pid: u32, capability: &[u8; CAPABILITY_LEN], timeout: f64, -) -> Result { +) -> Result { let mut session = Session::connect(endpoint, pid, capability, timeout)?; session.ping(timeout)?; let features = session.features(timeout)?; @@ -636,7 +662,7 @@ fn check_ready( missing.join(", ") ))); } - Ok(()) + Ok(session) } /// Ends the OpenVMM process of a failed start, as `_end_failed_start` does: returns OpenVMM's diff --git a/nvx-rs/src/host/cli/sandbox/mod.rs b/nvx-rs/src/host/cli/sandbox/mod.rs index 11cc4b6c3..138259e17 100644 --- a/nvx-rs/src/host/cli/sandbox/mod.rs +++ b/nvx-rs/src/host/cli/sandbox/mod.rs @@ -680,12 +680,13 @@ pub(super) fn run(root: Option<&str>, options: Options) -> Result { } let plan = run_plan(&launch, &binding)?; let [openvmm, kernel, initrd] = artifacts.require()?; - // A dry run launches nothing, so it shows the plan's own paths; a run launches through - // the checked files, which it holds until OpenVMM exits. + // A one-shot run delivers the shares as boot tokens. A dry run launches nothing, so it + // shows the plan's own paths; a run launches through the checked files, which it holds + // until OpenVMM exits. let (arguments, command_line, prepared) = if options.dry_run { ( - plan.openvmm_arguments()?, - plan.kernel_command_line(&options.cmdline)?, + plan.one_shot_openvmm_arguments()?, + plan.one_shot_kernel_command_line(&options.cmdline)?, None, ) } else { @@ -749,8 +750,9 @@ fn run_plan(launch: &SandboxLaunch, binding: &DistroBinding) -> Result Result { + let payloads = encode_maps_payloads(maps, OUTER_MAX_PAYLOAD - APP_HEADER_LEN) + .map_err(|error| Exit::error(error.message()))?; + let deadline = Deadline::after(timeout); + for payload in payloads { + let request_id = request_id()?; + self.send(APP_MAPS, request_id, &payload, deadline)?; + let (kind, status, payload) = self.reply(request_id, deadline)?; + match kind { + APP_READY if status == 0 && payload.is_empty() => {} + APP_ERROR if payload == MAPPING_FAILED.as_bytes() => { + return Err(Exit::error(format!( + "managed guest could not mount a mapped host path (error {status})" + ))); + } + APP_ERROR => { + return Err(Exit::error(format!( + "managed guest did not mount the host paths: {} (status {status})", + String::from_utf8_lossy(&payload) + ))); + } + _ => { + return Err(Exit::error( + "managed guest returned an invalid host mapping response", + )); + } + } + } + Ok(()) + } + /// Runs a workload and returns how it ended, as `ControlSession.exec` does: the request and /// every response must arrive within `response_timeout` seconds of each other's start. pub(crate) fn exec( diff --git a/nvx-rs/src/host/sandbox/golden.rs b/nvx-rs/src/host/sandbox/golden.rs index 687333cf1..dc68b8e45 100644 --- a/nvx-rs/src/host/sandbox/golden.rs +++ b/nvx-rs/src/host/sandbox/golden.rs @@ -308,7 +308,9 @@ fn launches_give_the_arguments_and_command_lines_that_python_gives() { Some(recorded_plan(&mounts, &cwd, true)?) }; let launch = launch.with_export(export)?; - let mut arguments = launch.plan().openvmm_arguments()?; + // `nvx.py` rendered the shares as boot tokens, as the one-shot lifecycle still + // does. + let mut arguments = launch.plan().one_shot_openvmm_arguments()?; if let Some(export) = launch.export() { let placeholders = boot_shares(export)?.arguments.len(); arguments.truncate(arguments.len() - placeholders); @@ -316,7 +318,7 @@ fn launches_give_the_arguments_and_command_lines_that_python_gives() { } let command_line = launch .plan() - .kernel_command_line(text(case, "command_line")); + .one_shot_kernel_command_line(text(case, "command_line")); Ok(json!([ arguments, command_line.as_ref().ok(), diff --git a/nvx-rs/src/host/sandbox/mount.rs b/nvx-rs/src/host/sandbox/mount.rs index e4530c178..ca4914e80 100644 --- a/nvx-rs/src/host/sandbox/mount.rs +++ b/nvx-rs/src/host/sandbox/mount.rs @@ -6,12 +6,15 @@ //! runtime keeps the [`RESERVED_MOUNT_TARGETS`] and the [`RESERVED_EXACT_MOUNT_TARGETS`], and the //! sandbox records the resulting [`ExportPlan`]. //! -//! [`boot_shares`] renders such a plan in the form that the guest's shell reads at boot. OpenVMM -//! attaches one virtio-fs device, with the tag [`MOUNT_TAG`]. One directory uses it directly, and -//! the guest mounts it at its target. Several directories or files, or a file, share it as the -//! children of an aggregate, each named by [`aggregate_child_name`], which the guest mounts at -//! [`AGGREGATE_MOUNT_TARGET`], a directory that only the guest's root can enter, before it binds -//! each child at its target, as the `nvx_share=` kernel parameters tell it. +//! [`boot_shares`] renders such a plan in the form that the guest's shell reads at boot, as the +//! one-shot lifecycle delivers it. OpenVMM attaches one virtio-fs device, with the tag +//! [`MOUNT_TAG`]. One directory uses it directly, and the guest mounts it at its target. Several +//! directories or files, or a file, share it as the children of an aggregate, each named by +//! [`aggregate_child_name`], which the guest mounts at [`AGGREGATE_MOUNT_TARGET`], a directory +//! that only the guest's root can enter, before it binds each child at its target, as the +//! `nvx_share=` kernel parameters tell it. The managed lifecycle exports the same plan at +//! [`GUEST_EXPORT`] instead, from which the guest agent maps it as the plan's mapping table +//! orders; see [`SandboxPlan`](super::SandboxPlan). //! //! A share's access-policy paths are host paths: `--mount-deny` hides a path, `--mount-allow` //! exposes a path inside a denied path again, and `--mount-write` makes a path one of the only @@ -27,7 +30,8 @@ use sha2::{Digest, Sha256}; use super::refused; use crate::error::{Error, Result}; use crate::host::filesystem::{ - self, ExportPlan, ExportRequest, Mapping, Owner, PathList, ReservedTargets, Target, within, + self, ExportPlan, ExportRequest, GUEST_EXPORT, Mapping, Owner, PathList, ReservedTargets, + Target, within, }; use crate::host::python::builtins::{is_space, repr}; use crate::host::python::fs; @@ -977,17 +981,17 @@ pub(crate) fn plan_mounts_with( Ok(plan) } -/// The form in which the guest's shell receives an export plan at boot: OpenVMM's arguments that -/// attach its directories and files, the `nvx_share=` kernel parameters that tell the guest where -/// to bind the children of an aggregate, and the bootstrap tokens that OpenVMM appends to the -/// kernel command line. +/// The form in which a launch delivers an export plan at boot: OpenVMM's arguments that attach +/// its directories and files, the kernel parameters that the plan adds for them, and the +/// bootstrap tokens that OpenVMM appends to the kernel command line. #[derive(Clone, Debug, Default, PartialEq, Eq)] pub struct BootShares { /// OpenVMM's arguments: one directory share or an aggregate with its children, in order, the /// access-policy paths of each, absolute, and the owner unless it is `vmm`. pub arguments: Vec, - /// The `nvx_share=` kernel parameters of an aggregate, one for each child, in order; none for - /// one directory share. + /// The kernel parameters: as [`boot_shares`] renders them, the `nvx_share=` tokens of an + /// aggregate, one for each child, in order, and none for one directory share; for a mapping + /// table, the `nvx_maps=` token of its number of mappings. pub tokens: Vec, /// The bootstrap tokens that OpenVMM appends after the kernel command line. pub fragment: String, @@ -1133,12 +1137,36 @@ pub fn aggregate_share_tokens(shares: &[(&str, MountAccess, MountKind)]) -> Vec< /// Returns the bootstrap tokens that OpenVMM appends for an aggregate of shares with /// `accesses`, which it mounts read-write if any child is. pub fn aggregate_command_line_fragment(accesses: &[MountAccess]) -> String { + aggregate_fragment(AGGREGATE_MOUNT_TARGET, accesses) +} + +/// Returns the bootstrap tokens that OpenVMM appends for the export of `plan` at +/// [`GUEST_EXPORT`], the aggregate from which a managed sandbox's guest agent maps the plan's +/// mapping table. +pub(crate) fn export_command_line_fragment(plan: &ExportPlan) -> String { + let accesses: Vec = plan + .children + .iter() + .map(|child| { + if child.writable { + MountAccess::ReadWrite + } else { + MountAccess::ReadOnly + } + }) + .collect(); + aggregate_fragment(GUEST_EXPORT, &accesses) +} + +/// Returns the bootstrap tokens that OpenVMM appends for an aggregate at `target` whose children +/// have `accesses`, which it mounts read-write if any child is. +fn aggregate_fragment(target: &str, accesses: &[MountAccess]) -> String { let access = if accesses.contains(&MountAccess::ReadWrite) { MountAccess::ReadWrite } else { MountAccess::ReadOnly }; - command_line_fragment(AGGREGATE_MOUNT_TARGET, access) + AGGREGATE_COMMAND_LINE_SUFFIX + command_line_fragment(target, access) + AGGREGATE_COMMAND_LINE_SUFFIX } #[cfg(test)] diff --git a/nvx-rs/src/host/sandbox/options/tests.rs b/nvx-rs/src/host/sandbox/options/tests.rs index ed26a5a34..591a62e67 100644 --- a/nvx-rs/src/host/sandbox/options/tests.rs +++ b/nvx-rs/src/host/sandbox/options/tests.rs @@ -582,9 +582,10 @@ impl Shares { launch.validated()?; let launch = launch.with_export(plan_mounts(&mounts)?)?; validate_sandbox_systemd_policy(&launch)?; + // The command runs one-shot, which renders the shares as boot tokens. Ok(( - launch.plan().openvmm_arguments()?, - launch.plan().kernel_command_line("")?, + launch.plan().one_shot_openvmm_arguments()?, + launch.plan().one_shot_kernel_command_line("")?, )) } } diff --git a/nvx-rs/src/host/sandbox/plan.rs b/nvx-rs/src/host/sandbox/plan.rs index 42446ea3f..27754229c 100644 --- a/nvx-rs/src/host/sandbox/plan.rs +++ b/nvx-rs/src/host/sandbox/plan.rs @@ -25,8 +25,13 @@ //! scratch block device for a RAM upper, and the network device, and //! [`kernel_command_line`](SandboxPlan::kernel_command_line) describes the root with the boot //! tokens of [`protocol::root`](crate::protocol::root), within the budget that OpenVMM leaves the -//! profile. Both render the shares as the guest's shell reads them at boot, as -//! [`mount::boot_shares`] does. The plan's arguments name the block devices by their paths; a +//! profile. Both render the shares as the managed lifecycle delivers them: OpenVMM exports them +//! at [`GUEST_EXPORT`](crate::host::filesystem::GUEST_EXPORT), where the guest mounts the export, +//! the kernel command line announces the number of their mappings with `nvx_maps=`, and the host +//! sends the plan's [`mapping_table`](SandboxPlan::mapping_table) in `MAPS` requests once the +//! guest agent is ready, which maps each in order beneath the container's root. The CLI's +//! one-shot lifecycle still renders them as boot tokens, from which the guest's shell binds them, +//! as [`mount::boot_shares`] does. The plan's arguments name the block devices by their paths; a //! launch renders them through a [`PreparedLaunch`](super::PreparedLaunch), which names the files //! that the checks of the images opened instead. //! @@ -108,6 +113,7 @@ use crate::host::filesystem::{ExportPlan, ReservedTargets}; use crate::host::network::{self, NetworkPolicy}; use crate::host::python::builtins::{repr, split, strip}; use crate::host::python::path::{Flavor, PurePath}; +use crate::protocol::HostMap; use crate::protocol::root::{ DISTRO_MMIO_BASE, ImageFormat, RootImage, RootLayout, RootUpper, SCRATCH_MMIO_BASE, }; @@ -116,6 +122,20 @@ use crate::uuid::Uuid; /// The version of the serde form of [`SandboxPlan`] that this build writes and reads. pub const PLAN_VERSION: u32 = 3; +/// How a launch delivers the shares of a plan to the guest. +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub(crate) enum Delivery { + /// The managed lifecycle's: OpenVMM exports the shares at + /// [`GUEST_EXPORT`](crate::host::filesystem::GUEST_EXPORT), the kernel command line announces + /// the number of their mappings, and the host sends the mapping table once the guest agent is + /// ready. + MappingTable, + /// The one-shot lifecycle's, which only the CLI launches: boot tokens, from which the guest's + /// shell binds the shares. + #[cfg(any(test, feature = "cli"))] + BootTokens, +} + /// The role of a block device of a plan, which fixes its MMIO base and its access. #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)] pub enum BlockRole { @@ -500,29 +520,53 @@ impl SandboxPlan { } } - /// Returns the shares in the form that the guest's shell reads at boot, which - /// [`mount::boot_shares`] renders from the export plan; nothing without shares. - fn boot_shares(&self) -> Result { - self.export - .as_ref() - .map_or_else(|| Ok(BootShares::default()), mount::boot_shares) + /// Returns the shares as `delivery` delivers them, which [`mount::boot_shares`] renders as + /// boot tokens; nothing without shares. + fn shares(&self, delivery: Delivery) -> Result { + let Some(export) = &self.export else { + return Ok(BootShares::default()); + }; + Ok(match delivery { + Delivery::MappingTable => BootShares { + arguments: export.openvmm_arguments(), + tokens: vec![export.kernel_token()], + fragment: mount::export_command_line_fragment(export), + }, + #[cfg(any(test, feature = "cli"))] + Delivery::BootTokens => mount::boot_shares(export)?, + }) } - /// Returns the OpenVMM arguments of the plan: the microVM machine, a sandbox block device for - /// each block device of the plan in role order, `ROLE:file:PATH` with `,ro` for the read-only - /// image, the workload identity, the arguments that attach the shares, and those of the - /// network, [`SandboxNetwork::openvmm_arguments`]. + /// Returns the OpenVMM arguments of the plan as the managed lifecycle launches it: the + /// microVM machine, a sandbox block device for each block device of the plan in role order, + /// `ROLE:file:PATH` with `,ro` for the read-only image, the workload identity, the arguments + /// that export the shares at [`GUEST_EXPORT`](crate::host::filesystem::GUEST_EXPORT), which + /// [`ExportPlan::openvmm_arguments`] renders, and from which the guest agent maps them as + /// [`mapping_table`](Self::mapping_table) orders, and those of the network, + /// [`SandboxNetwork::openvmm_arguments`]. /// - /// Fails as [`mount::boot_shares`] and [`SandboxNetwork::openvmm_arguments`] do. + /// Fails as [`SandboxNetwork::openvmm_arguments`] does. pub fn openvmm_arguments(&self) -> Result> { - self.render_arguments(&|_, path| path.as_str().to_owned()) + self.render_arguments(&|_, path| path.as_str().to_owned(), Delivery::MappingTable) } - /// Renders the OpenVMM arguments of [`openvmm_arguments`](Self::openvmm_arguments), with - /// `block` naming the file of each block device, given its role and its path in the plan. + /// Returns the OpenVMM arguments of the plan as the one-shot lifecycle launches it: as + /// [`openvmm_arguments`](Self::openvmm_arguments) does, but with the arguments that attach + /// the shares as the guest's shell binds them at boot. + /// + /// Fails as [`mount::boot_shares`] and [`SandboxNetwork::openvmm_arguments`] do. + #[cfg(any(test, feature = "cli"))] + pub(crate) fn one_shot_openvmm_arguments(&self) -> Result> { + self.render_arguments(&|_, path| path.as_str().to_owned(), Delivery::BootTokens) + } + + /// Renders the OpenVMM arguments of the plan, with `block` naming the file of each block + /// device, given its role and its path in the plan, and with the shares as `delivery` delivers + /// them. pub(crate) fn render_arguments( &self, block: &dyn Fn(BlockRole, &PurePath) -> String, + delivery: Delivery, ) -> Result> { let mut arguments = vec!["--machine".to_owned(), "microvm".to_owned()]; for (role, path) in self.pure_blocks() { @@ -535,27 +579,57 @@ impl SandboxPlan { "--microvm-workload-identity".to_owned(), format!("{uid}:{gid}"), ]); - arguments.extend(self.boot_shares()?.arguments); + arguments.extend(self.shares(delivery)?.arguments); if let Some(network) = &self.network { arguments.extend(network.openvmm_arguments()?); } Ok(arguments) } - /// Returns the kernel command line of the plan: `user_command_line`, stripped of Python - /// whitespace, then `nvx_sandbox=1`, the boot tokens of the root's image and upper, - /// `nvx_entrypoint=`, `nvx_hostname=`, a `nvx_arg=` token for each argument, - /// `nvx_memory_max=` and `nvx_pids_max=` when set, and the `nvx_share=` tokens of an - /// aggregate, which [`mount::boot_shares`] renders. + /// Returns the plan's mapping table, the binds of its export plan in their order, which + /// [`ExportPlan::guest_table`] renders: what the managed lifecycle sends in `MAPS` requests + /// once the guest agent is ready, and before the launch is usable. A plan without shares has + /// none, and its launch maps nothing. + pub fn mapping_table(&self) -> Vec { + self.export + .as_ref() + .map_or_else(Vec::new, ExportPlan::guest_table) + } + + /// Returns the kernel command line of the plan as the managed lifecycle boots it: + /// `user_command_line`, stripped of Python whitespace, then `nvx_sandbox=1`, the boot tokens + /// of the root's image and upper, `nvx_entrypoint=`, `nvx_hostname=`, a `nvx_arg=` token for + /// each argument, `nvx_memory_max=` and `nvx_pids_max=` when set, and with shares the + /// `nvx_maps=` token that announces the number of mappings of + /// [`mapping_table`](Self::mapping_table). /// /// The user's command line may hold no NUL and no `nvx_*` or `virtfs_*` token, which the /// profile and OpenVMM own. The command line, the bootstrap tokens that OpenVMM appends for /// the shares, and a NUL must fit in [`SANDBOX_COMMAND_LINE_MAX_SIZE`] bytes. The guest must /// then read the plan's root from the command line: one that [`RootLayout::parse`] refuses /// fails too, as when the user's command line adds a virtio-mmio device at the scratch base - /// beside a RAM upper. Fails with [`ErrorKind::Unsupported`](crate::ErrorKind::Unsupported), - /// or as [`mount::boot_shares`] does. + /// beside a RAM upper. Fails with [`ErrorKind::Unsupported`](crate::ErrorKind::Unsupported). pub fn kernel_command_line(&self, user_command_line: &str) -> Result { + self.command_line(user_command_line, Delivery::MappingTable) + } + + /// Returns the kernel command line of the plan as the one-shot lifecycle boots it: as + /// [`kernel_command_line`](Self::kernel_command_line) does, but with the `nvx_share=` tokens + /// of an aggregate, which [`mount::boot_shares`] renders, instead of `nvx_maps=`. + /// + /// Fails as [`kernel_command_line`](Self::kernel_command_line) and [`mount::boot_shares`] + /// do. + #[cfg(any(test, feature = "cli"))] + pub(crate) fn one_shot_kernel_command_line(&self, user_command_line: &str) -> Result { + self.command_line(user_command_line, Delivery::BootTokens) + } + + /// Returns the kernel command line of the plan, with the shares as `delivery` delivers them. + pub(crate) fn command_line( + &self, + user_command_line: &str, + delivery: Delivery, + ) -> Result { if user_command_line.contains('\0') { return Err(refused("kernel command line contains an embedded NUL")); } @@ -596,17 +670,24 @@ impl SandboxPlan { tokens: shares, fragment, .. - } = self.boot_shares()?; + } = self.shares(delivery)?; tokens.extend(shares); tokens.retain(|token| !token.is_empty()); let command_line = tokens.join(" "); // OpenVMM appends the shares' bootstrap tokens after this command line, so they consume // the same x86 budget. if command_line.len() + fragment.len() + 1 > SANDBOX_COMMAND_LINE_MAX_SIZE { - return Err(refused( - "sandbox kernel command line exceeds its 1024-byte x86 budget; attach fewer \ - --mount shares or use shorter targets and arguments", - )); + // Only boot tokens put the shares' targets on the command line. + let advice = match delivery { + Delivery::MappingTable => "use shorter arguments and kernel parameters", + #[cfg(any(test, feature = "cli"))] + Delivery::BootTokens => { + "attach fewer --mount shares or use shorter targets and arguments" + } + }; + return Err(refused(format!( + "sandbox kernel command line exceeds its 1024-byte x86 budget; {advice}" + ))); } let layout = RootLayout::parse(command_line.as_bytes()).map_err(|error| { refused(format!( diff --git a/nvx-rs/src/host/sandbox/plan/tests.rs b/nvx-rs/src/host/sandbox/plan/tests.rs index 7b4d6eb24..a0db5fa83 100644 --- a/nvx-rs/src/host/sandbox/plan/tests.rs +++ b/nvx-rs/src/host/sandbox/plan/tests.rs @@ -15,7 +15,7 @@ use crate::host::network::{ }; use crate::host::python::builtins::Int; use crate::host::sandbox::distro::DistroBinding; -use crate::host::sandbox::mount::boot_shares; +use crate::host::sandbox::mount::{boot_shares, export_command_line_fragment}; use crate::host::sandbox::tests::{deny, exported, host, host_text}; use crate::host::sandbox::{LayerRole, MountAccess, MountKind, SandboxLaunch, SandboxLayer}; @@ -98,13 +98,41 @@ fn nested(identity: Option) -> Bind { } } -/// Returns the bootstrap tokens that OpenVMM appends for the shares of `plan`. +/// Returns the bootstrap tokens that OpenVMM appends for the shares of `plan` in the managed +/// lifecycle, which exports them for the guest agent's mapping table. fn fragment(plan: &SandboxPlan) -> String { plan.export() - .map(|export| boot_shares(export).unwrap().fragment) + .map(export_command_line_fragment) .unwrap_or_default() } +/// A rendering of a plan's kernel command line, and of the bootstrap tokens that OpenVMM appends +/// for its export plan. +type Rendering = ( + fn(&SandboxPlan, &str) -> Result, + fn(&ExportPlan) -> String, +); + +/// Returns the renderings of the managed lifecycle, which announces a mapping table, and of the +/// one-shot lifecycle, which carries boot tokens, by name. +fn renderings() -> [(&'static str, Rendering); 2] { + [ + ( + "managed", + ( + SandboxPlan::kernel_command_line, + export_command_line_fragment, + ), + ), + ( + "one-shot", + (SandboxPlan::one_shot_kernel_command_line, |export| { + boot_shares(export).unwrap().fragment + }), + ), + ] +} + #[test] fn every_format_and_upper_plans_and_renders() { let settings = SandboxSettings { @@ -260,36 +288,109 @@ fn the_longest_boot_tokens_fit_the_command_line_budget_to_the_byte() { // of the budget, which every other plan keeps the rest of. let longest = plan(images()[0], uppers()[0].clone(), SandboxSettings::default()); let longest_base = longest.kernel_command_line("").unwrap().len(); - for export in [None, Some(shares(true)), Some(shares(false))] { - for image in images() { - for upper in uppers() { - let plan = exporting(image, upper, SandboxSettings::default(), export.clone()); - let base = plan.kernel_command_line("").unwrap(); - let fragment = fragment(&plan); - // The user's command line, a space, the plan's tokens, OpenVMM's share tokens, - // and a NUL fill the budget exactly. - let fitting = - "x".repeat(SANDBOX_COMMAND_LINE_MAX_SIZE - base.len() - fragment.len() - 2); - let command_line = plan.kernel_command_line(&fitting).unwrap(); - assert_eq!( - command_line.len() + fragment.len() + 1, - SANDBOX_COMMAND_LINE_MAX_SIZE - ); - assert_eq!( - RootLayout::parse(command_line.as_bytes()), - Ok(Some(plan.layout())) - ); - assert!( - message(plan.kernel_command_line(&format!("{fitting}x"))).contains("1024-byte") - ); - if plan.export().is_none() { - assert!(base.len() <= longest_base, "{base}"); + for (lifecycle, (render, appended)) in renderings() { + for export in [None, Some(shares(true)), Some(shares(false))] { + for image in images() { + for upper in uppers() { + let plan = exporting(image, upper, SandboxSettings::default(), export.clone()); + let base = render(&plan, "").unwrap(); + let fragment = plan.export().map(appended).unwrap_or_default(); + // The user's command line, a space, the plan's tokens, OpenVMM's share + // tokens, and a NUL fill the budget exactly. + let fitting = + "x".repeat(SANDBOX_COMMAND_LINE_MAX_SIZE - base.len() - fragment.len() - 2); + let command_line = render(&plan, &fitting).unwrap(); + assert_eq!( + command_line.len() + fragment.len() + 1, + SANDBOX_COMMAND_LINE_MAX_SIZE, + "{lifecycle}" + ); + assert_eq!( + RootLayout::parse(command_line.as_bytes()), + Ok(Some(plan.layout())) + ); + assert!( + message(render(&plan, &format!("{fitting}x"))).contains("1024-byte"), + "{lifecycle}" + ); + if plan.export().is_none() { + assert!(base.len() <= longest_base, "{base}"); + } } } } } } +#[test] +fn the_managed_lifecycle_exports_the_shares_and_announces_their_mapping_table() { + let export = shares(false); + let bare = plan(images()[0], uppers()[0].clone(), SandboxSettings::default()); + let plan = exporting( + images()[0], + uppers()[0].clone(), + SandboxSettings::default(), + Some(export.clone()), + ); + // OpenVMM exports the shares where the guest agent maps them from, after the block devices + // and the workload identity. + let blocks = bare.openvmm_arguments().unwrap(); + let arguments = plan.openvmm_arguments().unwrap(); + assert_eq!(arguments[..blocks.len()], blocks[..]); + assert_eq!(arguments[blocks.len()..], export.openvmm_arguments()[..]); + assert_eq!( + arguments[blocks.len()..][..2], + ["--mount-aggregate", crate::host::filesystem::GUEST_EXPORT] + ); + // The kernel command line announces the number of mappings, not their targets, and OpenVMM + // appends the export's tokens, read-write since a child is. + let base = bare.kernel_command_line("quiet").unwrap(); + assert_eq!( + plan.kernel_command_line("quiet").unwrap(), + format!("{base} nvx_maps=2") + ); + assert_eq!( + fragment(&plan), + " virtfs_dir=/run/nvx/hostfs/root virtfs_tag=microvm virtfs_mode=rw virtfs_aggregate=1" + ); + let read_only = exporting( + images()[0], + uppers()[0].clone(), + SandboxSettings::default(), + Some(exported(&[( + "/srv/cache", + "/host/cache", + MountAccess::ReadOnly, + MountKind::Directory, + )])), + ); + assert!(fragment(&read_only).contains(" virtfs_mode=ro ")); + // The mapping table is the export plan's binds, in order: parents first. + assert_eq!(plan.mapping_table(), export.guest_table()); + assert_eq!( + plan.mapping_table() + .iter() + .map(|map| map.target.as_str()) + .collect::>(), + ["/workspace", "/srv/cache"] + ); + // The one-shot lifecycle renders the same plan as boot tokens. + let boot = boot_shares(&export).unwrap(); + assert_eq!( + plan.one_shot_openvmm_arguments().unwrap()[blocks.len()..], + boot.arguments[..] + ); + assert_eq!( + plan.one_shot_kernel_command_line("quiet").unwrap(), + format!("{base} {}", boot.tokens.join(" ")) + ); + // Without shares, both render alike, and nothing is mapped. + assert!(bare.mapping_table().is_empty()); + assert_eq!(bare.one_shot_openvmm_arguments().unwrap(), blocks); + assert_eq!(bare.one_shot_kernel_command_line("quiet").unwrap(), base); + assert!(!base.contains("nvx_maps=")); +} + #[test] fn plans_check_their_settings_as_launches_do() { let checked = |change: fn(&mut SandboxSettings)| { diff --git a/nvx-rs/src/host/sandbox/prepared.rs b/nvx-rs/src/host/sandbox/prepared.rs index a743f80f9..866502a19 100644 --- a/nvx-rs/src/host/sandbox/prepared.rs +++ b/nvx-rs/src/host/sandbox/prepared.rs @@ -54,7 +54,7 @@ use std::path::Path; use super::distro::CheckedDistro; #[cfg(any(target_os = "linux", windows))] use super::mount::os_error; -use super::plan::{self, BlockRole, SandboxPlan}; +use super::plan::{self, BlockRole, Delivery, SandboxPlan}; use super::refused; use super::scratch::CheckedScratch; #[cfg(windows)] @@ -151,6 +151,45 @@ impl PreparedLaunch { distro: CheckedDistro, scratch: Option, user_command_line: &str, + ) -> Result { + Self::prepare( + plan, + distro, + scratch, + user_command_line, + Delivery::MappingTable, + ) + } + + /// Prepares the one-shot launch of `plan`, as [`new`](Self::new) does, but with the shares as + /// the one-shot lifecycle delivers them, which + /// [`SandboxPlan::one_shot_openvmm_arguments`] and + /// [`SandboxPlan::one_shot_kernel_command_line`] render: as the guest's shell binds them at + /// boot. + #[cfg(feature = "cli")] + pub(crate) fn one_shot( + plan: SandboxPlan, + distro: CheckedDistro, + scratch: Option, + user_command_line: &str, + ) -> Result { + Self::prepare( + plan, + distro, + scratch, + user_command_line, + Delivery::BootTokens, + ) + } + + /// Implements [`new`](Self::new) and [`one_shot`](Self::one_shot), with the shares as + /// `delivery` delivers them. + fn prepare( + plan: SandboxPlan, + distro: CheckedDistro, + scratch: Option, + user_command_line: &str, + delivery: Delivery, ) -> Result { let planned = plan.distro().path(); if !same_path(distro.path(), planned) { @@ -197,14 +236,17 @@ impl PreparedLaunch { Some(scratch) => Some(checked_path(scratch.file(), scratch.path())?), None => None, }; - let openvmm_arguments = plan.render_arguments(&|role, _| match (role, &scratch_block) { - (BlockRole::Distro, _) => distro_block.clone(), - (BlockRole::Scratch, Some(block)) => block.clone(), - (BlockRole::Scratch, None) => { - unreachable!("a plan with a scratch block has its checked scratch image") - } - })?; - let kernel_command_line = plan.kernel_command_line(user_command_line)?; + let openvmm_arguments = plan.render_arguments( + &|role, _| match (role, &scratch_block) { + (BlockRole::Distro, _) => distro_block.clone(), + (BlockRole::Scratch, Some(block)) => block.clone(), + (BlockRole::Scratch, None) => { + unreachable!("a plan with a scratch block has its checked scratch image") + } + }, + delivery, + )?; + let kernel_command_line = plan.command_line(user_command_line, delivery)?; Ok(Self { plan, distro, @@ -230,7 +272,8 @@ impl PreparedLaunch { } /// Returns the OpenVMM arguments of the plan, as [`SandboxPlan::openvmm_arguments`] renders - /// them, except that each block device names its checked file: on Linux as `/proc/self/fd/N`, + /// them, or for the CLI's one-shot launch with the shares as the guest's shell binds them at + /// boot, except that each block device names its checked file: on Linux as `/proc/self/fd/N`, /// which [`inherited`](Self::inherited) passes the VMM under the number `N`, and on Windows by /// its final path. /// @@ -240,7 +283,8 @@ impl PreparedLaunch { } /// Returns the kernel command line of the plan, with the user's command line given to - /// [`new`](Self::new). + /// [`new`](Self::new), as [`SandboxPlan::kernel_command_line`] renders it, or for the CLI's + /// one-shot launch with the shares' boot tokens. pub fn kernel_command_line(&self) -> &str { &self.kernel_command_line } diff --git a/nvx-rs/src/host/sandbox/tests.rs b/nvx-rs/src/host/sandbox/tests.rs index ca1854d9e..73c30b2e3 100644 --- a/nvx-rs/src/host/sandbox/tests.rs +++ b/nvx-rs/src/host/sandbox/tests.rs @@ -191,31 +191,37 @@ fn launch_contract_rejects_duplicates_and_reserved_tokens() { assert_eq!(error.kind(), ErrorKind::Unsupported); assert_eq!(error.to_string(), "duplicate sandbox layer role(s): distro"); let launch = with_export(None).unwrap(); + let plan = launch.plan(); + let renderings: [fn(&SandboxPlan, &str) -> Result; 2] = [ + SandboxPlan::kernel_command_line, + SandboxPlan::one_shot_kernel_command_line, + ]; + for render in renderings { + assert_eq!( + message(render(plan, "nvx_sandbox=0")), + "nvx_sandbox is owned by the sandbox profile" + ); + assert_eq!( + message(render(plan, r"foo=bar\ nvx_memory_max=max")), + "nvx_memory_max is owned by the sandbox profile" + ); + assert_eq!( + message(render(plan, "a\0b")), + "kernel command line contains an embedded NUL" + ); + } + // Only the one-shot lifecycle puts the shares' targets on the command line. + let long = "x".repeat(SANDBOX_COMMAND_LINE_MAX_SIZE); assert_eq!( - message(launch.plan().kernel_command_line("nvx_sandbox=0")), - "nvx_sandbox is owned by the sandbox profile" + message(plan.kernel_command_line(&long)), + "sandbox kernel command line exceeds its 1024-byte x86 budget; use shorter arguments and \ + kernel parameters" ); assert_eq!( - message( - launch - .plan() - .kernel_command_line(r"foo=bar\ nvx_memory_max=max") - ), - "nvx_memory_max is owned by the sandbox profile" - ); - assert_eq!( - message( - launch - .plan() - .kernel_command_line(&"x".repeat(SANDBOX_COMMAND_LINE_MAX_SIZE)) - ), + message(plan.one_shot_kernel_command_line(&long)), "sandbox kernel command line exceeds its 1024-byte x86 budget; attach fewer --mount \ shares or use shorter targets and arguments" ); - assert_eq!( - message(launch.plan().kernel_command_line("a\0b")), - "kernel command line contains an embedded NUL" - ); assert_eq!( message(parse_workload_identity("0:0")), "--workload-user UID must be between 1 and 4294967295" @@ -366,7 +372,7 @@ fn launch_contract_attaches_mount_and_reserves_bootstrap_tokens() { )]); deny(&mut plan, 0, &["/host/share/secrets"]); let launch = with_export(Some(plan)).unwrap(); - let arguments = launch.plan().openvmm_arguments().unwrap(); + let arguments = launch.plan().one_shot_openvmm_arguments().unwrap(); let start = arguments .iter() .position(|argument| argument == "--mount") @@ -383,7 +389,7 @@ fn launch_contract_attaches_mount_and_reserves_bootstrap_tokens() { assert!( !launch .plan() - .kernel_command_line("quiet") + .one_shot_kernel_command_line("quiet") .unwrap() .contains("virtfs_") ); @@ -393,14 +399,14 @@ fn launch_contract_attaches_mount_and_reserves_bootstrap_tokens() { ("virtfs_mode=rw", "virtfs_mode"), ] { assert_eq!( - message(launch.plan().kernel_command_line(token)), + message(launch.plan().one_shot_kernel_command_line(token)), format!("{name} is owned by the sandbox --mount option") ); } let base = with_export(None) .unwrap() .plan() - .kernel_command_line("") + .one_shot_kernel_command_line("") .unwrap(); let fragment = mount::boot_shares(launch.export().unwrap()) .unwrap() @@ -410,9 +416,17 @@ fn launch_contract_attaches_mount_and_reserves_bootstrap_tokens() { " virtfs_dir=/workspace virtfs_tag=microvm virtfs_mode=rw" ); let fitting = "x".repeat(SANDBOX_COMMAND_LINE_MAX_SIZE - base.len() - fragment.len() - 2); - launch.plan().kernel_command_line(&fitting).unwrap(); + launch + .plan() + .one_shot_kernel_command_line(&fitting) + .unwrap(); assert!( - message(launch.plan().kernel_command_line(&format!("{fitting}x"))).contains("1024-byte") + message( + launch + .plan() + .one_shot_kernel_command_line(&format!("{fitting}x")) + ) + .contains("1024-byte") ); } @@ -447,7 +461,7 @@ fn launch_contract_attaches_several_shares_as_an_aggregate() { .enumerate() .map(|(index, &(target, ..))| mount::aggregate_child_name(index, target)) .collect(); - let arguments = launch.plan().openvmm_arguments().unwrap(); + let arguments = launch.plan().one_shot_openvmm_arguments().unwrap(); // Several shares are the children of one aggregate, and OpenVMM attributes each denied // path, which is absolute, to the child that contains it. assert!(!arguments.iter().any(|argument| argument == "--mount")); @@ -478,7 +492,7 @@ fn launch_contract_attaches_several_shares_as_an_aggregate() { " virtfs_dir=/run/nvx/shares virtfs_tag=microvm virtfs_mode=rw virtfs_aggregate=1" ); // The guest binds each child at its target, in order. - let command_line = launch.plan().kernel_command_line("").unwrap(); + let command_line = launch.plan().one_shot_kernel_command_line("").unwrap(); assert!(!command_line.contains("virtfs_")); assert!( command_line.ends_with(&format!( @@ -495,21 +509,33 @@ fn launch_contract_attaches_several_shares_as_an_aggregate() { " virtfs_dir=/run/nvx/shares virtfs_tag=microvm virtfs_mode=ro virtfs_aggregate=1" ); assert_eq!( - message(launch.plan().kernel_command_line("nvx_share=0,/etc,rw")), + message( + launch + .plan() + .one_shot_kernel_command_line("nvx_share=0,/etc,rw") + ), "nvx_share is owned by the sandbox profile" ); // Every share's tokens count toward the x86 budget. let base = with_export(None) .unwrap() .plan() - .kernel_command_line("") + .one_shot_kernel_command_line("") .unwrap(); let tokens = command_line.len() - base.len(); let fitting = "x".repeat(SANDBOX_COMMAND_LINE_MAX_SIZE - base.len() - tokens - fragment.len() - 2); - launch.plan().kernel_command_line(&fitting).unwrap(); + launch + .plan() + .one_shot_kernel_command_line(&fitting) + .unwrap(); assert!( - message(launch.plan().kernel_command_line(&format!("{fitting}x"))).contains("1024-byte") + message( + launch + .plan() + .one_shot_kernel_command_line(&format!("{fitting}x")) + ) + .contains("1024-byte") ); let caller = ExportPlan { @@ -549,9 +575,22 @@ fn launch_bounds_shares_by_the_kernel_command_line() { .collect(); with_export(Some(exported(&shares))).unwrap() }; - // No fixed number of shares is the limit, only the command line. - launch(10).plan().kernel_command_line("").unwrap(); - assert!(message(launch(20).plan().kernel_command_line("")).contains("fewer --mount shares")); + // No fixed number of shares is the limit of the one-shot lifecycle, only the command line, + // which carries each share's target. + launch(10).plan().one_shot_kernel_command_line("").unwrap(); + assert!( + message(launch(20).plan().one_shot_kernel_command_line("")) + .contains("fewer --mount shares") + ); + // The managed lifecycle announces only their number, and sends them once the guest is ready. + assert!( + launch(20) + .plan() + .kernel_command_line("") + .unwrap() + .ends_with(" nvx_maps=20") + ); + assert_eq!(launch(20).plan().mapping_table().len(), 20); } #[test] @@ -600,7 +639,7 @@ fn launch_contract_attaches_a_file_as_an_aggregate_child() { let name = mount::aggregate_child_name(0, "/etc/app/settings.json"); // Even alone, a file is the child of an aggregate, because the guest mounts the device's // root, which is a directory. - let arguments = launch.plan().openvmm_arguments().unwrap(); + let arguments = launch.plan().one_shot_openvmm_arguments().unwrap(); assert!(!arguments.iter().any(|argument| argument == "--mount")); let start = arguments .iter() @@ -624,7 +663,7 @@ fn launch_contract_attaches_a_file_as_an_aggregate_child() { assert!( launch .plan() - .kernel_command_line("") + .one_shot_kernel_command_line("") .unwrap() .ends_with(&format!(" nvx_share={name},/etc/app/settings.json,ro,file")) ); @@ -656,7 +695,7 @@ fn launch_contract_attaches_a_file_as_an_aggregate_child() { assert!( mixed .plan() - .kernel_command_line("") + .one_shot_kernel_command_line("") .unwrap() .ends_with(&format!( " nvx_share={},/workspace,rw nvx_share={},/etc/app/settings.json,ro,file \ @@ -664,7 +703,7 @@ fn launch_contract_attaches_a_file_as_an_aggregate_child() { names[0], names[1], names[2] )) ); - let arguments = mixed.plan().openvmm_arguments().unwrap(); + let arguments = mixed.plan().one_shot_openvmm_arguments().unwrap(); let denied = arguments .iter() .position(|argument| argument == "--mount-deny") diff --git a/nvx-rs/src/protocol/features.rs b/nvx-rs/src/protocol/features.rs index d0a0d344c..f077f6e98 100644 --- a/nvx-rs/src/protocol/features.rs +++ b/nvx-rs/src/protocol/features.rs @@ -47,20 +47,23 @@ impl GuestFeatures { | Self::HOST_MAPPING_TABLE.0, ); /// Features announced by the managed agent that launches a sandbox container. - pub const SANDBOX_AGENT: Self = Self(Self::CANCEL.0 | Self::EXEC_ENVIRONMENT.0); + pub const SANDBOX_AGENT: Self = + Self(Self::CANCEL.0 | Self::EXEC_ENVIRONMENT.0 | Self::HOST_MAPPING_TABLE.0); /// The features that the host depends on. pub const REQUIRED: Self = Self::DIRECT_AGENT; /// The features that `nvx-rs sandbox` depends on in the layered sandbox root, whose agent - /// announces [`SANDBOX_AGENT`](Self::SANDBOX_AGENT): only + /// announces [`SANDBOX_AGENT`](Self::SANDBOX_AGENT): /// [`EXEC_ENVIRONMENT`](Self::EXEC_ENVIRONMENT), because `exec` sends a working directory and - /// an environment in an extended `EXEC`. + /// an environment in an extended `EXEC`, and + /// [`HOST_MAPPING_TABLE`](Self::HOST_MAPPING_TABLE), because `start` sends the mappings of + /// the sandbox's shares as `MAPS` requests. /// /// It holds no [`CANCEL`](Self::CANCEL), because the CLI sends no `APP_CANCEL`: as `nvx.py` /// did, Ctrl-C ends an `exec` by closing the session, and the guest agent ends the workload /// when OpenVMM resets the session that it ran for. It holds no /// [`WORKLOAD_ACCOUNT`](Self::WORKLOAD_ACCOUNT), because no sandbox launch requests account /// creation, which the layered root neither performs nor announces (microsoft/nvx#566). - pub const LAYERED_SANDBOX: Self = Self::EXEC_ENVIRONMENT; + pub const LAYERED_SANDBOX: Self = Self(Self::EXEC_ENVIRONMENT.0 | Self::HOST_MAPPING_TABLE.0); /// Human-readable names of every required feature, used in compatibility errors. pub(crate) const NAMES: [(Self, &'static str); 6] = [ diff --git a/nvx-rs/src/protocol/tests.rs b/nvx-rs/src/protocol/tests.rs index bc9aba540..11e748623 100644 --- a/nvx-rs/src/protocol/tests.rs +++ b/nvx-rs/src/protocol/tests.rs @@ -1056,12 +1056,15 @@ fn host_mapping_count_matches_the_guest_command_line_parser() { } #[test] -fn agent_feature_sets_match_the_c_modes() { +fn both_agent_modes_announce_the_host_mapping_table() { assert_eq!(GuestFeatures::DIRECT_AGENT.bits(), 0x7d); // The layered root creates no account, so it announces no workload accounts (bit 2). - assert_eq!(GuestFeatures::SANDBOX_AGENT.bits(), 0x11); + assert_eq!(GuestFeatures::SANDBOX_AGENT.bits(), 0x51); assert!(!GuestFeatures::SANDBOX_AGENT.contains(GuestFeatures::WORKLOAD_ACCOUNT)); assert!(GuestFeatures::DIRECT_AGENT.contains(GuestFeatures::WORKLOAD_ACCOUNT)); + for features in [GuestFeatures::DIRECT_AGENT, GuestFeatures::SANDBOX_AGENT] { + assert!(features.contains(GuestFeatures::HOST_MAPPING_TABLE)); + } assert_eq!( GuestFeatures::DIRECT_AGENT.bits() & (1 << 1), 0, @@ -1070,10 +1073,11 @@ fn agent_feature_sets_match_the_c_modes() { } #[test] -fn layered_sandboxes_need_only_per_execution_environments() { - // The CLI's exec sends working directories and environments; it never cancels a workload or - // asks for a workload account (microsoft/nvx#566). - assert_eq!(GuestFeatures::LAYERED_SANDBOX.bits(), 1 << 4); +fn layered_sandboxes_need_per_execution_environments_and_mapping_tables() { + // The CLI's exec sends working directories and environments, and its start sends the + // mappings of the shares; it never cancels a workload or asks for a workload account + // (microsoft/nvx#566). + assert_eq!(GuestFeatures::LAYERED_SANDBOX.bits(), (1 << 4) | (1 << 6)); assert!(GuestFeatures::SANDBOX_AGENT.contains(GuestFeatures::LAYERED_SANDBOX)); assert!( GuestFeatures::SANDBOX_AGENT @@ -1083,7 +1087,7 @@ fn layered_sandboxes_need_only_per_execution_environments() { assert_eq!( (GuestFeatures::CANCEL | GuestFeatures::WORKLOAD_ACCOUNT) .missing(GuestFeatures::LAYERED_SANDBOX), - ["per-execution environments"] + ["per-execution environments", "host path mapping tables"] ); } diff --git a/nvx-rs/src/testing/fake_openvmm.rs b/nvx-rs/src/testing/fake_openvmm.rs index d58ee599c..412fd8b16 100644 --- a/nvx-rs/src/testing/fake_openvmm.rs +++ b/nvx-rs/src/testing/fake_openvmm.rs @@ -53,15 +53,18 @@ //! The fake also serves the sandbox profile of `nvx.py sandbox` and `nvx-rs sandbox`, which a //! `--microvm-sandbox-block` option selects: read-only `distro`, `runtime`, and `custom` layers //! and a `scratch` disk, each an existing file, with `nvx_sandbox=1`, `nvx_entrypoint=`, and -//! `nvx_hostname=` on the kernel command line, and shares through one `--mount` or the children -//! of an aggregate at `/run/nvx/shares`. Like OpenVMM, it opens each block device at the path that -//! its option names, a layer read-only and the scratch disk for reading and writing, and holds -//! them until it exits; it reads them whole, and records what each held, with its role and path, -//! in `fake-openvmm--blocks.json` next to the kernel. The `fake_block_delay_ms=MS` token -//! delays the opens. Its guest advertises the features of the sandbox agent, -//! [`GuestFeatures::SANDBOX_AGENT`], and the guest targets of its directory shares are -//! directories that a workload can enter. With `--microvm-lifecycle managed`, it serves the -//! control console as above. With `--microvm-lifecycle one-shot`, it reads no capability and +//! `nvx_hostname=` on the kernel command line. Like OpenVMM, it opens each block device at the +//! path that its option names, a layer read-only and the scratch disk for reading and writing, +//! and holds them until it exits; it reads them whole, and records what each held, with its role +//! and path, in `fake-openvmm--blocks.json` next to the kernel. The +//! `fake_block_delay_ms=MS` token delays the opens. Its guest advertises the features of the +//! sandbox agent, [`GuestFeatures::SANDBOX_AGENT`]. With `--microvm-lifecycle managed`, it serves +//! the control console as above, and maps the sandbox's shares as above too: from the children of +//! the aggregate export at `/run/nvx/hostfs/root`, as many as `nvx_maps=` announces, which `MAPS` +//! requests deliver; it refuses a `--mount` share and `nvx_share=` tokens. With +//! `--microvm-lifecycle one-shot`, it takes the shares through one `--mount` or the children of +//! an aggregate at `/run/nvx/shares`, which `nvx_share=` tokens place, and whose guest targets of +//! directory shares are directories that a workload can enter; it reads no capability and //! serves no console: it runs the entrypoint and arguments of the kernel command line with its //! own standard streams, `/bin/echo` printing its arguments, `/bin/sleep` sleeping for its //! argument in seconds, `/bin/true` and `/bin/false` exiting with 0 and 1, and any other program @@ -675,20 +678,40 @@ fn parse(program: &str, arguments: &[String]) -> Result { if token_values("nvx_hostname=").len() != 1 { return Err("the kernel command line must set one nvx_hostname".to_owned()); } - if !token_values(MAPS_TOKEN).is_empty() { - return Err(format!("a sandbox takes no {MAPS_TOKEN}")); - } - let (children, mut share_targets) = sandbox_shares(&values)?; - // The guest binds each directory child of an aggregate at the target of its - // `nvx_share=NAME,TARGET,ACCESS[,file]` token. - for share in token_values("nvx_share=") { - match share.split(',').collect::>().as_slice() { - [_, target, _] => share_targets.push((*target).to_owned()), - [_, _, _, "file"] => {} - _ => return Err(format!("invalid nvx_share={share}")), + let (maps, children, share_targets) = match lifecycle { + // A managed sandbox's guest agent maps its shares from the export, as the mapping + // table of the host's `MAPS` requests orders. + Lifecycle::Managed => { + if values.contains_key("--mount") { + return Err("a managed sandbox takes no --mount".to_owned()); + } + if !token_values("nvx_share=").is_empty() { + return Err("a managed sandbox takes no nvx_share=".to_owned()); + } + let maps = mapping_count(&token_values(MAPS_TOKEN))?; + (maps, mapped_children(&values, maps)?, Vec::new()) } - } - (0, children, share_targets, workload, blocks) + // A one-shot sandbox's shell binds them at boot, as their tokens place them. + Lifecycle::OneShot => { + if !token_values(MAPS_TOKEN).is_empty() { + return Err(format!("a one-shot sandbox takes no {MAPS_TOKEN}")); + } + let (children, mut share_targets) = sandbox_shares(&values)?; + // The guest binds each directory child of an aggregate at the target of its + // `nvx_share=NAME,TARGET,ACCESS[,file]` token. + for share in token_values("nvx_share=") { + match share.split(',').collect::>().as_slice() { + [_, target, _] => share_targets.push((*target).to_owned()), + [_, _, _, "file"] => {} + _ => return Err(format!("invalid nvx_share={share}")), + } + } + (0, children, share_targets) + } + // A sandbox block device makes a command line no run. + Lifecycle::Run => return Err("a microVM run takes no sandbox block device".to_owned()), + }; + (maps, children, share_targets, workload, blocks) } else if run { // A run shares as a sandbox does, and its kernel command line is its user's. let (children, _) = sandbox_shares(&values)?; @@ -709,15 +732,7 @@ fn parse(program: &str, arguments: &[String]) -> Result { if !tokens.iter().any(|token| token.starts_with("hostname=")) { return Err("the kernel command line must set the hostname".to_owned()); } - let maps = match token_values(MAPS_TOKEN).as_slice() { - [] => 0, - [count] => count - .parse::() - .ok() - .filter(|count| (1..=MAX_HOST_MAPPINGS).contains(count)) - .ok_or_else(|| format!("invalid {MAPS_TOKEN}{count}"))?, - _ => return Err(format!("{MAPS_TOKEN} must be given at most once")), - }; + let maps = mapping_count(&token_values(MAPS_TOKEN))?; let children = mapped_children(&values, maps)?; (maps, children, Vec::new(), Vec::new(), Vec::new()) }; @@ -956,10 +971,25 @@ fn check_sandbox_blocks<'a>( Ok(checked) } -/// Returns the host directories of the shares of a sandbox or a run, for the checks of their -/// policy paths, and the guest targets of their directory shares: one `--mount TARGET,HOST,MODE` -/// of a directory, or the `--mount-child NAME,HOST,MODE[,file]` children of an aggregate at -/// `/run/nvx/shares`. +/// Returns the number of host mappings that the `nvx_maps=` tokens of a kernel command line, +/// whose values are `counts`, announce: none without a token, and otherwise from 1 through +/// [`MAX_HOST_MAPPINGS`], given once. +fn mapping_count(counts: &[&str]) -> Result { + match counts { + [] => Ok(0), + [count] => count + .parse::() + .ok() + .filter(|count| (1..=MAX_HOST_MAPPINGS).contains(count)) + .ok_or_else(|| format!("invalid {MAPS_TOKEN}{count}")), + _ => Err(format!("{MAPS_TOKEN} must be given at most once")), + } +} + +/// Returns the host directories of the shares of a one-shot sandbox or a run, for the checks of +/// their policy paths, and the guest targets of their directory shares: one +/// `--mount TARGET,HOST,MODE` of a directory, or the `--mount-child NAME,HOST,MODE[,file]` +/// children of an aggregate at `/run/nvx/shares`. fn sandbox_shares( values: &BTreeMap<&str, Vec<&str>>, ) -> Result<(Vec, Vec), String> { diff --git a/nvx-rs/tests/cli.rs b/nvx-rs/tests/cli.rs index 46905e516..f43bf2ee4 100644 --- a/nvx-rs/tests/cli.rs +++ b/nvx-rs/tests/cli.rs @@ -527,11 +527,24 @@ fn text(data: &[u8]) -> String { #[test] fn start_requires_the_guest_features_of_layered_sandboxes() { let root = populated_root(); - // A guest that lacks per-execution environments, or that predates feature negotiation, is - // stopped, and its start fails like any other. - for (state, command_line) in [ - ("cancel-only", "fake_guest_features=1"), - ("legacy", "fake_legacy_guest=1"), + // A guest that lacks per-execution environments or host path mapping tables, or that + // predates feature negotiation, is stopped, and its start fails like any other. + for (state, command_line, missing) in [ + ( + "cancel-only", + "fake_guest_features=1", + "per-execution environments, host path mapping tables", + ), + ( + "legacy", + "fake_legacy_guest=1", + "per-execution environments, host path mapping tables", + ), + ( + "environments-only", + "fake_guest_features=16", + "host path mapping tables", + ), ] { let output = run(&root, &provision(&root, state, command_line)); assert!(output.status.success(), "{}", text(&output.stderr)); @@ -539,8 +552,10 @@ fn start_requires_the_guest_features_of_layered_sandboxes() { assert_eq!(output.status.code(), Some(1)); assert_eq!( text(&output.stderr), - "error: the guest image lacks control features that layered sandboxes need \ - (per-execution environments); use an NVX release or build that includes them\n" + format!( + "error: the guest image lacks control features that layered sandboxes need \ + ({missing}); use an NVX release or build that includes them\n" + ) ); let mut names: Vec = fs::read_dir(root.path.join(state)) .unwrap() @@ -551,11 +566,11 @@ fn start_requires_the_guest_features_of_layered_sandboxes() { let output = run(&root, &lifecycle("deprovision", &root, state)); assert!(output.status.success(), "{}", text(&output.stderr)); } - // Per-execution environments are all that the CLI needs: neither cancellation nor workload - // accounts. + // Per-execution environments and host path mapping tables are all that the CLI needs: + // neither cancellation nor workload accounts. let output = run( &root, - &provision(&root, "environments", "fake_guest_features=16"), + &provision(&root, "environments", "fake_guest_features=80"), ); assert!(output.status.success(), "{}", text(&output.stderr)); for operation in ["start", "stop", "deprovision"] { @@ -568,6 +583,73 @@ fn start_requires_the_guest_features_of_layered_sandboxes() { } } +#[test] +fn a_mapping_that_the_guest_refuses_leaves_no_usable_start() { + // The guest agent mounts each share as the mapping table that start sends once it is ready + // orders, and refuses workloads until then: a mapping that it cannot mount ends the start. + // The guest then shuts down as a stop has it do, and OpenVMM reports a stopped VM, unless + // the guest ignores the request, and OpenVMM is terminated without a report. + let root = populated_root(); + let share = root.path.join("share"); + for (state, command_line, stops) in [ + ("refused", "fake_refuse_maps=1", true), + ( + "unstoppable", + "fake_refuse_maps=1 fake_ignore_stop=1", + false, + ), + ] { + let mut arguments = provision(&root, state, command_line); + arguments.extend([ + "--mount".to_owned(), + format!("/data,{}", share.to_str().unwrap()), + ]); + let output = run(&root, &arguments); + assert!(output.status.success(), "{}", text(&output.stderr)); + let mut start = lifecycle("start", &root, state); + start.extend(["--timeout".to_owned(), "2".to_owned()]); + let output = run(&root, &start); + assert_eq!(output.status.code(), Some(1), "{state}"); + assert_eq!( + text(&output.stderr), + "error: managed guest could not mount a mapped host path (error 13)\n" + ); + let mut names: Vec = fs::read_dir(root.path.join(state)) + .unwrap() + .map(|entry| entry.unwrap().file_name().into_string().unwrap()) + .collect(); + names.sort(); + if stops { + assert_eq!( + names, + ["config.json", "openvmm.log", "outcome.json", "sandbox.lock"] + ); + let report: Value = serde_json::from_str( + &fs::read_to_string(root.path.join(state).join("outcome.json")).unwrap(), + ) + .unwrap(); + assert_eq!(report["outcome"]["operation"], "managed"); + assert_eq!(report["outcome"]["category"], "success"); + } else { + assert_eq!(names, ["config.json", "openvmm.log", "sandbox.lock"]); + } + assert!( + !root + .path + .join("build") + .join(format!("fake-openvmm-{state}-maps.json")) + .exists() + ); + let mut exec = lifecycle("exec", &root, state); + exec.extend(["--entrypoint".to_owned(), "/bin/true".to_owned()]); + let output = run(&root, &exec); + assert_eq!(output.status.code(), Some(1)); + assert_eq!(text(&output.stderr), "error: sandbox is not running\n"); + let output = run(&root, &lifecycle("deprovision", &root, state)); + assert!(output.status.success(), "{}", text(&output.stderr)); + } +} + #[test] fn a_sandbox_whose_configuration_names_another_layer_role_does_not_start() { // A sandbox takes only the distro layer, so a configuration whose layers name another role is diff --git a/nvx-rs/tests/fixtures/cli.json b/nvx-rs/tests/fixtures/cli.json index 885c781b1..0a1f5a36a 100644 --- a/nvx-rs/tests/fixtures/cli.json +++ b/nvx-rs/tests/fixtures/cli.json @@ -148,12 +148,12 @@ {"name":"run: missing OpenVMM","steps":[{"argv":["sandbox","run","--layer","distro,{root}/distro.erofs,11111111-1111-1111-1111-111111111111","--scratch","{root}/scratch.ext4"],"remove":["openvmm/target/release/openvmm{exe}"],"status":1,"stdout":"","stderr":"error: OpenVMM release binary not found: {root}/openvmm/target/release/openvmm\n"}]}, {"name":"run: missing kernel","steps":[{"argv":["sandbox","run","--layer","distro,{root}/distro.erofs,11111111-1111-1111-1111-111111111111","--scratch","{root}/scratch.ext4"],"remove":["build/vmlinux"],"status":1,"stdout":"","stderr":"error: Linux direct kernel not found: {root}/build/vmlinux\n"}]}, {"name":"run: missing initramfs","steps":[{"argv":["sandbox","run","--layer","distro,{root}/distro.erofs,11111111-1111-1111-1111-111111111111","--scratch","{root}/scratch.ext4"],"remove":["build/initramfs.cpio.gz"],"status":1,"stdout":"","stderr":"error: initramfs not found: {root}/build/initramfs.cpio.gz\n"}]}, -{"name":"lifecycle: minimal","steps":[{"argv":["sandbox","provision","--state-dir","{root}/state","--layer","distro,{root}/distro.erofs,11111111-1111-1111-1111-111111111111","--scratch","{root}/scratch.ext4"],"check":["state","state/config.json","state/runtime.json","state/control.capability","state/outcome.json","state/openvmm.log"],"status":0,"stdout":"","stderr":"","files":{"state":{"entries":["config.json","sandbox.lock"],"mode":448},"state/config.json":{"text":"{\n \"cmdline\": \"\",\n \"distro_binding\": {\n \"format\": \"erofs\",\n \"identity\": \"11111111-1111-1111-1111-111111111111\",\n \"image\": {\n \"changed\": {\n \"nanoseconds\": {int},\n \"seconds\": {int}\n },\n \"device\": {int},\n \"fileId\": \"{hex32}\",\n \"kind\": \"regular\",\n \"length\": 7,\n \"modified\": {\n \"nanoseconds\": {int},\n \"seconds\": {int}\n },\n \"scheme\": \"linux\",\n \"version\": 1\n },\n \"manifest\": null,\n \"policy\": {\n \"result\": \"accepted\",\n \"revision\": 1\n },\n \"version\": 1\n },\n \"format\": 1,\n \"hostname\": \"nvx-sandbox\",\n \"hypervisor\": \"kvm\",\n \"layers\": [\n {\n \"path\": \"{root}/distro.erofs\",\n \"role\": \"distro\",\n \"uuid\": \"11111111-1111-1111-1111-111111111111\"\n }\n ],\n \"memory_max\": null,\n \"memory_mib\": 256,\n \"mount\": null,\n \"network\": null,\n \"pids_max\": null,\n \"scratch\": \"{root}/scratch.ext4\",\n \"scratch_binding\": {\n \"device\": {int},\n \"fileId\": \"{hex32}\",\n \"kind\": \"regular\",\n \"length\": 8,\n \"scheme\": \"linux\",\n \"version\": 1\n },\n \"workload_gid\": 65534,\n \"workload_uid\": 65534\n}\n","mode":384},"state/runtime.json":null,"state/control.capability":null,"state/outcome.json":null,"state/openvmm.log":null}},{"argv":["sandbox","start","--state-dir","{root}/state"],"check":["state","state/config.json","state/runtime.json","state/control.capability","state/outcome.json","state/openvmm.log","build/fake-openvmm-state.json"],"status":0,"stdout":"","stderr":"","files":{"state":{"entries":["config.json","control.capability","control.sock","openvmm.log","runtime.json","sandbox.lock"],"mode":448},"state/config.json":{"text":"{\n \"cmdline\": \"\",\n \"distro_binding\": {\n \"format\": \"erofs\",\n \"identity\": \"11111111-1111-1111-1111-111111111111\",\n \"image\": {\n \"changed\": {\n \"nanoseconds\": {int},\n \"seconds\": {int}\n },\n \"device\": {int},\n \"fileId\": \"{hex32}\",\n \"kind\": \"regular\",\n \"length\": 7,\n \"modified\": {\n \"nanoseconds\": {int},\n \"seconds\": {int}\n },\n \"scheme\": \"linux\",\n \"version\": 1\n },\n \"manifest\": null,\n \"policy\": {\n \"result\": \"accepted\",\n \"revision\": 1\n },\n \"version\": 1\n },\n \"format\": 1,\n \"hostname\": \"nvx-sandbox\",\n \"hypervisor\": \"kvm\",\n \"layers\": [\n {\n \"path\": \"{root}/distro.erofs\",\n \"role\": \"distro\",\n \"uuid\": \"11111111-1111-1111-1111-111111111111\"\n }\n ],\n \"memory_max\": null,\n \"memory_mib\": 256,\n \"mount\": null,\n \"network\": null,\n \"pids_max\": null,\n \"scratch\": \"{root}/scratch.ext4\",\n \"scratch_binding\": {\n \"device\": {int},\n \"fileId\": \"{hex32}\",\n \"kind\": \"regular\",\n \"length\": 8,\n \"scheme\": \"linux\",\n \"version\": 1\n },\n \"workload_gid\": 65534,\n \"workload_uid\": 65534\n}\n","mode":384},"state/runtime.json":{"text":"{\n \"format\": 4,\n \"launch\": \"{hex32}\",\n \"process\": {\n \"pid\": {int},\n \"startTime\": {int},\n \"boot\": \"{hex32}\"\n },\n \"endpoint\": \"{root}/state/control.sock\",\n \"runtime\": {\n \"openvmm\": \"sha256:1e8c924cdaac227bf74b4a4a9bcdb9e8836a1355fd0408cc81dab5d9aa71eb4d\",\n \"kernel\": \"sha256:a0c936696eb7d5ee3192bf53b9d281cecbb40ca9db520de72cb95817ad92ac72\",\n \"initramfs\": \"sha256:2f77c2c97621e8bf69794e9d12815bb7c46338638f126bea8b18dfe02a684d62\",\n \"bootContract\": 3,\n \"controlContract\": \"nvx-microvm-v2-control-v2\",\n \"controlSession\": 1\n }\n}\n","mode":384},"state/control.capability":{"size":32,"mode":384},"state/outcome.json":null,"state/openvmm.log":{"text":""},"build/fake-openvmm-state.json":{"text":"[\"--machine\",\"microvm\",\"--microvm-sandbox-block\",\"distro:file:/proc/self/fd/{int},ro\",\"--microvm-sandbox-block\",\"scratch:file:/proc/self/fd/{int}\",\"--microvm-workload-identity\",\"65534:65534\",\"--microvm-lifecycle\",\"managed\",\"--single-process\",\"--hypervisor\",\"kvm\",\"--memory\",\"256M\",\"--kernel\",\"{root}/build/vmlinux\",\"--initrd\",\"{root}/build/initramfs.cpio.gz\",\"--cmdline\",\"nvx_sandbox=1 nvx_layer=distro,0xd0003000,erofs:11111111-1111-1111-1111-111111111111 nvx_scratch=0xd0006000,ext4 nvx_entrypoint=/bin/sh nvx_hostname=nvx-sandbox\",\"--virtio-console\",\"none\",\"--microvm-control-console\",\"listen={root}/state/control.sock\",\"--microvm-control-auth-stdin\",\"--microvm-report\",\"{root}/state/outcome.json\"]"}}},{"argv":["sandbox","exec","--state-dir","{root}/state","--entrypoint","/bin/echo","--arg","hello","--arg","world"],"status":0,"stdout":"hello world\n","stderr":""},{"argv":["sandbox","exec","--state-dir","{root}/state","--entrypoint","/bin/pwd","--cwd","/tmp"],"status":0,"stdout":"/tmp\n","stderr":""},{"argv":["sandbox","exec","--state-dir","{root}/state","--entrypoint","/bin/sh","--arg=-c","--arg","echo out; echoerr err; exit 3","--outcome-report","{root}/reports/exec.json"],"check":["reports/exec.json"],"status":3,"stdout":"out\n","stderr":"err\n","files":{"reports/exec.json":{"text":"{\n \"operation_id\": \"{hex32}\",\n \"outcome\": {\n \"category\": \"exit\",\n \"operation\": \"exec\",\n \"status_code\": 3\n },\n \"schema_version\": 1\n}\n","mode":384}}},{"argv":["sandbox","exec","--state-dir","{root}/state","--entrypoint","/usr/bin/env","--environment","A=1","--environment","B=two"],"status":0,"stdout":"A=1\nB=two\n","stderr":""},{"argv":["sandbox","exec","--state-dir","{root}/state","--entrypoint","/usr/bin/printenv","--arg","PATH","--inherit-default-environment","--environment","A=1"],"status":0,"stdout":"/usr/sbin:/usr/bin:/sbin:/bin\n","stderr":""},{"argv":["sandbox","exec","--state-dir","{root}/state","--entrypoint","/usr/bin/env","--environment-file","{root}/env.json"],"write":{"env.json":"[\"X=1\", \"Y=two words\"]"},"status":0,"stdout":"X=1\nY=two words\n","stderr":""},{"argv":["sandbox","exec","--state-dir","{root}/state","--entrypoint","/usr/bin/env","--environment-file","{root}/empty.json"],"write":{"empty.json":"[]"},"status":0,"stdout":"","stderr":""},{"argv":["sandbox","exec","--state-dir","{root}/state","--entrypoint","/bin/sh","--arg=-c","--arg","sleep 5000","--exec-timeout-ms","50","--outcome-report","{root}/reports/exec-timeout.json"],"check":["reports/exec-timeout.json"],"status":124,"stdout":"","stderr":"","files":{"reports/exec-timeout.json":{"text":"{\n \"operation_id\": \"{hex32}\",\n \"outcome\": {\n \"category\": \"timeout\",\n \"operation\": \"exec\",\n \"status_code\": 124\n },\n \"schema_version\": 1\n}\n","mode":384}}},{"argv":["sandbox","exec","--state-dir","{root}/state","--entrypoint","/bin/sh","--arg=-c","--arg","signal 9"],"status":137,"stdout":"","stderr":""},{"argv":["sandbox","exec","--state-dir","{root}/state","--entrypoint","/bin/missing"],"status":127,"stdout":"","stderr":"openvmm: /bin/missing: not found\n"},{"argv":["sandbox","exec","--state-dir","{root}/state","--entrypoint","/bin/pwd","--cwd","/missing"],"status":1,"stdout":"","stderr":"error: managed guest rejected exec (status=2, category=cwd-failed)\n"},{"argv":["sandbox","exec","--state-dir","{root}/state","--entrypoint","/bin/pwd","--cwd","relative"],"status":1,"stdout":"","stderr":"error: managed exec working directory must be an absolute path of at most 4096 bytes\n"},{"argv":["sandbox","exec","--state-dir","{root}/state","--entrypoint","/bin/echo","--outcome-report","{root}/reports/exec.json"],"status":1,"stdout":"","stderr":"error: outcome report already exists: {root}/reports/exec.json\n"},{"argv":["sandbox","exec","--state-dir","{root}/state","--entrypoint","/bin/echo","--outcome-report","{root}/missing/exec.json"],"status":1,"stdout":"","stderr":"error: outcome report parent is not a plain directory: {root}/missing\n"},{"argv":["sandbox","stop","--state-dir","{root}/state"],"check":["state","state/config.json","state/runtime.json","state/control.capability","state/outcome.json","state/openvmm.log"],"status":0,"stdout":"","stderr":"","files":{"state":{"entries":["config.json","openvmm.log","outcome.json","sandbox.lock"],"mode":448},"state/config.json":{"text":"{\n \"cmdline\": \"\",\n \"distro_binding\": {\n \"format\": \"erofs\",\n \"identity\": \"11111111-1111-1111-1111-111111111111\",\n \"image\": {\n \"changed\": {\n \"nanoseconds\": {int},\n \"seconds\": {int}\n },\n \"device\": {int},\n \"fileId\": \"{hex32}\",\n \"kind\": \"regular\",\n \"length\": 7,\n \"modified\": {\n \"nanoseconds\": {int},\n \"seconds\": {int}\n },\n \"scheme\": \"linux\",\n \"version\": 1\n },\n \"manifest\": null,\n \"policy\": {\n \"result\": \"accepted\",\n \"revision\": 1\n },\n \"version\": 1\n },\n \"format\": 1,\n \"hostname\": \"nvx-sandbox\",\n \"hypervisor\": \"kvm\",\n \"layers\": [\n {\n \"path\": \"{root}/distro.erofs\",\n \"role\": \"distro\",\n \"uuid\": \"11111111-1111-1111-1111-111111111111\"\n }\n ],\n \"memory_max\": null,\n \"memory_mib\": 256,\n \"mount\": null,\n \"network\": null,\n \"pids_max\": null,\n \"scratch\": \"{root}/scratch.ext4\",\n \"scratch_binding\": {\n \"device\": {int},\n \"fileId\": \"{hex32}\",\n \"kind\": \"regular\",\n \"length\": 8,\n \"scheme\": \"linux\",\n \"version\": 1\n },\n \"workload_gid\": 65534,\n \"workload_uid\": 65534\n}\n","mode":384},"state/runtime.json":null,"state/control.capability":null,"state/outcome.json":{"text":"{\n \"backend\": \"kvm\",\n \"instance_id\": \"{hex32}\",\n \"network_policy\": {\n \"allow_rule_count\": 0,\n \"deny_rule_count\": 0,\n \"host_loopback\": \"none\",\n \"mode\": \"none\",\n \"status\": \"not-requested\",\n \"status_code\": 0\n },\n \"outcome\": {\n \"category\": \"success\",\n \"operation\": \"managed\",\n \"status_code\": 0\n },\n \"schema_version\": 1,\n \"teardown\": {\n \"control_channels_closed\": true,\n \"guest_workload_stopped\": true,\n \"network_released\": true,\n \"openvmm_process_terminated\": true,\n \"temporary_storage_removed\": true,\n \"virtiofs_released\": true,\n \"vm_stopped\": true\n }\n}\n"},"state/openvmm.log":{"text":""}}},{"argv":["sandbox","start","--state-dir","{root}/state"],"check":["state","state/config.json","state/runtime.json","state/control.capability","state/outcome.json","state/openvmm.log"],"status":0,"stdout":"","stderr":"","files":{"state":{"entries":["config.json","control.capability","control.sock","openvmm.log","runtime.json","sandbox.lock"],"mode":448},"state/config.json":{"text":"{\n \"cmdline\": \"\",\n \"distro_binding\": {\n \"format\": \"erofs\",\n \"identity\": \"11111111-1111-1111-1111-111111111111\",\n \"image\": {\n \"changed\": {\n \"nanoseconds\": {int},\n \"seconds\": {int}\n },\n \"device\": {int},\n \"fileId\": \"{hex32}\",\n \"kind\": \"regular\",\n \"length\": 7,\n \"modified\": {\n \"nanoseconds\": {int},\n \"seconds\": {int}\n },\n \"scheme\": \"linux\",\n \"version\": 1\n },\n \"manifest\": null,\n \"policy\": {\n \"result\": \"accepted\",\n \"revision\": 1\n },\n \"version\": 1\n },\n \"format\": 1,\n \"hostname\": \"nvx-sandbox\",\n \"hypervisor\": \"kvm\",\n \"layers\": [\n {\n \"path\": \"{root}/distro.erofs\",\n \"role\": \"distro\",\n \"uuid\": \"11111111-1111-1111-1111-111111111111\"\n }\n ],\n \"memory_max\": null,\n \"memory_mib\": 256,\n \"mount\": null,\n \"network\": null,\n \"pids_max\": null,\n \"scratch\": \"{root}/scratch.ext4\",\n \"scratch_binding\": {\n \"device\": {int},\n \"fileId\": \"{hex32}\",\n \"kind\": \"regular\",\n \"length\": 8,\n \"scheme\": \"linux\",\n \"version\": 1\n },\n \"workload_gid\": 65534,\n \"workload_uid\": 65534\n}\n","mode":384},"state/runtime.json":{"text":"{\n \"format\": 4,\n \"launch\": \"{hex32}\",\n \"process\": {\n \"pid\": {int},\n \"startTime\": {int},\n \"boot\": \"{hex32}\"\n },\n \"endpoint\": \"{root}/state/control.sock\",\n \"runtime\": {\n \"openvmm\": \"sha256:1e8c924cdaac227bf74b4a4a9bcdb9e8836a1355fd0408cc81dab5d9aa71eb4d\",\n \"kernel\": \"sha256:a0c936696eb7d5ee3192bf53b9d281cecbb40ca9db520de72cb95817ad92ac72\",\n \"initramfs\": \"sha256:2f77c2c97621e8bf69794e9d12815bb7c46338638f126bea8b18dfe02a684d62\",\n \"bootContract\": 3,\n \"controlContract\": \"nvx-microvm-v2-control-v2\",\n \"controlSession\": 1\n }\n}\n","mode":384},"state/control.capability":{"size":32,"mode":384},"state/outcome.json":null,"state/openvmm.log":{"text":""}}},{"argv":["sandbox","stop","--state-dir","{root}/state"],"check":["state","state/config.json","state/runtime.json","state/control.capability","state/outcome.json","state/openvmm.log"],"status":0,"stdout":"","stderr":"","files":{"state":{"entries":["config.json","openvmm.log","outcome.json","sandbox.lock"],"mode":448},"state/config.json":{"text":"{\n \"cmdline\": \"\",\n \"distro_binding\": {\n \"format\": \"erofs\",\n \"identity\": \"11111111-1111-1111-1111-111111111111\",\n \"image\": {\n \"changed\": {\n \"nanoseconds\": {int},\n \"seconds\": {int}\n },\n \"device\": {int},\n \"fileId\": \"{hex32}\",\n \"kind\": \"regular\",\n \"length\": 7,\n \"modified\": {\n \"nanoseconds\": {int},\n \"seconds\": {int}\n },\n \"scheme\": \"linux\",\n \"version\": 1\n },\n \"manifest\": null,\n \"policy\": {\n \"result\": \"accepted\",\n \"revision\": 1\n },\n \"version\": 1\n },\n \"format\": 1,\n \"hostname\": \"nvx-sandbox\",\n \"hypervisor\": \"kvm\",\n \"layers\": [\n {\n \"path\": \"{root}/distro.erofs\",\n \"role\": \"distro\",\n \"uuid\": \"11111111-1111-1111-1111-111111111111\"\n }\n ],\n \"memory_max\": null,\n \"memory_mib\": 256,\n \"mount\": null,\n \"network\": null,\n \"pids_max\": null,\n \"scratch\": \"{root}/scratch.ext4\",\n \"scratch_binding\": {\n \"device\": {int},\n \"fileId\": \"{hex32}\",\n \"kind\": \"regular\",\n \"length\": 8,\n \"scheme\": \"linux\",\n \"version\": 1\n },\n \"workload_gid\": 65534,\n \"workload_uid\": 65534\n}\n","mode":384},"state/runtime.json":null,"state/control.capability":null,"state/outcome.json":{"text":"{\n \"backend\": \"kvm\",\n \"instance_id\": \"{hex32}\",\n \"network_policy\": {\n \"allow_rule_count\": 0,\n \"deny_rule_count\": 0,\n \"host_loopback\": \"none\",\n \"mode\": \"none\",\n \"status\": \"not-requested\",\n \"status_code\": 0\n },\n \"outcome\": {\n \"category\": \"success\",\n \"operation\": \"managed\",\n \"status_code\": 0\n },\n \"schema_version\": 1,\n \"teardown\": {\n \"control_channels_closed\": true,\n \"guest_workload_stopped\": true,\n \"network_released\": true,\n \"openvmm_process_terminated\": true,\n \"temporary_storage_removed\": true,\n \"virtiofs_released\": true,\n \"vm_stopped\": true\n }\n}\n"},"state/openvmm.log":{"text":""}}},{"argv":["sandbox","deprovision","--state-dir","{root}/state"],"check":["state"],"status":0,"stdout":"","stderr":"","files":{"state":null}}],"interop":true}, -{"name":"lifecycle: one share","steps":[{"argv":["sandbox","provision","--state-dir","{root}/state","--layer","distro,{root}/distro.erofs,11111111-1111-1111-1111-111111111111","--scratch","{root}/scratch.ext4","--mount","/data,{root}/share"],"check":["state","state/config.json","state/runtime.json","state/control.capability","state/outcome.json","state/openvmm.log"],"status":0,"stdout":"","stderr":"","files":{"state":{"entries":["config.json","sandbox.lock"],"mode":448},"state/config.json":{"text":"{\n \"cmdline\": \"\",\n \"distro_binding\": {\n \"format\": \"erofs\",\n \"identity\": \"11111111-1111-1111-1111-111111111111\",\n \"image\": {\n \"changed\": {\n \"nanoseconds\": {int},\n \"seconds\": {int}\n },\n \"device\": {int},\n \"fileId\": \"{hex32}\",\n \"kind\": \"regular\",\n \"length\": 7,\n \"modified\": {\n \"nanoseconds\": {int},\n \"seconds\": {int}\n },\n \"scheme\": \"linux\",\n \"version\": 1\n },\n \"manifest\": null,\n \"policy\": {\n \"result\": \"accepted\",\n \"revision\": 1\n },\n \"version\": 1\n },\n \"export\": {\n \"binds\": [\n {\n \"child\": 0,\n \"readOnly\": true,\n \"source\": \"\",\n \"target\": \"/data\"\n }\n ],\n \"children\": [\n {\n \"allowed\": [],\n \"denied\": [],\n \"deniedIdentities\": [],\n \"root\": \"{root}/share\",\n \"writable\": false,\n \"write\": []\n }\n ]\n },\n \"format\": 7,\n \"hostname\": \"nvx-sandbox\",\n \"hypervisor\": \"kvm\",\n \"layers\": [\n {\n \"path\": \"{root}/distro.erofs\",\n \"role\": \"distro\",\n \"uuid\": \"11111111-1111-1111-1111-111111111111\"\n }\n ],\n \"memory_max\": null,\n \"memory_mib\": 256,\n \"network\": null,\n \"pids_max\": null,\n \"scratch\": \"{root}/scratch.ext4\",\n \"scratch_binding\": {\n \"device\": {int},\n \"fileId\": \"{hex32}\",\n \"kind\": \"regular\",\n \"length\": 8,\n \"scheme\": \"linux\",\n \"version\": 1\n },\n \"workload_gid\": 65534,\n \"workload_uid\": 65534\n}\n","mode":384},"state/runtime.json":null,"state/control.capability":null,"state/outcome.json":null,"state/openvmm.log":null}},{"argv":["sandbox","start","--state-dir","{root}/state"],"check":["state","state/config.json","state/runtime.json","state/control.capability","state/outcome.json","state/openvmm.log","build/fake-openvmm-state.json"],"status":0,"stdout":"","stderr":"","files":{"state":{"entries":["config.json","control.capability","control.sock","openvmm.log","runtime.json","sandbox.lock"],"mode":448},"state/config.json":{"text":"{\n \"cmdline\": \"\",\n \"distro_binding\": {\n \"format\": \"erofs\",\n \"identity\": \"11111111-1111-1111-1111-111111111111\",\n \"image\": {\n \"changed\": {\n \"nanoseconds\": {int},\n \"seconds\": {int}\n },\n \"device\": {int},\n \"fileId\": \"{hex32}\",\n \"kind\": \"regular\",\n \"length\": 7,\n \"modified\": {\n \"nanoseconds\": {int},\n \"seconds\": {int}\n },\n \"scheme\": \"linux\",\n \"version\": 1\n },\n \"manifest\": null,\n \"policy\": {\n \"result\": \"accepted\",\n \"revision\": 1\n },\n \"version\": 1\n },\n \"export\": {\n \"binds\": [\n {\n \"child\": 0,\n \"readOnly\": true,\n \"source\": \"\",\n \"target\": \"/data\"\n }\n ],\n \"children\": [\n {\n \"allowed\": [],\n \"denied\": [],\n \"deniedIdentities\": [],\n \"root\": \"{root}/share\",\n \"writable\": false,\n \"write\": []\n }\n ]\n },\n \"format\": 7,\n \"hostname\": \"nvx-sandbox\",\n \"hypervisor\": \"kvm\",\n \"layers\": [\n {\n \"path\": \"{root}/distro.erofs\",\n \"role\": \"distro\",\n \"uuid\": \"11111111-1111-1111-1111-111111111111\"\n }\n ],\n \"memory_max\": null,\n \"memory_mib\": 256,\n \"network\": null,\n \"pids_max\": null,\n \"scratch\": \"{root}/scratch.ext4\",\n \"scratch_binding\": {\n \"device\": {int},\n \"fileId\": \"{hex32}\",\n \"kind\": \"regular\",\n \"length\": 8,\n \"scheme\": \"linux\",\n \"version\": 1\n },\n \"workload_gid\": 65534,\n \"workload_uid\": 65534\n}\n","mode":384},"state/runtime.json":{"text":"{\n \"format\": 4,\n \"launch\": \"{hex32}\",\n \"process\": {\n \"pid\": {int},\n \"startTime\": {int},\n \"boot\": \"{hex32}\"\n },\n \"endpoint\": \"{root}/state/control.sock\",\n \"runtime\": {\n \"openvmm\": \"sha256:1e8c924cdaac227bf74b4a4a9bcdb9e8836a1355fd0408cc81dab5d9aa71eb4d\",\n \"kernel\": \"sha256:a0c936696eb7d5ee3192bf53b9d281cecbb40ca9db520de72cb95817ad92ac72\",\n \"initramfs\": \"sha256:2f77c2c97621e8bf69794e9d12815bb7c46338638f126bea8b18dfe02a684d62\",\n \"bootContract\": 3,\n \"controlContract\": \"nvx-microvm-v2-control-v2\",\n \"controlSession\": 1\n }\n}\n","mode":384},"state/control.capability":{"size":32,"mode":384},"state/outcome.json":null,"state/openvmm.log":{"text":""},"build/fake-openvmm-state.json":{"text":"[\"--machine\",\"microvm\",\"--microvm-sandbox-block\",\"distro:file:/proc/self/fd/{int},ro\",\"--microvm-sandbox-block\",\"scratch:file:/proc/self/fd/{int}\",\"--microvm-workload-identity\",\"65534:65534\",\"--mount\",\"/data,{root}/share,ro\",\"--microvm-lifecycle\",\"managed\",\"--single-process\",\"--hypervisor\",\"kvm\",\"--memory\",\"256M\",\"--kernel\",\"{root}/build/vmlinux\",\"--initrd\",\"{root}/build/initramfs.cpio.gz\",\"--cmdline\",\"nvx_sandbox=1 nvx_layer=distro,0xd0003000,erofs:11111111-1111-1111-1111-111111111111 nvx_scratch=0xd0006000,ext4 nvx_entrypoint=/bin/sh nvx_hostname=nvx-sandbox\",\"--virtio-console\",\"none\",\"--microvm-control-console\",\"listen={root}/state/control.sock\",\"--microvm-control-auth-stdin\",\"--microvm-report\",\"{root}/state/outcome.json\"]"}}},{"argv":["sandbox","exec","--state-dir","{root}/state","--entrypoint","/bin/pwd","--cwd","/data"],"status":0,"stdout":"/data\n","stderr":""},{"argv":["sandbox","stop","--state-dir","{root}/state"],"check":["state","state/config.json","state/runtime.json","state/control.capability","state/outcome.json","state/openvmm.log"],"status":0,"stdout":"","stderr":"","files":{"state":{"entries":["config.json","openvmm.log","outcome.json","sandbox.lock"],"mode":448},"state/config.json":{"text":"{\n \"cmdline\": \"\",\n \"distro_binding\": {\n \"format\": \"erofs\",\n \"identity\": \"11111111-1111-1111-1111-111111111111\",\n \"image\": {\n \"changed\": {\n \"nanoseconds\": {int},\n \"seconds\": {int}\n },\n \"device\": {int},\n \"fileId\": \"{hex32}\",\n \"kind\": \"regular\",\n \"length\": 7,\n \"modified\": {\n \"nanoseconds\": {int},\n \"seconds\": {int}\n },\n \"scheme\": \"linux\",\n \"version\": 1\n },\n \"manifest\": null,\n \"policy\": {\n \"result\": \"accepted\",\n \"revision\": 1\n },\n \"version\": 1\n },\n \"export\": {\n \"binds\": [\n {\n \"child\": 0,\n \"readOnly\": true,\n \"source\": \"\",\n \"target\": \"/data\"\n }\n ],\n \"children\": [\n {\n \"allowed\": [],\n \"denied\": [],\n \"deniedIdentities\": [],\n \"root\": \"{root}/share\",\n \"writable\": false,\n \"write\": []\n }\n ]\n },\n \"format\": 7,\n \"hostname\": \"nvx-sandbox\",\n \"hypervisor\": \"kvm\",\n \"layers\": [\n {\n \"path\": \"{root}/distro.erofs\",\n \"role\": \"distro\",\n \"uuid\": \"11111111-1111-1111-1111-111111111111\"\n }\n ],\n \"memory_max\": null,\n \"memory_mib\": 256,\n \"network\": null,\n \"pids_max\": null,\n \"scratch\": \"{root}/scratch.ext4\",\n \"scratch_binding\": {\n \"device\": {int},\n \"fileId\": \"{hex32}\",\n \"kind\": \"regular\",\n \"length\": 8,\n \"scheme\": \"linux\",\n \"version\": 1\n },\n \"workload_gid\": 65534,\n \"workload_uid\": 65534\n}\n","mode":384},"state/runtime.json":null,"state/control.capability":null,"state/outcome.json":{"text":"{\n \"backend\": \"kvm\",\n \"instance_id\": \"{hex32}\",\n \"network_policy\": {\n \"allow_rule_count\": 0,\n \"deny_rule_count\": 0,\n \"host_loopback\": \"none\",\n \"mode\": \"none\",\n \"status\": \"not-requested\",\n \"status_code\": 0\n },\n \"outcome\": {\n \"category\": \"success\",\n \"operation\": \"managed\",\n \"status_code\": 0\n },\n \"schema_version\": 1,\n \"teardown\": {\n \"control_channels_closed\": true,\n \"guest_workload_stopped\": true,\n \"network_released\": true,\n \"openvmm_process_terminated\": true,\n \"temporary_storage_removed\": true,\n \"virtiofs_released\": true,\n \"vm_stopped\": true\n }\n}\n"},"state/openvmm.log":{"text":""}}},{"argv":["sandbox","start","--state-dir","{root}/state"],"check":["state","state/config.json","state/runtime.json","state/control.capability","state/outcome.json","state/openvmm.log"],"status":0,"stdout":"","stderr":"","files":{"state":{"entries":["config.json","control.capability","control.sock","openvmm.log","runtime.json","sandbox.lock"],"mode":448},"state/config.json":{"text":"{\n \"cmdline\": \"\",\n \"distro_binding\": {\n \"format\": \"erofs\",\n \"identity\": \"11111111-1111-1111-1111-111111111111\",\n \"image\": {\n \"changed\": {\n \"nanoseconds\": {int},\n \"seconds\": {int}\n },\n \"device\": {int},\n \"fileId\": \"{hex32}\",\n \"kind\": \"regular\",\n \"length\": 7,\n \"modified\": {\n \"nanoseconds\": {int},\n \"seconds\": {int}\n },\n \"scheme\": \"linux\",\n \"version\": 1\n },\n \"manifest\": null,\n \"policy\": {\n \"result\": \"accepted\",\n \"revision\": 1\n },\n \"version\": 1\n },\n \"export\": {\n \"binds\": [\n {\n \"child\": 0,\n \"readOnly\": true,\n \"source\": \"\",\n \"target\": \"/data\"\n }\n ],\n \"children\": [\n {\n \"allowed\": [],\n \"denied\": [],\n \"deniedIdentities\": [],\n \"root\": \"{root}/share\",\n \"writable\": false,\n \"write\": []\n }\n ]\n },\n \"format\": 7,\n \"hostname\": \"nvx-sandbox\",\n \"hypervisor\": \"kvm\",\n \"layers\": [\n {\n \"path\": \"{root}/distro.erofs\",\n \"role\": \"distro\",\n \"uuid\": \"11111111-1111-1111-1111-111111111111\"\n }\n ],\n \"memory_max\": null,\n \"memory_mib\": 256,\n \"network\": null,\n \"pids_max\": null,\n \"scratch\": \"{root}/scratch.ext4\",\n \"scratch_binding\": {\n \"device\": {int},\n \"fileId\": \"{hex32}\",\n \"kind\": \"regular\",\n \"length\": 8,\n \"scheme\": \"linux\",\n \"version\": 1\n },\n \"workload_gid\": 65534,\n \"workload_uid\": 65534\n}\n","mode":384},"state/runtime.json":{"text":"{\n \"format\": 4,\n \"launch\": \"{hex32}\",\n \"process\": {\n \"pid\": {int},\n \"startTime\": {int},\n \"boot\": \"{hex32}\"\n },\n \"endpoint\": \"{root}/state/control.sock\",\n \"runtime\": {\n \"openvmm\": \"sha256:1e8c924cdaac227bf74b4a4a9bcdb9e8836a1355fd0408cc81dab5d9aa71eb4d\",\n \"kernel\": \"sha256:a0c936696eb7d5ee3192bf53b9d281cecbb40ca9db520de72cb95817ad92ac72\",\n \"initramfs\": \"sha256:2f77c2c97621e8bf69794e9d12815bb7c46338638f126bea8b18dfe02a684d62\",\n \"bootContract\": 3,\n \"controlContract\": \"nvx-microvm-v2-control-v2\",\n \"controlSession\": 1\n }\n}\n","mode":384},"state/control.capability":{"size":32,"mode":384},"state/outcome.json":null,"state/openvmm.log":{"text":""}}},{"argv":["sandbox","stop","--state-dir","{root}/state"],"check":["state","state/config.json","state/runtime.json","state/control.capability","state/outcome.json","state/openvmm.log"],"status":0,"stdout":"","stderr":"","files":{"state":{"entries":["config.json","openvmm.log","outcome.json","sandbox.lock"],"mode":448},"state/config.json":{"text":"{\n \"cmdline\": \"\",\n \"distro_binding\": {\n \"format\": \"erofs\",\n \"identity\": \"11111111-1111-1111-1111-111111111111\",\n \"image\": {\n \"changed\": {\n \"nanoseconds\": {int},\n \"seconds\": {int}\n },\n \"device\": {int},\n \"fileId\": \"{hex32}\",\n \"kind\": \"regular\",\n \"length\": 7,\n \"modified\": {\n \"nanoseconds\": {int},\n \"seconds\": {int}\n },\n \"scheme\": \"linux\",\n \"version\": 1\n },\n \"manifest\": null,\n \"policy\": {\n \"result\": \"accepted\",\n \"revision\": 1\n },\n \"version\": 1\n },\n \"export\": {\n \"binds\": [\n {\n \"child\": 0,\n \"readOnly\": true,\n \"source\": \"\",\n \"target\": \"/data\"\n }\n ],\n \"children\": [\n {\n \"allowed\": [],\n \"denied\": [],\n \"deniedIdentities\": [],\n \"root\": \"{root}/share\",\n \"writable\": false,\n \"write\": []\n }\n ]\n },\n \"format\": 7,\n \"hostname\": \"nvx-sandbox\",\n \"hypervisor\": \"kvm\",\n \"layers\": [\n {\n \"path\": \"{root}/distro.erofs\",\n \"role\": \"distro\",\n \"uuid\": \"11111111-1111-1111-1111-111111111111\"\n }\n ],\n \"memory_max\": null,\n \"memory_mib\": 256,\n \"network\": null,\n \"pids_max\": null,\n \"scratch\": \"{root}/scratch.ext4\",\n \"scratch_binding\": {\n \"device\": {int},\n \"fileId\": \"{hex32}\",\n \"kind\": \"regular\",\n \"length\": 8,\n \"scheme\": \"linux\",\n \"version\": 1\n },\n \"workload_gid\": 65534,\n \"workload_uid\": 65534\n}\n","mode":384},"state/runtime.json":null,"state/control.capability":null,"state/outcome.json":{"text":"{\n \"backend\": \"kvm\",\n \"instance_id\": \"{hex32}\",\n \"network_policy\": {\n \"allow_rule_count\": 0,\n \"deny_rule_count\": 0,\n \"host_loopback\": \"none\",\n \"mode\": \"none\",\n \"status\": \"not-requested\",\n \"status_code\": 0\n },\n \"outcome\": {\n \"category\": \"success\",\n \"operation\": \"managed\",\n \"status_code\": 0\n },\n \"schema_version\": 1,\n \"teardown\": {\n \"control_channels_closed\": true,\n \"guest_workload_stopped\": true,\n \"network_released\": true,\n \"openvmm_process_terminated\": true,\n \"temporary_storage_removed\": true,\n \"virtiofs_released\": true,\n \"vm_stopped\": true\n }\n}\n"},"state/openvmm.log":{"text":""}}},{"argv":["sandbox","deprovision","--state-dir","{root}/state"],"check":["state"],"status":0,"stdout":"","stderr":"","files":{"state":null}}],"interop":true}, -{"name":"lifecycle: caller-owned share","steps":[{"argv":["sandbox","provision","--state-dir","{root}/state","--layer","distro,{root}/distro.erofs,11111111-1111-1111-1111-111111111111","--scratch","{root}/scratch.ext4","--mount","/data,{root}/share,rw","--mount-owner","caller"],"check":["state","state/config.json","state/runtime.json","state/control.capability","state/outcome.json","state/openvmm.log"],"status":0,"stdout":"","stderr":"","files":{"state":{"entries":["config.json","sandbox.lock"],"mode":448},"state/config.json":{"text":"{\n \"cmdline\": \"\",\n \"distro_binding\": {\n \"format\": \"erofs\",\n \"identity\": \"11111111-1111-1111-1111-111111111111\",\n \"image\": {\n \"changed\": {\n \"nanoseconds\": {int},\n \"seconds\": {int}\n },\n \"device\": {int},\n \"fileId\": \"{hex32}\",\n \"kind\": \"regular\",\n \"length\": 7,\n \"modified\": {\n \"nanoseconds\": {int},\n \"seconds\": {int}\n },\n \"scheme\": \"linux\",\n \"version\": 1\n },\n \"manifest\": null,\n \"policy\": {\n \"result\": \"accepted\",\n \"revision\": 1\n },\n \"version\": 1\n },\n \"export\": {\n \"binds\": [\n {\n \"child\": 0,\n \"readOnly\": false,\n \"source\": \"\",\n \"target\": \"/data\"\n }\n ],\n \"children\": [\n {\n \"allowed\": [],\n \"denied\": [],\n \"deniedIdentities\": [],\n \"root\": \"{root}/share\",\n \"writable\": true,\n \"write\": []\n }\n ],\n \"owner\": \"caller\"\n },\n \"format\": 7,\n \"hostname\": \"nvx-sandbox\",\n \"hypervisor\": \"kvm\",\n \"layers\": [\n {\n \"path\": \"{root}/distro.erofs\",\n \"role\": \"distro\",\n \"uuid\": \"11111111-1111-1111-1111-111111111111\"\n }\n ],\n \"memory_max\": null,\n \"memory_mib\": 256,\n \"network\": null,\n \"pids_max\": null,\n \"scratch\": \"{root}/scratch.ext4\",\n \"scratch_binding\": {\n \"device\": {int},\n \"fileId\": \"{hex32}\",\n \"kind\": \"regular\",\n \"length\": 8,\n \"scheme\": \"linux\",\n \"version\": 1\n },\n \"workload_gid\": 65534,\n \"workload_uid\": 65534\n}\n","mode":384},"state/runtime.json":null,"state/control.capability":null,"state/outcome.json":null,"state/openvmm.log":null}},{"argv":["sandbox","start","--state-dir","{root}/state"],"check":["state","state/config.json","state/runtime.json","state/control.capability","state/outcome.json","state/openvmm.log","build/fake-openvmm-state.json"],"status":0,"stdout":"","stderr":"","files":{"state":{"entries":["config.json","control.capability","control.sock","openvmm.log","runtime.json","sandbox.lock"],"mode":448},"state/config.json":{"text":"{\n \"cmdline\": \"\",\n \"distro_binding\": {\n \"format\": \"erofs\",\n \"identity\": \"11111111-1111-1111-1111-111111111111\",\n \"image\": {\n \"changed\": {\n \"nanoseconds\": {int},\n \"seconds\": {int}\n },\n \"device\": {int},\n \"fileId\": \"{hex32}\",\n \"kind\": \"regular\",\n \"length\": 7,\n \"modified\": {\n \"nanoseconds\": {int},\n \"seconds\": {int}\n },\n \"scheme\": \"linux\",\n \"version\": 1\n },\n \"manifest\": null,\n \"policy\": {\n \"result\": \"accepted\",\n \"revision\": 1\n },\n \"version\": 1\n },\n \"export\": {\n \"binds\": [\n {\n \"child\": 0,\n \"readOnly\": false,\n \"source\": \"\",\n \"target\": \"/data\"\n }\n ],\n \"children\": [\n {\n \"allowed\": [],\n \"denied\": [],\n \"deniedIdentities\": [],\n \"root\": \"{root}/share\",\n \"writable\": true,\n \"write\": []\n }\n ],\n \"owner\": \"caller\"\n },\n \"format\": 7,\n \"hostname\": \"nvx-sandbox\",\n \"hypervisor\": \"kvm\",\n \"layers\": [\n {\n \"path\": \"{root}/distro.erofs\",\n \"role\": \"distro\",\n \"uuid\": \"11111111-1111-1111-1111-111111111111\"\n }\n ],\n \"memory_max\": null,\n \"memory_mib\": 256,\n \"network\": null,\n \"pids_max\": null,\n \"scratch\": \"{root}/scratch.ext4\",\n \"scratch_binding\": {\n \"device\": {int},\n \"fileId\": \"{hex32}\",\n \"kind\": \"regular\",\n \"length\": 8,\n \"scheme\": \"linux\",\n \"version\": 1\n },\n \"workload_gid\": 65534,\n \"workload_uid\": 65534\n}\n","mode":384},"state/runtime.json":{"text":"{\n \"format\": 4,\n \"launch\": \"{hex32}\",\n \"process\": {\n \"pid\": {int},\n \"startTime\": {int},\n \"boot\": \"{hex32}\"\n },\n \"endpoint\": \"{root}/state/control.sock\",\n \"runtime\": {\n \"openvmm\": \"sha256:1e8c924cdaac227bf74b4a4a9bcdb9e8836a1355fd0408cc81dab5d9aa71eb4d\",\n \"kernel\": \"sha256:a0c936696eb7d5ee3192bf53b9d281cecbb40ca9db520de72cb95817ad92ac72\",\n \"initramfs\": \"sha256:2f77c2c97621e8bf69794e9d12815bb7c46338638f126bea8b18dfe02a684d62\",\n \"bootContract\": 3,\n \"controlContract\": \"nvx-microvm-v2-control-v2\",\n \"controlSession\": 1\n }\n}\n","mode":384},"state/control.capability":{"size":32,"mode":384},"state/outcome.json":null,"state/openvmm.log":{"text":""},"build/fake-openvmm-state.json":{"text":"[\"--machine\",\"microvm\",\"--microvm-sandbox-block\",\"distro:file:/proc/self/fd/{int},ro\",\"--microvm-sandbox-block\",\"scratch:file:/proc/self/fd/{int}\",\"--microvm-workload-identity\",\"65534:65534\",\"--mount\",\"/data,{root}/share,rw\",\"--mount-owner\",\"caller\",\"--microvm-lifecycle\",\"managed\",\"--single-process\",\"--hypervisor\",\"kvm\",\"--memory\",\"256M\",\"--kernel\",\"{root}/build/vmlinux\",\"--initrd\",\"{root}/build/initramfs.cpio.gz\",\"--cmdline\",\"nvx_sandbox=1 nvx_layer=distro,0xd0003000,erofs:11111111-1111-1111-1111-111111111111 nvx_scratch=0xd0006000,ext4 nvx_entrypoint=/bin/sh nvx_hostname=nvx-sandbox\",\"--virtio-console\",\"none\",\"--microvm-control-console\",\"listen={root}/state/control.sock\",\"--microvm-control-auth-stdin\",\"--microvm-report\",\"{root}/state/outcome.json\"]"}}},{"argv":["sandbox","stop","--state-dir","{root}/state"],"check":["state","state/config.json","state/runtime.json","state/control.capability","state/outcome.json","state/openvmm.log"],"status":0,"stdout":"","stderr":"","files":{"state":{"entries":["config.json","openvmm.log","outcome.json","sandbox.lock"],"mode":448},"state/config.json":{"text":"{\n \"cmdline\": \"\",\n \"distro_binding\": {\n \"format\": \"erofs\",\n \"identity\": \"11111111-1111-1111-1111-111111111111\",\n \"image\": {\n \"changed\": {\n \"nanoseconds\": {int},\n \"seconds\": {int}\n },\n \"device\": {int},\n \"fileId\": \"{hex32}\",\n \"kind\": \"regular\",\n \"length\": 7,\n \"modified\": {\n \"nanoseconds\": {int},\n \"seconds\": {int}\n },\n \"scheme\": \"linux\",\n \"version\": 1\n },\n \"manifest\": null,\n \"policy\": {\n \"result\": \"accepted\",\n \"revision\": 1\n },\n \"version\": 1\n },\n \"export\": {\n \"binds\": [\n {\n \"child\": 0,\n \"readOnly\": false,\n \"source\": \"\",\n \"target\": \"/data\"\n }\n ],\n \"children\": [\n {\n \"allowed\": [],\n \"denied\": [],\n \"deniedIdentities\": [],\n \"root\": \"{root}/share\",\n \"writable\": true,\n \"write\": []\n }\n ],\n \"owner\": \"caller\"\n },\n \"format\": 7,\n \"hostname\": \"nvx-sandbox\",\n \"hypervisor\": \"kvm\",\n \"layers\": [\n {\n \"path\": \"{root}/distro.erofs\",\n \"role\": \"distro\",\n \"uuid\": \"11111111-1111-1111-1111-111111111111\"\n }\n ],\n \"memory_max\": null,\n \"memory_mib\": 256,\n \"network\": null,\n \"pids_max\": null,\n \"scratch\": \"{root}/scratch.ext4\",\n \"scratch_binding\": {\n \"device\": {int},\n \"fileId\": \"{hex32}\",\n \"kind\": \"regular\",\n \"length\": 8,\n \"scheme\": \"linux\",\n \"version\": 1\n },\n \"workload_gid\": 65534,\n \"workload_uid\": 65534\n}\n","mode":384},"state/runtime.json":null,"state/control.capability":null,"state/outcome.json":{"text":"{\n \"backend\": \"kvm\",\n \"instance_id\": \"{hex32}\",\n \"network_policy\": {\n \"allow_rule_count\": 0,\n \"deny_rule_count\": 0,\n \"host_loopback\": \"none\",\n \"mode\": \"none\",\n \"status\": \"not-requested\",\n \"status_code\": 0\n },\n \"outcome\": {\n \"category\": \"success\",\n \"operation\": \"managed\",\n \"status_code\": 0\n },\n \"schema_version\": 1,\n \"teardown\": {\n \"control_channels_closed\": true,\n \"guest_workload_stopped\": true,\n \"network_released\": true,\n \"openvmm_process_terminated\": true,\n \"temporary_storage_removed\": true,\n \"virtiofs_released\": true,\n \"vm_stopped\": true\n }\n}\n"},"state/openvmm.log":{"text":""}}},{"argv":["sandbox","start","--state-dir","{root}/state"],"check":["state","state/config.json","state/runtime.json","state/control.capability","state/outcome.json","state/openvmm.log"],"status":0,"stdout":"","stderr":"","files":{"state":{"entries":["config.json","control.capability","control.sock","openvmm.log","runtime.json","sandbox.lock"],"mode":448},"state/config.json":{"text":"{\n \"cmdline\": \"\",\n \"distro_binding\": {\n \"format\": \"erofs\",\n \"identity\": \"11111111-1111-1111-1111-111111111111\",\n \"image\": {\n \"changed\": {\n \"nanoseconds\": {int},\n \"seconds\": {int}\n },\n \"device\": {int},\n \"fileId\": \"{hex32}\",\n \"kind\": \"regular\",\n \"length\": 7,\n \"modified\": {\n \"nanoseconds\": {int},\n \"seconds\": {int}\n },\n \"scheme\": \"linux\",\n \"version\": 1\n },\n \"manifest\": null,\n \"policy\": {\n \"result\": \"accepted\",\n \"revision\": 1\n },\n \"version\": 1\n },\n \"export\": {\n \"binds\": [\n {\n \"child\": 0,\n \"readOnly\": false,\n \"source\": \"\",\n \"target\": \"/data\"\n }\n ],\n \"children\": [\n {\n \"allowed\": [],\n \"denied\": [],\n \"deniedIdentities\": [],\n \"root\": \"{root}/share\",\n \"writable\": true,\n \"write\": []\n }\n ],\n \"owner\": \"caller\"\n },\n \"format\": 7,\n \"hostname\": \"nvx-sandbox\",\n \"hypervisor\": \"kvm\",\n \"layers\": [\n {\n \"path\": \"{root}/distro.erofs\",\n \"role\": \"distro\",\n \"uuid\": \"11111111-1111-1111-1111-111111111111\"\n }\n ],\n \"memory_max\": null,\n \"memory_mib\": 256,\n \"network\": null,\n \"pids_max\": null,\n \"scratch\": \"{root}/scratch.ext4\",\n \"scratch_binding\": {\n \"device\": {int},\n \"fileId\": \"{hex32}\",\n \"kind\": \"regular\",\n \"length\": 8,\n \"scheme\": \"linux\",\n \"version\": 1\n },\n \"workload_gid\": 65534,\n \"workload_uid\": 65534\n}\n","mode":384},"state/runtime.json":{"text":"{\n \"format\": 4,\n \"launch\": \"{hex32}\",\n \"process\": {\n \"pid\": {int},\n \"startTime\": {int},\n \"boot\": \"{hex32}\"\n },\n \"endpoint\": \"{root}/state/control.sock\",\n \"runtime\": {\n \"openvmm\": \"sha256:1e8c924cdaac227bf74b4a4a9bcdb9e8836a1355fd0408cc81dab5d9aa71eb4d\",\n \"kernel\": \"sha256:a0c936696eb7d5ee3192bf53b9d281cecbb40ca9db520de72cb95817ad92ac72\",\n \"initramfs\": \"sha256:2f77c2c97621e8bf69794e9d12815bb7c46338638f126bea8b18dfe02a684d62\",\n \"bootContract\": 3,\n \"controlContract\": \"nvx-microvm-v2-control-v2\",\n \"controlSession\": 1\n }\n}\n","mode":384},"state/control.capability":{"size":32,"mode":384},"state/outcome.json":null,"state/openvmm.log":{"text":""}}},{"argv":["sandbox","stop","--state-dir","{root}/state"],"check":["state","state/config.json","state/runtime.json","state/control.capability","state/outcome.json","state/openvmm.log"],"status":0,"stdout":"","stderr":"","files":{"state":{"entries":["config.json","openvmm.log","outcome.json","sandbox.lock"],"mode":448},"state/config.json":{"text":"{\n \"cmdline\": \"\",\n \"distro_binding\": {\n \"format\": \"erofs\",\n \"identity\": \"11111111-1111-1111-1111-111111111111\",\n \"image\": {\n \"changed\": {\n \"nanoseconds\": {int},\n \"seconds\": {int}\n },\n \"device\": {int},\n \"fileId\": \"{hex32}\",\n \"kind\": \"regular\",\n \"length\": 7,\n \"modified\": {\n \"nanoseconds\": {int},\n \"seconds\": {int}\n },\n \"scheme\": \"linux\",\n \"version\": 1\n },\n \"manifest\": null,\n \"policy\": {\n \"result\": \"accepted\",\n \"revision\": 1\n },\n \"version\": 1\n },\n \"export\": {\n \"binds\": [\n {\n \"child\": 0,\n \"readOnly\": false,\n \"source\": \"\",\n \"target\": \"/data\"\n }\n ],\n \"children\": [\n {\n \"allowed\": [],\n \"denied\": [],\n \"deniedIdentities\": [],\n \"root\": \"{root}/share\",\n \"writable\": true,\n \"write\": []\n }\n ],\n \"owner\": \"caller\"\n },\n \"format\": 7,\n \"hostname\": \"nvx-sandbox\",\n \"hypervisor\": \"kvm\",\n \"layers\": [\n {\n \"path\": \"{root}/distro.erofs\",\n \"role\": \"distro\",\n \"uuid\": \"11111111-1111-1111-1111-111111111111\"\n }\n ],\n \"memory_max\": null,\n \"memory_mib\": 256,\n \"network\": null,\n \"pids_max\": null,\n \"scratch\": \"{root}/scratch.ext4\",\n \"scratch_binding\": {\n \"device\": {int},\n \"fileId\": \"{hex32}\",\n \"kind\": \"regular\",\n \"length\": 8,\n \"scheme\": \"linux\",\n \"version\": 1\n },\n \"workload_gid\": 65534,\n \"workload_uid\": 65534\n}\n","mode":384},"state/runtime.json":null,"state/control.capability":null,"state/outcome.json":{"text":"{\n \"backend\": \"kvm\",\n \"instance_id\": \"{hex32}\",\n \"network_policy\": {\n \"allow_rule_count\": 0,\n \"deny_rule_count\": 0,\n \"host_loopback\": \"none\",\n \"mode\": \"none\",\n \"status\": \"not-requested\",\n \"status_code\": 0\n },\n \"outcome\": {\n \"category\": \"success\",\n \"operation\": \"managed\",\n \"status_code\": 0\n },\n \"schema_version\": 1,\n \"teardown\": {\n \"control_channels_closed\": true,\n \"guest_workload_stopped\": true,\n \"network_released\": true,\n \"openvmm_process_terminated\": true,\n \"temporary_storage_removed\": true,\n \"virtiofs_released\": true,\n \"vm_stopped\": true\n }\n}\n"},"state/openvmm.log":{"text":""}}},{"argv":["sandbox","deprovision","--state-dir","{root}/state"],"check":["state"],"status":0,"stdout":"","stderr":"","files":{"state":null}}],"interop":true}, -{"name":"lifecycle: several shares","steps":[{"argv":["sandbox","provision","--state-dir","{root}/state","--layer","distro,{root}/distro.erofs,11111111-1111-1111-1111-111111111111","--scratch","{root}/scratch.ext4","--mount","/data,{root}/share","--mount","/other,{root}/share2,rw"],"check":["state","state/config.json","state/runtime.json","state/control.capability","state/outcome.json","state/openvmm.log"],"status":0,"stdout":"","stderr":"","files":{"state":{"entries":["config.json","sandbox.lock"],"mode":448},"state/config.json":{"text":"{\n \"cmdline\": \"\",\n \"distro_binding\": {\n \"format\": \"erofs\",\n \"identity\": \"11111111-1111-1111-1111-111111111111\",\n \"image\": {\n \"changed\": {\n \"nanoseconds\": {int},\n \"seconds\": {int}\n },\n \"device\": {int},\n \"fileId\": \"{hex32}\",\n \"kind\": \"regular\",\n \"length\": 7,\n \"modified\": {\n \"nanoseconds\": {int},\n \"seconds\": {int}\n },\n \"scheme\": \"linux\",\n \"version\": 1\n },\n \"manifest\": null,\n \"policy\": {\n \"result\": \"accepted\",\n \"revision\": 1\n },\n \"version\": 1\n },\n \"export\": {\n \"binds\": [\n {\n \"child\": 0,\n \"readOnly\": true,\n \"source\": \"\",\n \"target\": \"/data\"\n },\n {\n \"child\": 1,\n \"readOnly\": false,\n \"source\": \"\",\n \"target\": \"/other\"\n }\n ],\n \"children\": [\n {\n \"allowed\": [],\n \"denied\": [],\n \"deniedIdentities\": [],\n \"root\": \"{root}/share\",\n \"writable\": false,\n \"write\": []\n },\n {\n \"allowed\": [],\n \"denied\": [],\n \"deniedIdentities\": [],\n \"root\": \"{root}/share2\",\n \"writable\": true,\n \"write\": []\n }\n ]\n },\n \"format\": 7,\n \"hostname\": \"nvx-sandbox\",\n \"hypervisor\": \"kvm\",\n \"layers\": [\n {\n \"path\": \"{root}/distro.erofs\",\n \"role\": \"distro\",\n \"uuid\": \"11111111-1111-1111-1111-111111111111\"\n }\n ],\n \"memory_max\": null,\n \"memory_mib\": 256,\n \"network\": null,\n \"pids_max\": null,\n \"scratch\": \"{root}/scratch.ext4\",\n \"scratch_binding\": {\n \"device\": {int},\n \"fileId\": \"{hex32}\",\n \"kind\": \"regular\",\n \"length\": 8,\n \"scheme\": \"linux\",\n \"version\": 1\n },\n \"workload_gid\": 65534,\n \"workload_uid\": 65534\n}\n","mode":384},"state/runtime.json":null,"state/control.capability":null,"state/outcome.json":null,"state/openvmm.log":null}},{"argv":["sandbox","start","--state-dir","{root}/state"],"check":["state","state/config.json","state/runtime.json","state/control.capability","state/outcome.json","state/openvmm.log","build/fake-openvmm-state.json"],"status":0,"stdout":"","stderr":"","files":{"state":{"entries":["config.json","control.capability","control.sock","openvmm.log","runtime.json","sandbox.lock"],"mode":448},"state/config.json":{"text":"{\n \"cmdline\": \"\",\n \"distro_binding\": {\n \"format\": \"erofs\",\n \"identity\": \"11111111-1111-1111-1111-111111111111\",\n \"image\": {\n \"changed\": {\n \"nanoseconds\": {int},\n \"seconds\": {int}\n },\n \"device\": {int},\n \"fileId\": \"{hex32}\",\n \"kind\": \"regular\",\n \"length\": 7,\n \"modified\": {\n \"nanoseconds\": {int},\n \"seconds\": {int}\n },\n \"scheme\": \"linux\",\n \"version\": 1\n },\n \"manifest\": null,\n \"policy\": {\n \"result\": \"accepted\",\n \"revision\": 1\n },\n \"version\": 1\n },\n \"export\": {\n \"binds\": [\n {\n \"child\": 0,\n \"readOnly\": true,\n \"source\": \"\",\n \"target\": \"/data\"\n },\n {\n \"child\": 1,\n \"readOnly\": false,\n \"source\": \"\",\n \"target\": \"/other\"\n }\n ],\n \"children\": [\n {\n \"allowed\": [],\n \"denied\": [],\n \"deniedIdentities\": [],\n \"root\": \"{root}/share\",\n \"writable\": false,\n \"write\": []\n },\n {\n \"allowed\": [],\n \"denied\": [],\n \"deniedIdentities\": [],\n \"root\": \"{root}/share2\",\n \"writable\": true,\n \"write\": []\n }\n ]\n },\n \"format\": 7,\n \"hostname\": \"nvx-sandbox\",\n \"hypervisor\": \"kvm\",\n \"layers\": [\n {\n \"path\": \"{root}/distro.erofs\",\n \"role\": \"distro\",\n \"uuid\": \"11111111-1111-1111-1111-111111111111\"\n }\n ],\n \"memory_max\": null,\n \"memory_mib\": 256,\n \"network\": null,\n \"pids_max\": null,\n \"scratch\": \"{root}/scratch.ext4\",\n \"scratch_binding\": {\n \"device\": {int},\n \"fileId\": \"{hex32}\",\n \"kind\": \"regular\",\n \"length\": 8,\n \"scheme\": \"linux\",\n \"version\": 1\n },\n \"workload_gid\": 65534,\n \"workload_uid\": 65534\n}\n","mode":384},"state/runtime.json":{"text":"{\n \"format\": 4,\n \"launch\": \"{hex32}\",\n \"process\": {\n \"pid\": {int},\n \"startTime\": {int},\n \"boot\": \"{hex32}\"\n },\n \"endpoint\": \"{root}/state/control.sock\",\n \"runtime\": {\n \"openvmm\": \"sha256:1e8c924cdaac227bf74b4a4a9bcdb9e8836a1355fd0408cc81dab5d9aa71eb4d\",\n \"kernel\": \"sha256:a0c936696eb7d5ee3192bf53b9d281cecbb40ca9db520de72cb95817ad92ac72\",\n \"initramfs\": \"sha256:2f77c2c97621e8bf69794e9d12815bb7c46338638f126bea8b18dfe02a684d62\",\n \"bootContract\": 3,\n \"controlContract\": \"nvx-microvm-v2-control-v2\",\n \"controlSession\": 1\n }\n}\n","mode":384},"state/control.capability":{"size":32,"mode":384},"state/outcome.json":null,"state/openvmm.log":{"text":""},"build/fake-openvmm-state.json":{"text":"[\"--machine\",\"microvm\",\"--microvm-sandbox-block\",\"distro:file:/proc/self/fd/{int},ro\",\"--microvm-sandbox-block\",\"scratch:file:/proc/self/fd/{int}\",\"--microvm-workload-identity\",\"65534:65534\",\"--mount-aggregate\",\"/run/nvx/shares\",\"--mount-child\",\"0-bd47413b5c03dfc6e4b5b8143fe205ea,{root}/share,ro\",\"--mount-child\",\"1-bf2faee2596026620b5cbc997c2d7d45,{root}/share2,rw\",\"--microvm-lifecycle\",\"managed\",\"--single-process\",\"--hypervisor\",\"kvm\",\"--memory\",\"256M\",\"--kernel\",\"{root}/build/vmlinux\",\"--initrd\",\"{root}/build/initramfs.cpio.gz\",\"--cmdline\",\"nvx_sandbox=1 nvx_layer=distro,0xd0003000,erofs:11111111-1111-1111-1111-111111111111 nvx_scratch=0xd0006000,ext4 nvx_entrypoint=/bin/sh nvx_hostname=nvx-sandbox nvx_share=0-bd47413b5c03dfc6e4b5b8143fe205ea,/data,ro nvx_share=1-bf2faee2596026620b5cbc997c2d7d45,/other,rw\",\"--virtio-console\",\"none\",\"--microvm-control-console\",\"listen={root}/state/control.sock\",\"--microvm-control-auth-stdin\",\"--microvm-report\",\"{root}/state/outcome.json\"]"}}},{"argv":["sandbox","exec","--state-dir","{root}/state","--entrypoint","/bin/pwd","--cwd","/other"],"status":0,"stdout":"/other\n","stderr":""},{"argv":["sandbox","stop","--state-dir","{root}/state"],"check":["state","state/config.json","state/runtime.json","state/control.capability","state/outcome.json","state/openvmm.log"],"status":0,"stdout":"","stderr":"","files":{"state":{"entries":["config.json","openvmm.log","outcome.json","sandbox.lock"],"mode":448},"state/config.json":{"text":"{\n \"cmdline\": \"\",\n \"distro_binding\": {\n \"format\": \"erofs\",\n \"identity\": \"11111111-1111-1111-1111-111111111111\",\n \"image\": {\n \"changed\": {\n \"nanoseconds\": {int},\n \"seconds\": {int}\n },\n \"device\": {int},\n \"fileId\": \"{hex32}\",\n \"kind\": \"regular\",\n \"length\": 7,\n \"modified\": {\n \"nanoseconds\": {int},\n \"seconds\": {int}\n },\n \"scheme\": \"linux\",\n \"version\": 1\n },\n \"manifest\": null,\n \"policy\": {\n \"result\": \"accepted\",\n \"revision\": 1\n },\n \"version\": 1\n },\n \"export\": {\n \"binds\": [\n {\n \"child\": 0,\n \"readOnly\": true,\n \"source\": \"\",\n \"target\": \"/data\"\n },\n {\n \"child\": 1,\n \"readOnly\": false,\n \"source\": \"\",\n \"target\": \"/other\"\n }\n ],\n \"children\": [\n {\n \"allowed\": [],\n \"denied\": [],\n \"deniedIdentities\": [],\n \"root\": \"{root}/share\",\n \"writable\": false,\n \"write\": []\n },\n {\n \"allowed\": [],\n \"denied\": [],\n \"deniedIdentities\": [],\n \"root\": \"{root}/share2\",\n \"writable\": true,\n \"write\": []\n }\n ]\n },\n \"format\": 7,\n \"hostname\": \"nvx-sandbox\",\n \"hypervisor\": \"kvm\",\n \"layers\": [\n {\n \"path\": \"{root}/distro.erofs\",\n \"role\": \"distro\",\n \"uuid\": \"11111111-1111-1111-1111-111111111111\"\n }\n ],\n \"memory_max\": null,\n \"memory_mib\": 256,\n \"network\": null,\n \"pids_max\": null,\n \"scratch\": \"{root}/scratch.ext4\",\n \"scratch_binding\": {\n \"device\": {int},\n \"fileId\": \"{hex32}\",\n \"kind\": \"regular\",\n \"length\": 8,\n \"scheme\": \"linux\",\n \"version\": 1\n },\n \"workload_gid\": 65534,\n \"workload_uid\": 65534\n}\n","mode":384},"state/runtime.json":null,"state/control.capability":null,"state/outcome.json":{"text":"{\n \"backend\": \"kvm\",\n \"instance_id\": \"{hex32}\",\n \"network_policy\": {\n \"allow_rule_count\": 0,\n \"deny_rule_count\": 0,\n \"host_loopback\": \"none\",\n \"mode\": \"none\",\n \"status\": \"not-requested\",\n \"status_code\": 0\n },\n \"outcome\": {\n \"category\": \"success\",\n \"operation\": \"managed\",\n \"status_code\": 0\n },\n \"schema_version\": 1,\n \"teardown\": {\n \"control_channels_closed\": true,\n \"guest_workload_stopped\": true,\n \"network_released\": true,\n \"openvmm_process_terminated\": true,\n \"temporary_storage_removed\": true,\n \"virtiofs_released\": true,\n \"vm_stopped\": true\n }\n}\n"},"state/openvmm.log":{"text":""}}},{"argv":["sandbox","start","--state-dir","{root}/state"],"check":["state","state/config.json","state/runtime.json","state/control.capability","state/outcome.json","state/openvmm.log"],"status":0,"stdout":"","stderr":"","files":{"state":{"entries":["config.json","control.capability","control.sock","openvmm.log","runtime.json","sandbox.lock"],"mode":448},"state/config.json":{"text":"{\n \"cmdline\": \"\",\n \"distro_binding\": {\n \"format\": \"erofs\",\n \"identity\": \"11111111-1111-1111-1111-111111111111\",\n \"image\": {\n \"changed\": {\n \"nanoseconds\": {int},\n \"seconds\": {int}\n },\n \"device\": {int},\n \"fileId\": \"{hex32}\",\n \"kind\": \"regular\",\n \"length\": 7,\n \"modified\": {\n \"nanoseconds\": {int},\n \"seconds\": {int}\n },\n \"scheme\": \"linux\",\n \"version\": 1\n },\n \"manifest\": null,\n \"policy\": {\n \"result\": \"accepted\",\n \"revision\": 1\n },\n \"version\": 1\n },\n \"export\": {\n \"binds\": [\n {\n \"child\": 0,\n \"readOnly\": true,\n \"source\": \"\",\n \"target\": \"/data\"\n },\n {\n \"child\": 1,\n \"readOnly\": false,\n \"source\": \"\",\n \"target\": \"/other\"\n }\n ],\n \"children\": [\n {\n \"allowed\": [],\n \"denied\": [],\n \"deniedIdentities\": [],\n \"root\": \"{root}/share\",\n \"writable\": false,\n \"write\": []\n },\n {\n \"allowed\": [],\n \"denied\": [],\n \"deniedIdentities\": [],\n \"root\": \"{root}/share2\",\n \"writable\": true,\n \"write\": []\n }\n ]\n },\n \"format\": 7,\n \"hostname\": \"nvx-sandbox\",\n \"hypervisor\": \"kvm\",\n \"layers\": [\n {\n \"path\": \"{root}/distro.erofs\",\n \"role\": \"distro\",\n \"uuid\": \"11111111-1111-1111-1111-111111111111\"\n }\n ],\n \"memory_max\": null,\n \"memory_mib\": 256,\n \"network\": null,\n \"pids_max\": null,\n \"scratch\": \"{root}/scratch.ext4\",\n \"scratch_binding\": {\n \"device\": {int},\n \"fileId\": \"{hex32}\",\n \"kind\": \"regular\",\n \"length\": 8,\n \"scheme\": \"linux\",\n \"version\": 1\n },\n \"workload_gid\": 65534,\n \"workload_uid\": 65534\n}\n","mode":384},"state/runtime.json":{"text":"{\n \"format\": 4,\n \"launch\": \"{hex32}\",\n \"process\": {\n \"pid\": {int},\n \"startTime\": {int},\n \"boot\": \"{hex32}\"\n },\n \"endpoint\": \"{root}/state/control.sock\",\n \"runtime\": {\n \"openvmm\": \"sha256:1e8c924cdaac227bf74b4a4a9bcdb9e8836a1355fd0408cc81dab5d9aa71eb4d\",\n \"kernel\": \"sha256:a0c936696eb7d5ee3192bf53b9d281cecbb40ca9db520de72cb95817ad92ac72\",\n \"initramfs\": \"sha256:2f77c2c97621e8bf69794e9d12815bb7c46338638f126bea8b18dfe02a684d62\",\n \"bootContract\": 3,\n \"controlContract\": \"nvx-microvm-v2-control-v2\",\n \"controlSession\": 1\n }\n}\n","mode":384},"state/control.capability":{"size":32,"mode":384},"state/outcome.json":null,"state/openvmm.log":{"text":""}}},{"argv":["sandbox","stop","--state-dir","{root}/state"],"check":["state","state/config.json","state/runtime.json","state/control.capability","state/outcome.json","state/openvmm.log"],"status":0,"stdout":"","stderr":"","files":{"state":{"entries":["config.json","openvmm.log","outcome.json","sandbox.lock"],"mode":448},"state/config.json":{"text":"{\n \"cmdline\": \"\",\n \"distro_binding\": {\n \"format\": \"erofs\",\n \"identity\": \"11111111-1111-1111-1111-111111111111\",\n \"image\": {\n \"changed\": {\n \"nanoseconds\": {int},\n \"seconds\": {int}\n },\n \"device\": {int},\n \"fileId\": \"{hex32}\",\n \"kind\": \"regular\",\n \"length\": 7,\n \"modified\": {\n \"nanoseconds\": {int},\n \"seconds\": {int}\n },\n \"scheme\": \"linux\",\n \"version\": 1\n },\n \"manifest\": null,\n \"policy\": {\n \"result\": \"accepted\",\n \"revision\": 1\n },\n \"version\": 1\n },\n \"export\": {\n \"binds\": [\n {\n \"child\": 0,\n \"readOnly\": true,\n \"source\": \"\",\n \"target\": \"/data\"\n },\n {\n \"child\": 1,\n \"readOnly\": false,\n \"source\": \"\",\n \"target\": \"/other\"\n }\n ],\n \"children\": [\n {\n \"allowed\": [],\n \"denied\": [],\n \"deniedIdentities\": [],\n \"root\": \"{root}/share\",\n \"writable\": false,\n \"write\": []\n },\n {\n \"allowed\": [],\n \"denied\": [],\n \"deniedIdentities\": [],\n \"root\": \"{root}/share2\",\n \"writable\": true,\n \"write\": []\n }\n ]\n },\n \"format\": 7,\n \"hostname\": \"nvx-sandbox\",\n \"hypervisor\": \"kvm\",\n \"layers\": [\n {\n \"path\": \"{root}/distro.erofs\",\n \"role\": \"distro\",\n \"uuid\": \"11111111-1111-1111-1111-111111111111\"\n }\n ],\n \"memory_max\": null,\n \"memory_mib\": 256,\n \"network\": null,\n \"pids_max\": null,\n \"scratch\": \"{root}/scratch.ext4\",\n \"scratch_binding\": {\n \"device\": {int},\n \"fileId\": \"{hex32}\",\n \"kind\": \"regular\",\n \"length\": 8,\n \"scheme\": \"linux\",\n \"version\": 1\n },\n \"workload_gid\": 65534,\n \"workload_uid\": 65534\n}\n","mode":384},"state/runtime.json":null,"state/control.capability":null,"state/outcome.json":{"text":"{\n \"backend\": \"kvm\",\n \"instance_id\": \"{hex32}\",\n \"network_policy\": {\n \"allow_rule_count\": 0,\n \"deny_rule_count\": 0,\n \"host_loopback\": \"none\",\n \"mode\": \"none\",\n \"status\": \"not-requested\",\n \"status_code\": 0\n },\n \"outcome\": {\n \"category\": \"success\",\n \"operation\": \"managed\",\n \"status_code\": 0\n },\n \"schema_version\": 1,\n \"teardown\": {\n \"control_channels_closed\": true,\n \"guest_workload_stopped\": true,\n \"network_released\": true,\n \"openvmm_process_terminated\": true,\n \"temporary_storage_removed\": true,\n \"virtiofs_released\": true,\n \"vm_stopped\": true\n }\n}\n"},"state/openvmm.log":{"text":""}}},{"argv":["sandbox","deprovision","--state-dir","{root}/state"],"check":["state"],"status":0,"stdout":"","stderr":"","files":{"state":null}}],"interop":true}, -{"name":"lifecycle: share policies","steps":[{"argv":["sandbox","provision","--state-dir","{root}/state","--layer","distro,{root}/distro.erofs,11111111-1111-1111-1111-111111111111","--scratch","{root}/scratch.ext4","--mount","/data,{root}/share,rw","--mount-deny","{root}/share/hidden","--mount-allow","{root}/share/hidden/shown","--mount-write","{root}/share/writable"],"check":["state","state/config.json","state/runtime.json","state/control.capability","state/outcome.json","state/openvmm.log"],"status":0,"stdout":"","stderr":"","files":{"state":{"entries":["config.json","sandbox.lock"],"mode":448},"state/config.json":{"text":"{\n \"cmdline\": \"\",\n \"distro_binding\": {\n \"format\": \"erofs\",\n \"identity\": \"11111111-1111-1111-1111-111111111111\",\n \"image\": {\n \"changed\": {\n \"nanoseconds\": {int},\n \"seconds\": {int}\n },\n \"device\": {int},\n \"fileId\": \"{hex32}\",\n \"kind\": \"regular\",\n \"length\": 7,\n \"modified\": {\n \"nanoseconds\": {int},\n \"seconds\": {int}\n },\n \"scheme\": \"linux\",\n \"version\": 1\n },\n \"manifest\": null,\n \"policy\": {\n \"result\": \"accepted\",\n \"revision\": 1\n },\n \"version\": 1\n },\n \"export\": {\n \"binds\": [\n {\n \"child\": 0,\n \"readOnly\": false,\n \"source\": \"\",\n \"target\": \"/data\"\n }\n ],\n \"children\": [\n {\n \"allowed\": [\n \"{root}/share/hidden/shown\"\n ],\n \"denied\": [\n \"{root}/share/hidden\"\n ],\n \"deniedIdentities\": [\n null\n ],\n \"root\": \"{root}/share\",\n \"writable\": true,\n \"write\": [\n \"{root}/share/writable\"\n ]\n }\n ]\n },\n \"format\": 7,\n \"hostname\": \"nvx-sandbox\",\n \"hypervisor\": \"kvm\",\n \"layers\": [\n {\n \"path\": \"{root}/distro.erofs\",\n \"role\": \"distro\",\n \"uuid\": \"11111111-1111-1111-1111-111111111111\"\n }\n ],\n \"memory_max\": null,\n \"memory_mib\": 256,\n \"network\": null,\n \"pids_max\": null,\n \"scratch\": \"{root}/scratch.ext4\",\n \"scratch_binding\": {\n \"device\": {int},\n \"fileId\": \"{hex32}\",\n \"kind\": \"regular\",\n \"length\": 8,\n \"scheme\": \"linux\",\n \"version\": 1\n },\n \"workload_gid\": 65534,\n \"workload_uid\": 65534\n}\n","mode":384},"state/runtime.json":null,"state/control.capability":null,"state/outcome.json":null,"state/openvmm.log":null}},{"argv":["sandbox","start","--state-dir","{root}/state"],"check":["state","state/config.json","state/runtime.json","state/control.capability","state/outcome.json","state/openvmm.log","build/fake-openvmm-state.json"],"status":0,"stdout":"","stderr":"","files":{"state":{"entries":["config.json","control.capability","control.sock","openvmm.log","runtime.json","sandbox.lock"],"mode":448},"state/config.json":{"text":"{\n \"cmdline\": \"\",\n \"distro_binding\": {\n \"format\": \"erofs\",\n \"identity\": \"11111111-1111-1111-1111-111111111111\",\n \"image\": {\n \"changed\": {\n \"nanoseconds\": {int},\n \"seconds\": {int}\n },\n \"device\": {int},\n \"fileId\": \"{hex32}\",\n \"kind\": \"regular\",\n \"length\": 7,\n \"modified\": {\n \"nanoseconds\": {int},\n \"seconds\": {int}\n },\n \"scheme\": \"linux\",\n \"version\": 1\n },\n \"manifest\": null,\n \"policy\": {\n \"result\": \"accepted\",\n \"revision\": 1\n },\n \"version\": 1\n },\n \"export\": {\n \"binds\": [\n {\n \"child\": 0,\n \"readOnly\": false,\n \"source\": \"\",\n \"target\": \"/data\"\n }\n ],\n \"children\": [\n {\n \"allowed\": [\n \"{root}/share/hidden/shown\"\n ],\n \"denied\": [\n \"{root}/share/hidden\"\n ],\n \"deniedIdentities\": [\n null\n ],\n \"root\": \"{root}/share\",\n \"writable\": true,\n \"write\": [\n \"{root}/share/writable\"\n ]\n }\n ]\n },\n \"format\": 7,\n \"hostname\": \"nvx-sandbox\",\n \"hypervisor\": \"kvm\",\n \"layers\": [\n {\n \"path\": \"{root}/distro.erofs\",\n \"role\": \"distro\",\n \"uuid\": \"11111111-1111-1111-1111-111111111111\"\n }\n ],\n \"memory_max\": null,\n \"memory_mib\": 256,\n \"network\": null,\n \"pids_max\": null,\n \"scratch\": \"{root}/scratch.ext4\",\n \"scratch_binding\": {\n \"device\": {int},\n \"fileId\": \"{hex32}\",\n \"kind\": \"regular\",\n \"length\": 8,\n \"scheme\": \"linux\",\n \"version\": 1\n },\n \"workload_gid\": 65534,\n \"workload_uid\": 65534\n}\n","mode":384},"state/runtime.json":{"text":"{\n \"format\": 4,\n \"launch\": \"{hex32}\",\n \"process\": {\n \"pid\": {int},\n \"startTime\": {int},\n \"boot\": \"{hex32}\"\n },\n \"endpoint\": \"{root}/state/control.sock\",\n \"runtime\": {\n \"openvmm\": \"sha256:1e8c924cdaac227bf74b4a4a9bcdb9e8836a1355fd0408cc81dab5d9aa71eb4d\",\n \"kernel\": \"sha256:a0c936696eb7d5ee3192bf53b9d281cecbb40ca9db520de72cb95817ad92ac72\",\n \"initramfs\": \"sha256:2f77c2c97621e8bf69794e9d12815bb7c46338638f126bea8b18dfe02a684d62\",\n \"bootContract\": 3,\n \"controlContract\": \"nvx-microvm-v2-control-v2\",\n \"controlSession\": 1\n }\n}\n","mode":384},"state/control.capability":{"size":32,"mode":384},"state/outcome.json":null,"state/openvmm.log":{"text":""},"build/fake-openvmm-state.json":{"text":"[\"--machine\",\"microvm\",\"--microvm-sandbox-block\",\"distro:file:/proc/self/fd/{int},ro\",\"--microvm-sandbox-block\",\"scratch:file:/proc/self/fd/{int}\",\"--microvm-workload-identity\",\"65534:65534\",\"--mount\",\"/data,{root}/share,rw\",\"--mount-deny\",\"{root}/share/hidden\",\"--mount-allow\",\"{root}/share/hidden/shown\",\"--mount-write\",\"{root}/share/writable\",\"--microvm-lifecycle\",\"managed\",\"--single-process\",\"--hypervisor\",\"kvm\",\"--memory\",\"256M\",\"--kernel\",\"{root}/build/vmlinux\",\"--initrd\",\"{root}/build/initramfs.cpio.gz\",\"--cmdline\",\"nvx_sandbox=1 nvx_layer=distro,0xd0003000,erofs:11111111-1111-1111-1111-111111111111 nvx_scratch=0xd0006000,ext4 nvx_entrypoint=/bin/sh nvx_hostname=nvx-sandbox\",\"--virtio-console\",\"none\",\"--microvm-control-console\",\"listen={root}/state/control.sock\",\"--microvm-control-auth-stdin\",\"--microvm-report\",\"{root}/state/outcome.json\"]"}}},{"argv":["sandbox","stop","--state-dir","{root}/state"],"check":["state","state/config.json","state/runtime.json","state/control.capability","state/outcome.json","state/openvmm.log"],"status":0,"stdout":"","stderr":"","files":{"state":{"entries":["config.json","openvmm.log","outcome.json","sandbox.lock"],"mode":448},"state/config.json":{"text":"{\n \"cmdline\": \"\",\n \"distro_binding\": {\n \"format\": \"erofs\",\n \"identity\": \"11111111-1111-1111-1111-111111111111\",\n \"image\": {\n \"changed\": {\n \"nanoseconds\": {int},\n \"seconds\": {int}\n },\n \"device\": {int},\n \"fileId\": \"{hex32}\",\n \"kind\": \"regular\",\n \"length\": 7,\n \"modified\": {\n \"nanoseconds\": {int},\n \"seconds\": {int}\n },\n \"scheme\": \"linux\",\n \"version\": 1\n },\n \"manifest\": null,\n \"policy\": {\n \"result\": \"accepted\",\n \"revision\": 1\n },\n \"version\": 1\n },\n \"export\": {\n \"binds\": [\n {\n \"child\": 0,\n \"readOnly\": false,\n \"source\": \"\",\n \"target\": \"/data\"\n }\n ],\n \"children\": [\n {\n \"allowed\": [\n \"{root}/share/hidden/shown\"\n ],\n \"denied\": [\n \"{root}/share/hidden\"\n ],\n \"deniedIdentities\": [\n null\n ],\n \"root\": \"{root}/share\",\n \"writable\": true,\n \"write\": [\n \"{root}/share/writable\"\n ]\n }\n ]\n },\n \"format\": 7,\n \"hostname\": \"nvx-sandbox\",\n \"hypervisor\": \"kvm\",\n \"layers\": [\n {\n \"path\": \"{root}/distro.erofs\",\n \"role\": \"distro\",\n \"uuid\": \"11111111-1111-1111-1111-111111111111\"\n }\n ],\n \"memory_max\": null,\n \"memory_mib\": 256,\n \"network\": null,\n \"pids_max\": null,\n \"scratch\": \"{root}/scratch.ext4\",\n \"scratch_binding\": {\n \"device\": {int},\n \"fileId\": \"{hex32}\",\n \"kind\": \"regular\",\n \"length\": 8,\n \"scheme\": \"linux\",\n \"version\": 1\n },\n \"workload_gid\": 65534,\n \"workload_uid\": 65534\n}\n","mode":384},"state/runtime.json":null,"state/control.capability":null,"state/outcome.json":{"text":"{\n \"backend\": \"kvm\",\n \"instance_id\": \"{hex32}\",\n \"network_policy\": {\n \"allow_rule_count\": 0,\n \"deny_rule_count\": 0,\n \"host_loopback\": \"none\",\n \"mode\": \"none\",\n \"status\": \"not-requested\",\n \"status_code\": 0\n },\n \"outcome\": {\n \"category\": \"success\",\n \"operation\": \"managed\",\n \"status_code\": 0\n },\n \"schema_version\": 1,\n \"teardown\": {\n \"control_channels_closed\": true,\n \"guest_workload_stopped\": true,\n \"network_released\": true,\n \"openvmm_process_terminated\": true,\n \"temporary_storage_removed\": true,\n \"virtiofs_released\": true,\n \"vm_stopped\": true\n }\n}\n"},"state/openvmm.log":{"text":""}}},{"argv":["sandbox","start","--state-dir","{root}/state"],"check":["state","state/config.json","state/runtime.json","state/control.capability","state/outcome.json","state/openvmm.log"],"status":0,"stdout":"","stderr":"","files":{"state":{"entries":["config.json","control.capability","control.sock","openvmm.log","runtime.json","sandbox.lock"],"mode":448},"state/config.json":{"text":"{\n \"cmdline\": \"\",\n \"distro_binding\": {\n \"format\": \"erofs\",\n \"identity\": \"11111111-1111-1111-1111-111111111111\",\n \"image\": {\n \"changed\": {\n \"nanoseconds\": {int},\n \"seconds\": {int}\n },\n \"device\": {int},\n \"fileId\": \"{hex32}\",\n \"kind\": \"regular\",\n \"length\": 7,\n \"modified\": {\n \"nanoseconds\": {int},\n \"seconds\": {int}\n },\n \"scheme\": \"linux\",\n \"version\": 1\n },\n \"manifest\": null,\n \"policy\": {\n \"result\": \"accepted\",\n \"revision\": 1\n },\n \"version\": 1\n },\n \"export\": {\n \"binds\": [\n {\n \"child\": 0,\n \"readOnly\": false,\n \"source\": \"\",\n \"target\": \"/data\"\n }\n ],\n \"children\": [\n {\n \"allowed\": [\n \"{root}/share/hidden/shown\"\n ],\n \"denied\": [\n \"{root}/share/hidden\"\n ],\n \"deniedIdentities\": [\n null\n ],\n \"root\": \"{root}/share\",\n \"writable\": true,\n \"write\": [\n \"{root}/share/writable\"\n ]\n }\n ]\n },\n \"format\": 7,\n \"hostname\": \"nvx-sandbox\",\n \"hypervisor\": \"kvm\",\n \"layers\": [\n {\n \"path\": \"{root}/distro.erofs\",\n \"role\": \"distro\",\n \"uuid\": \"11111111-1111-1111-1111-111111111111\"\n }\n ],\n \"memory_max\": null,\n \"memory_mib\": 256,\n \"network\": null,\n \"pids_max\": null,\n \"scratch\": \"{root}/scratch.ext4\",\n \"scratch_binding\": {\n \"device\": {int},\n \"fileId\": \"{hex32}\",\n \"kind\": \"regular\",\n \"length\": 8,\n \"scheme\": \"linux\",\n \"version\": 1\n },\n \"workload_gid\": 65534,\n \"workload_uid\": 65534\n}\n","mode":384},"state/runtime.json":{"text":"{\n \"format\": 4,\n \"launch\": \"{hex32}\",\n \"process\": {\n \"pid\": {int},\n \"startTime\": {int},\n \"boot\": \"{hex32}\"\n },\n \"endpoint\": \"{root}/state/control.sock\",\n \"runtime\": {\n \"openvmm\": \"sha256:1e8c924cdaac227bf74b4a4a9bcdb9e8836a1355fd0408cc81dab5d9aa71eb4d\",\n \"kernel\": \"sha256:a0c936696eb7d5ee3192bf53b9d281cecbb40ca9db520de72cb95817ad92ac72\",\n \"initramfs\": \"sha256:2f77c2c97621e8bf69794e9d12815bb7c46338638f126bea8b18dfe02a684d62\",\n \"bootContract\": 3,\n \"controlContract\": \"nvx-microvm-v2-control-v2\",\n \"controlSession\": 1\n }\n}\n","mode":384},"state/control.capability":{"size":32,"mode":384},"state/outcome.json":null,"state/openvmm.log":{"text":""}}},{"argv":["sandbox","stop","--state-dir","{root}/state"],"check":["state","state/config.json","state/runtime.json","state/control.capability","state/outcome.json","state/openvmm.log"],"status":0,"stdout":"","stderr":"","files":{"state":{"entries":["config.json","openvmm.log","outcome.json","sandbox.lock"],"mode":448},"state/config.json":{"text":"{\n \"cmdline\": \"\",\n \"distro_binding\": {\n \"format\": \"erofs\",\n \"identity\": \"11111111-1111-1111-1111-111111111111\",\n \"image\": {\n \"changed\": {\n \"nanoseconds\": {int},\n \"seconds\": {int}\n },\n \"device\": {int},\n \"fileId\": \"{hex32}\",\n \"kind\": \"regular\",\n \"length\": 7,\n \"modified\": {\n \"nanoseconds\": {int},\n \"seconds\": {int}\n },\n \"scheme\": \"linux\",\n \"version\": 1\n },\n \"manifest\": null,\n \"policy\": {\n \"result\": \"accepted\",\n \"revision\": 1\n },\n \"version\": 1\n },\n \"export\": {\n \"binds\": [\n {\n \"child\": 0,\n \"readOnly\": false,\n \"source\": \"\",\n \"target\": \"/data\"\n }\n ],\n \"children\": [\n {\n \"allowed\": [\n \"{root}/share/hidden/shown\"\n ],\n \"denied\": [\n \"{root}/share/hidden\"\n ],\n \"deniedIdentities\": [\n null\n ],\n \"root\": \"{root}/share\",\n \"writable\": true,\n \"write\": [\n \"{root}/share/writable\"\n ]\n }\n ]\n },\n \"format\": 7,\n \"hostname\": \"nvx-sandbox\",\n \"hypervisor\": \"kvm\",\n \"layers\": [\n {\n \"path\": \"{root}/distro.erofs\",\n \"role\": \"distro\",\n \"uuid\": \"11111111-1111-1111-1111-111111111111\"\n }\n ],\n \"memory_max\": null,\n \"memory_mib\": 256,\n \"network\": null,\n \"pids_max\": null,\n \"scratch\": \"{root}/scratch.ext4\",\n \"scratch_binding\": {\n \"device\": {int},\n \"fileId\": \"{hex32}\",\n \"kind\": \"regular\",\n \"length\": 8,\n \"scheme\": \"linux\",\n \"version\": 1\n },\n \"workload_gid\": 65534,\n \"workload_uid\": 65534\n}\n","mode":384},"state/runtime.json":null,"state/control.capability":null,"state/outcome.json":{"text":"{\n \"backend\": \"kvm\",\n \"instance_id\": \"{hex32}\",\n \"network_policy\": {\n \"allow_rule_count\": 0,\n \"deny_rule_count\": 0,\n \"host_loopback\": \"none\",\n \"mode\": \"none\",\n \"status\": \"not-requested\",\n \"status_code\": 0\n },\n \"outcome\": {\n \"category\": \"success\",\n \"operation\": \"managed\",\n \"status_code\": 0\n },\n \"schema_version\": 1,\n \"teardown\": {\n \"control_channels_closed\": true,\n \"guest_workload_stopped\": true,\n \"network_released\": true,\n \"openvmm_process_terminated\": true,\n \"temporary_storage_removed\": true,\n \"virtiofs_released\": true,\n \"vm_stopped\": true\n }\n}\n"},"state/openvmm.log":{"text":""}}},{"argv":["sandbox","deprovision","--state-dir","{root}/state"],"check":["state"],"status":0,"stdout":"","stderr":"","files":{"state":null}}],"interop":true}, -{"name":"lifecycle: file share","steps":[{"argv":["sandbox","provision","--state-dir","{root}/state","--layer","distro,{root}/distro.erofs,11111111-1111-1111-1111-111111111111","--scratch","{root}/scratch.ext4","--mount","/etc/single.txt,{root}/single.txt,ro"],"check":["state","state/config.json","state/runtime.json","state/control.capability","state/outcome.json","state/openvmm.log"],"status":0,"stdout":"","stderr":"","files":{"state":{"entries":["config.json","sandbox.lock"],"mode":448},"state/config.json":{"text":"{\n \"cmdline\": \"\",\n \"distro_binding\": {\n \"format\": \"erofs\",\n \"identity\": \"11111111-1111-1111-1111-111111111111\",\n \"image\": {\n \"changed\": {\n \"nanoseconds\": {int},\n \"seconds\": {int}\n },\n \"device\": {int},\n \"fileId\": \"{hex32}\",\n \"kind\": \"regular\",\n \"length\": 7,\n \"modified\": {\n \"nanoseconds\": {int},\n \"seconds\": {int}\n },\n \"scheme\": \"linux\",\n \"version\": 1\n },\n \"manifest\": null,\n \"policy\": {\n \"result\": \"accepted\",\n \"revision\": 1\n },\n \"version\": 1\n },\n \"export\": {\n \"binds\": [\n {\n \"child\": 0,\n \"readOnly\": true,\n \"source\": \"\",\n \"target\": \"/etc/single.txt\"\n }\n ],\n \"children\": [\n {\n \"allowed\": [],\n \"denied\": [],\n \"deniedIdentities\": [],\n \"file\": true,\n \"root\": \"{root}/single.txt\",\n \"writable\": false,\n \"write\": []\n }\n ]\n },\n \"format\": 7,\n \"hostname\": \"nvx-sandbox\",\n \"hypervisor\": \"kvm\",\n \"layers\": [\n {\n \"path\": \"{root}/distro.erofs\",\n \"role\": \"distro\",\n \"uuid\": \"11111111-1111-1111-1111-111111111111\"\n }\n ],\n \"memory_max\": null,\n \"memory_mib\": 256,\n \"network\": null,\n \"pids_max\": null,\n \"scratch\": \"{root}/scratch.ext4\",\n \"scratch_binding\": {\n \"device\": {int},\n \"fileId\": \"{hex32}\",\n \"kind\": \"regular\",\n \"length\": 8,\n \"scheme\": \"linux\",\n \"version\": 1\n },\n \"workload_gid\": 65534,\n \"workload_uid\": 65534\n}\n","mode":384},"state/runtime.json":null,"state/control.capability":null,"state/outcome.json":null,"state/openvmm.log":null}},{"argv":["sandbox","start","--state-dir","{root}/state"],"check":["state","state/config.json","state/runtime.json","state/control.capability","state/outcome.json","state/openvmm.log","build/fake-openvmm-state.json"],"status":0,"stdout":"","stderr":"","files":{"state":{"entries":["config.json","control.capability","control.sock","openvmm.log","runtime.json","sandbox.lock"],"mode":448},"state/config.json":{"text":"{\n \"cmdline\": \"\",\n \"distro_binding\": {\n \"format\": \"erofs\",\n \"identity\": \"11111111-1111-1111-1111-111111111111\",\n \"image\": {\n \"changed\": {\n \"nanoseconds\": {int},\n \"seconds\": {int}\n },\n \"device\": {int},\n \"fileId\": \"{hex32}\",\n \"kind\": \"regular\",\n \"length\": 7,\n \"modified\": {\n \"nanoseconds\": {int},\n \"seconds\": {int}\n },\n \"scheme\": \"linux\",\n \"version\": 1\n },\n \"manifest\": null,\n \"policy\": {\n \"result\": \"accepted\",\n \"revision\": 1\n },\n \"version\": 1\n },\n \"export\": {\n \"binds\": [\n {\n \"child\": 0,\n \"readOnly\": true,\n \"source\": \"\",\n \"target\": \"/etc/single.txt\"\n }\n ],\n \"children\": [\n {\n \"allowed\": [],\n \"denied\": [],\n \"deniedIdentities\": [],\n \"file\": true,\n \"root\": \"{root}/single.txt\",\n \"writable\": false,\n \"write\": []\n }\n ]\n },\n \"format\": 7,\n \"hostname\": \"nvx-sandbox\",\n \"hypervisor\": \"kvm\",\n \"layers\": [\n {\n \"path\": \"{root}/distro.erofs\",\n \"role\": \"distro\",\n \"uuid\": \"11111111-1111-1111-1111-111111111111\"\n }\n ],\n \"memory_max\": null,\n \"memory_mib\": 256,\n \"network\": null,\n \"pids_max\": null,\n \"scratch\": \"{root}/scratch.ext4\",\n \"scratch_binding\": {\n \"device\": {int},\n \"fileId\": \"{hex32}\",\n \"kind\": \"regular\",\n \"length\": 8,\n \"scheme\": \"linux\",\n \"version\": 1\n },\n \"workload_gid\": 65534,\n \"workload_uid\": 65534\n}\n","mode":384},"state/runtime.json":{"text":"{\n \"format\": 4,\n \"launch\": \"{hex32}\",\n \"process\": {\n \"pid\": {int},\n \"startTime\": {int},\n \"boot\": \"{hex32}\"\n },\n \"endpoint\": \"{root}/state/control.sock\",\n \"runtime\": {\n \"openvmm\": \"sha256:1e8c924cdaac227bf74b4a4a9bcdb9e8836a1355fd0408cc81dab5d9aa71eb4d\",\n \"kernel\": \"sha256:a0c936696eb7d5ee3192bf53b9d281cecbb40ca9db520de72cb95817ad92ac72\",\n \"initramfs\": \"sha256:2f77c2c97621e8bf69794e9d12815bb7c46338638f126bea8b18dfe02a684d62\",\n \"bootContract\": 3,\n \"controlContract\": \"nvx-microvm-v2-control-v2\",\n \"controlSession\": 1\n }\n}\n","mode":384},"state/control.capability":{"size":32,"mode":384},"state/outcome.json":null,"state/openvmm.log":{"text":""},"build/fake-openvmm-state.json":{"text":"[\"--machine\",\"microvm\",\"--microvm-sandbox-block\",\"distro:file:/proc/self/fd/{int},ro\",\"--microvm-sandbox-block\",\"scratch:file:/proc/self/fd/{int}\",\"--microvm-workload-identity\",\"65534:65534\",\"--mount-aggregate\",\"/run/nvx/shares\",\"--mount-child\",\"0-a80a05e9cb129bc27b7ba103bf2f5ac0,{root}/single.txt,ro,file\",\"--microvm-lifecycle\",\"managed\",\"--single-process\",\"--hypervisor\",\"kvm\",\"--memory\",\"256M\",\"--kernel\",\"{root}/build/vmlinux\",\"--initrd\",\"{root}/build/initramfs.cpio.gz\",\"--cmdline\",\"nvx_sandbox=1 nvx_layer=distro,0xd0003000,erofs:11111111-1111-1111-1111-111111111111 nvx_scratch=0xd0006000,ext4 nvx_entrypoint=/bin/sh nvx_hostname=nvx-sandbox nvx_share=0-a80a05e9cb129bc27b7ba103bf2f5ac0,/etc/single.txt,ro,file\",\"--virtio-console\",\"none\",\"--microvm-control-console\",\"listen={root}/state/control.sock\",\"--microvm-control-auth-stdin\",\"--microvm-report\",\"{root}/state/outcome.json\"]"}}},{"argv":["sandbox","stop","--state-dir","{root}/state"],"check":["state","state/config.json","state/runtime.json","state/control.capability","state/outcome.json","state/openvmm.log"],"status":0,"stdout":"","stderr":"","files":{"state":{"entries":["config.json","openvmm.log","outcome.json","sandbox.lock"],"mode":448},"state/config.json":{"text":"{\n \"cmdline\": \"\",\n \"distro_binding\": {\n \"format\": \"erofs\",\n \"identity\": \"11111111-1111-1111-1111-111111111111\",\n \"image\": {\n \"changed\": {\n \"nanoseconds\": {int},\n \"seconds\": {int}\n },\n \"device\": {int},\n \"fileId\": \"{hex32}\",\n \"kind\": \"regular\",\n \"length\": 7,\n \"modified\": {\n \"nanoseconds\": {int},\n \"seconds\": {int}\n },\n \"scheme\": \"linux\",\n \"version\": 1\n },\n \"manifest\": null,\n \"policy\": {\n \"result\": \"accepted\",\n \"revision\": 1\n },\n \"version\": 1\n },\n \"export\": {\n \"binds\": [\n {\n \"child\": 0,\n \"readOnly\": true,\n \"source\": \"\",\n \"target\": \"/etc/single.txt\"\n }\n ],\n \"children\": [\n {\n \"allowed\": [],\n \"denied\": [],\n \"deniedIdentities\": [],\n \"file\": true,\n \"root\": \"{root}/single.txt\",\n \"writable\": false,\n \"write\": []\n }\n ]\n },\n \"format\": 7,\n \"hostname\": \"nvx-sandbox\",\n \"hypervisor\": \"kvm\",\n \"layers\": [\n {\n \"path\": \"{root}/distro.erofs\",\n \"role\": \"distro\",\n \"uuid\": \"11111111-1111-1111-1111-111111111111\"\n }\n ],\n \"memory_max\": null,\n \"memory_mib\": 256,\n \"network\": null,\n \"pids_max\": null,\n \"scratch\": \"{root}/scratch.ext4\",\n \"scratch_binding\": {\n \"device\": {int},\n \"fileId\": \"{hex32}\",\n \"kind\": \"regular\",\n \"length\": 8,\n \"scheme\": \"linux\",\n \"version\": 1\n },\n \"workload_gid\": 65534,\n \"workload_uid\": 65534\n}\n","mode":384},"state/runtime.json":null,"state/control.capability":null,"state/outcome.json":{"text":"{\n \"backend\": \"kvm\",\n \"instance_id\": \"{hex32}\",\n \"network_policy\": {\n \"allow_rule_count\": 0,\n \"deny_rule_count\": 0,\n \"host_loopback\": \"none\",\n \"mode\": \"none\",\n \"status\": \"not-requested\",\n \"status_code\": 0\n },\n \"outcome\": {\n \"category\": \"success\",\n \"operation\": \"managed\",\n \"status_code\": 0\n },\n \"schema_version\": 1,\n \"teardown\": {\n \"control_channels_closed\": true,\n \"guest_workload_stopped\": true,\n \"network_released\": true,\n \"openvmm_process_terminated\": true,\n \"temporary_storage_removed\": true,\n \"virtiofs_released\": true,\n \"vm_stopped\": true\n }\n}\n"},"state/openvmm.log":{"text":""}}},{"argv":["sandbox","start","--state-dir","{root}/state"],"check":["state","state/config.json","state/runtime.json","state/control.capability","state/outcome.json","state/openvmm.log"],"status":0,"stdout":"","stderr":"","files":{"state":{"entries":["config.json","control.capability","control.sock","openvmm.log","runtime.json","sandbox.lock"],"mode":448},"state/config.json":{"text":"{\n \"cmdline\": \"\",\n \"distro_binding\": {\n \"format\": \"erofs\",\n \"identity\": \"11111111-1111-1111-1111-111111111111\",\n \"image\": {\n \"changed\": {\n \"nanoseconds\": {int},\n \"seconds\": {int}\n },\n \"device\": {int},\n \"fileId\": \"{hex32}\",\n \"kind\": \"regular\",\n \"length\": 7,\n \"modified\": {\n \"nanoseconds\": {int},\n \"seconds\": {int}\n },\n \"scheme\": \"linux\",\n \"version\": 1\n },\n \"manifest\": null,\n \"policy\": {\n \"result\": \"accepted\",\n \"revision\": 1\n },\n \"version\": 1\n },\n \"export\": {\n \"binds\": [\n {\n \"child\": 0,\n \"readOnly\": true,\n \"source\": \"\",\n \"target\": \"/etc/single.txt\"\n }\n ],\n \"children\": [\n {\n \"allowed\": [],\n \"denied\": [],\n \"deniedIdentities\": [],\n \"file\": true,\n \"root\": \"{root}/single.txt\",\n \"writable\": false,\n \"write\": []\n }\n ]\n },\n \"format\": 7,\n \"hostname\": \"nvx-sandbox\",\n \"hypervisor\": \"kvm\",\n \"layers\": [\n {\n \"path\": \"{root}/distro.erofs\",\n \"role\": \"distro\",\n \"uuid\": \"11111111-1111-1111-1111-111111111111\"\n }\n ],\n \"memory_max\": null,\n \"memory_mib\": 256,\n \"network\": null,\n \"pids_max\": null,\n \"scratch\": \"{root}/scratch.ext4\",\n \"scratch_binding\": {\n \"device\": {int},\n \"fileId\": \"{hex32}\",\n \"kind\": \"regular\",\n \"length\": 8,\n \"scheme\": \"linux\",\n \"version\": 1\n },\n \"workload_gid\": 65534,\n \"workload_uid\": 65534\n}\n","mode":384},"state/runtime.json":{"text":"{\n \"format\": 4,\n \"launch\": \"{hex32}\",\n \"process\": {\n \"pid\": {int},\n \"startTime\": {int},\n \"boot\": \"{hex32}\"\n },\n \"endpoint\": \"{root}/state/control.sock\",\n \"runtime\": {\n \"openvmm\": \"sha256:1e8c924cdaac227bf74b4a4a9bcdb9e8836a1355fd0408cc81dab5d9aa71eb4d\",\n \"kernel\": \"sha256:a0c936696eb7d5ee3192bf53b9d281cecbb40ca9db520de72cb95817ad92ac72\",\n \"initramfs\": \"sha256:2f77c2c97621e8bf69794e9d12815bb7c46338638f126bea8b18dfe02a684d62\",\n \"bootContract\": 3,\n \"controlContract\": \"nvx-microvm-v2-control-v2\",\n \"controlSession\": 1\n }\n}\n","mode":384},"state/control.capability":{"size":32,"mode":384},"state/outcome.json":null,"state/openvmm.log":{"text":""}}},{"argv":["sandbox","stop","--state-dir","{root}/state"],"check":["state","state/config.json","state/runtime.json","state/control.capability","state/outcome.json","state/openvmm.log"],"status":0,"stdout":"","stderr":"","files":{"state":{"entries":["config.json","openvmm.log","outcome.json","sandbox.lock"],"mode":448},"state/config.json":{"text":"{\n \"cmdline\": \"\",\n \"distro_binding\": {\n \"format\": \"erofs\",\n \"identity\": \"11111111-1111-1111-1111-111111111111\",\n \"image\": {\n \"changed\": {\n \"nanoseconds\": {int},\n \"seconds\": {int}\n },\n \"device\": {int},\n \"fileId\": \"{hex32}\",\n \"kind\": \"regular\",\n \"length\": 7,\n \"modified\": {\n \"nanoseconds\": {int},\n \"seconds\": {int}\n },\n \"scheme\": \"linux\",\n \"version\": 1\n },\n \"manifest\": null,\n \"policy\": {\n \"result\": \"accepted\",\n \"revision\": 1\n },\n \"version\": 1\n },\n \"export\": {\n \"binds\": [\n {\n \"child\": 0,\n \"readOnly\": true,\n \"source\": \"\",\n \"target\": \"/etc/single.txt\"\n }\n ],\n \"children\": [\n {\n \"allowed\": [],\n \"denied\": [],\n \"deniedIdentities\": [],\n \"file\": true,\n \"root\": \"{root}/single.txt\",\n \"writable\": false,\n \"write\": []\n }\n ]\n },\n \"format\": 7,\n \"hostname\": \"nvx-sandbox\",\n \"hypervisor\": \"kvm\",\n \"layers\": [\n {\n \"path\": \"{root}/distro.erofs\",\n \"role\": \"distro\",\n \"uuid\": \"11111111-1111-1111-1111-111111111111\"\n }\n ],\n \"memory_max\": null,\n \"memory_mib\": 256,\n \"network\": null,\n \"pids_max\": null,\n \"scratch\": \"{root}/scratch.ext4\",\n \"scratch_binding\": {\n \"device\": {int},\n \"fileId\": \"{hex32}\",\n \"kind\": \"regular\",\n \"length\": 8,\n \"scheme\": \"linux\",\n \"version\": 1\n },\n \"workload_gid\": 65534,\n \"workload_uid\": 65534\n}\n","mode":384},"state/runtime.json":null,"state/control.capability":null,"state/outcome.json":{"text":"{\n \"backend\": \"kvm\",\n \"instance_id\": \"{hex32}\",\n \"network_policy\": {\n \"allow_rule_count\": 0,\n \"deny_rule_count\": 0,\n \"host_loopback\": \"none\",\n \"mode\": \"none\",\n \"status\": \"not-requested\",\n \"status_code\": 0\n },\n \"outcome\": {\n \"category\": \"success\",\n \"operation\": \"managed\",\n \"status_code\": 0\n },\n \"schema_version\": 1,\n \"teardown\": {\n \"control_channels_closed\": true,\n \"guest_workload_stopped\": true,\n \"network_released\": true,\n \"openvmm_process_terminated\": true,\n \"temporary_storage_removed\": true,\n \"virtiofs_released\": true,\n \"vm_stopped\": true\n }\n}\n"},"state/openvmm.log":{"text":""}}},{"argv":["sandbox","deprovision","--state-dir","{root}/state"],"check":["state"],"status":0,"stdout":"","stderr":"","files":{"state":null}}],"interop":true}, +{"name":"lifecycle: minimal","steps":[{"argv":["sandbox","provision","--state-dir","{root}/state","--layer","distro,{root}/distro.erofs,11111111-1111-1111-1111-111111111111","--scratch","{root}/scratch.ext4"],"check":["state","state/config.json","state/runtime.json","state/control.capability","state/outcome.json","state/openvmm.log"],"status":0,"stdout":"","stderr":"","files":{"state":{"entries":["config.json","sandbox.lock"],"mode":448},"state/config.json":{"text":"{\n \"cmdline\": \"\",\n \"distro_binding\": {\n \"format\": \"erofs\",\n \"identity\": \"11111111-1111-1111-1111-111111111111\",\n \"image\": {\n \"changed\": {\n \"nanoseconds\": {int},\n \"seconds\": {int}\n },\n \"device\": {int},\n \"fileId\": \"{hex32}\",\n \"kind\": \"regular\",\n \"length\": 7,\n \"modified\": {\n \"nanoseconds\": {int},\n \"seconds\": {int}\n },\n \"scheme\": \"linux\",\n \"version\": 1\n },\n \"manifest\": null,\n \"policy\": {\n \"result\": \"accepted\",\n \"revision\": 1\n },\n \"version\": 1\n },\n \"format\": 1,\n \"hostname\": \"nvx-sandbox\",\n \"hypervisor\": \"kvm\",\n \"layers\": [\n {\n \"path\": \"{root}/distro.erofs\",\n \"role\": \"distro\",\n \"uuid\": \"11111111-1111-1111-1111-111111111111\"\n }\n ],\n \"memory_max\": null,\n \"memory_mib\": 256,\n \"mount\": null,\n \"network\": null,\n \"pids_max\": null,\n \"scratch\": \"{root}/scratch.ext4\",\n \"scratch_binding\": {\n \"device\": {int},\n \"fileId\": \"{hex32}\",\n \"kind\": \"regular\",\n \"length\": 8,\n \"scheme\": \"linux\",\n \"version\": 1\n },\n \"workload_gid\": 65534,\n \"workload_uid\": 65534\n}\n","mode":384},"state/runtime.json":null,"state/control.capability":null,"state/outcome.json":null,"state/openvmm.log":null}},{"argv":["sandbox","start","--state-dir","{root}/state"],"check":["state","state/config.json","state/runtime.json","state/control.capability","state/outcome.json","state/openvmm.log","build/fake-openvmm-state.json","build/fake-openvmm-state-maps.json"],"status":0,"stdout":"","stderr":"","files":{"state":{"entries":["config.json","control.capability","control.sock","openvmm.log","runtime.json","sandbox.lock"],"mode":448},"state/config.json":{"text":"{\n \"cmdline\": \"\",\n \"distro_binding\": {\n \"format\": \"erofs\",\n \"identity\": \"11111111-1111-1111-1111-111111111111\",\n \"image\": {\n \"changed\": {\n \"nanoseconds\": {int},\n \"seconds\": {int}\n },\n \"device\": {int},\n \"fileId\": \"{hex32}\",\n \"kind\": \"regular\",\n \"length\": 7,\n \"modified\": {\n \"nanoseconds\": {int},\n \"seconds\": {int}\n },\n \"scheme\": \"linux\",\n \"version\": 1\n },\n \"manifest\": null,\n \"policy\": {\n \"result\": \"accepted\",\n \"revision\": 1\n },\n \"version\": 1\n },\n \"format\": 1,\n \"hostname\": \"nvx-sandbox\",\n \"hypervisor\": \"kvm\",\n \"layers\": [\n {\n \"path\": \"{root}/distro.erofs\",\n \"role\": \"distro\",\n \"uuid\": \"11111111-1111-1111-1111-111111111111\"\n }\n ],\n \"memory_max\": null,\n \"memory_mib\": 256,\n \"mount\": null,\n \"network\": null,\n \"pids_max\": null,\n \"scratch\": \"{root}/scratch.ext4\",\n \"scratch_binding\": {\n \"device\": {int},\n \"fileId\": \"{hex32}\",\n \"kind\": \"regular\",\n \"length\": 8,\n \"scheme\": \"linux\",\n \"version\": 1\n },\n \"workload_gid\": 65534,\n \"workload_uid\": 65534\n}\n","mode":384},"state/runtime.json":{"text":"{\n \"format\": 4,\n \"launch\": \"{hex32}\",\n \"process\": {\n \"pid\": {int},\n \"startTime\": {int},\n \"boot\": \"{hex32}\"\n },\n \"endpoint\": \"{root}/state/control.sock\",\n \"runtime\": {\n \"openvmm\": \"sha256:1e8c924cdaac227bf74b4a4a9bcdb9e8836a1355fd0408cc81dab5d9aa71eb4d\",\n \"kernel\": \"sha256:a0c936696eb7d5ee3192bf53b9d281cecbb40ca9db520de72cb95817ad92ac72\",\n \"initramfs\": \"sha256:2f77c2c97621e8bf69794e9d12815bb7c46338638f126bea8b18dfe02a684d62\",\n \"bootContract\": 3,\n \"controlContract\": \"nvx-microvm-v2-control-v2\",\n \"controlSession\": 1\n }\n}\n","mode":384},"state/control.capability":{"size":32,"mode":384},"state/outcome.json":null,"state/openvmm.log":{"text":""},"build/fake-openvmm-state.json":{"text":"[\"--machine\",\"microvm\",\"--microvm-sandbox-block\",\"distro:file:/proc/self/fd/{int},ro\",\"--microvm-sandbox-block\",\"scratch:file:/proc/self/fd/{int}\",\"--microvm-workload-identity\",\"65534:65534\",\"--microvm-lifecycle\",\"managed\",\"--single-process\",\"--hypervisor\",\"kvm\",\"--memory\",\"256M\",\"--kernel\",\"{root}/build/vmlinux\",\"--initrd\",\"{root}/build/initramfs.cpio.gz\",\"--cmdline\",\"nvx_sandbox=1 nvx_layer=distro,0xd0003000,erofs:11111111-1111-1111-1111-111111111111 nvx_scratch=0xd0006000,ext4 nvx_entrypoint=/bin/sh nvx_hostname=nvx-sandbox\",\"--virtio-console\",\"none\",\"--microvm-control-console\",\"listen={root}/state/control.sock\",\"--microvm-control-auth-stdin\",\"--microvm-report\",\"{root}/state/outcome.json\"]"},"build/fake-openvmm-state-maps.json":null}},{"argv":["sandbox","exec","--state-dir","{root}/state","--entrypoint","/bin/echo","--arg","hello","--arg","world"],"status":0,"stdout":"hello world\n","stderr":""},{"argv":["sandbox","exec","--state-dir","{root}/state","--entrypoint","/bin/pwd","--cwd","/tmp"],"status":0,"stdout":"/tmp\n","stderr":""},{"argv":["sandbox","exec","--state-dir","{root}/state","--entrypoint","/bin/sh","--arg=-c","--arg","echo out; echoerr err; exit 3","--outcome-report","{root}/reports/exec.json"],"check":["reports/exec.json"],"status":3,"stdout":"out\n","stderr":"err\n","files":{"reports/exec.json":{"text":"{\n \"operation_id\": \"{hex32}\",\n \"outcome\": {\n \"category\": \"exit\",\n \"operation\": \"exec\",\n \"status_code\": 3\n },\n \"schema_version\": 1\n}\n","mode":384}}},{"argv":["sandbox","exec","--state-dir","{root}/state","--entrypoint","/usr/bin/env","--environment","A=1","--environment","B=two"],"status":0,"stdout":"A=1\nB=two\n","stderr":""},{"argv":["sandbox","exec","--state-dir","{root}/state","--entrypoint","/usr/bin/printenv","--arg","PATH","--inherit-default-environment","--environment","A=1"],"status":0,"stdout":"/usr/sbin:/usr/bin:/sbin:/bin\n","stderr":""},{"argv":["sandbox","exec","--state-dir","{root}/state","--entrypoint","/usr/bin/env","--environment-file","{root}/env.json"],"write":{"env.json":"[\"X=1\", \"Y=two words\"]"},"status":0,"stdout":"X=1\nY=two words\n","stderr":""},{"argv":["sandbox","exec","--state-dir","{root}/state","--entrypoint","/usr/bin/env","--environment-file","{root}/empty.json"],"write":{"empty.json":"[]"},"status":0,"stdout":"","stderr":""},{"argv":["sandbox","exec","--state-dir","{root}/state","--entrypoint","/bin/sh","--arg=-c","--arg","sleep 5000","--exec-timeout-ms","50","--outcome-report","{root}/reports/exec-timeout.json"],"check":["reports/exec-timeout.json"],"status":124,"stdout":"","stderr":"","files":{"reports/exec-timeout.json":{"text":"{\n \"operation_id\": \"{hex32}\",\n \"outcome\": {\n \"category\": \"timeout\",\n \"operation\": \"exec\",\n \"status_code\": 124\n },\n \"schema_version\": 1\n}\n","mode":384}}},{"argv":["sandbox","exec","--state-dir","{root}/state","--entrypoint","/bin/sh","--arg=-c","--arg","signal 9"],"status":137,"stdout":"","stderr":""},{"argv":["sandbox","exec","--state-dir","{root}/state","--entrypoint","/bin/missing"],"status":127,"stdout":"","stderr":"openvmm: /bin/missing: not found\n"},{"argv":["sandbox","exec","--state-dir","{root}/state","--entrypoint","/bin/pwd","--cwd","/missing"],"status":1,"stdout":"","stderr":"error: managed guest rejected exec (status=2, category=cwd-failed)\n"},{"argv":["sandbox","exec","--state-dir","{root}/state","--entrypoint","/bin/pwd","--cwd","relative"],"status":1,"stdout":"","stderr":"error: managed exec working directory must be an absolute path of at most 4096 bytes\n"},{"argv":["sandbox","exec","--state-dir","{root}/state","--entrypoint","/bin/echo","--outcome-report","{root}/reports/exec.json"],"status":1,"stdout":"","stderr":"error: outcome report already exists: {root}/reports/exec.json\n"},{"argv":["sandbox","exec","--state-dir","{root}/state","--entrypoint","/bin/echo","--outcome-report","{root}/missing/exec.json"],"status":1,"stdout":"","stderr":"error: outcome report parent is not a plain directory: {root}/missing\n"},{"argv":["sandbox","stop","--state-dir","{root}/state"],"check":["state","state/config.json","state/runtime.json","state/control.capability","state/outcome.json","state/openvmm.log"],"status":0,"stdout":"","stderr":"","files":{"state":{"entries":["config.json","openvmm.log","outcome.json","sandbox.lock"],"mode":448},"state/config.json":{"text":"{\n \"cmdline\": \"\",\n \"distro_binding\": {\n \"format\": \"erofs\",\n \"identity\": \"11111111-1111-1111-1111-111111111111\",\n \"image\": {\n \"changed\": {\n \"nanoseconds\": {int},\n \"seconds\": {int}\n },\n \"device\": {int},\n \"fileId\": \"{hex32}\",\n \"kind\": \"regular\",\n \"length\": 7,\n \"modified\": {\n \"nanoseconds\": {int},\n \"seconds\": {int}\n },\n \"scheme\": \"linux\",\n \"version\": 1\n },\n \"manifest\": null,\n \"policy\": {\n \"result\": \"accepted\",\n \"revision\": 1\n },\n \"version\": 1\n },\n \"format\": 1,\n \"hostname\": \"nvx-sandbox\",\n \"hypervisor\": \"kvm\",\n \"layers\": [\n {\n \"path\": \"{root}/distro.erofs\",\n \"role\": \"distro\",\n \"uuid\": \"11111111-1111-1111-1111-111111111111\"\n }\n ],\n \"memory_max\": null,\n \"memory_mib\": 256,\n \"mount\": null,\n \"network\": null,\n \"pids_max\": null,\n \"scratch\": \"{root}/scratch.ext4\",\n \"scratch_binding\": {\n \"device\": {int},\n \"fileId\": \"{hex32}\",\n \"kind\": \"regular\",\n \"length\": 8,\n \"scheme\": \"linux\",\n \"version\": 1\n },\n \"workload_gid\": 65534,\n \"workload_uid\": 65534\n}\n","mode":384},"state/runtime.json":null,"state/control.capability":null,"state/outcome.json":{"text":"{\n \"backend\": \"kvm\",\n \"instance_id\": \"{hex32}\",\n \"network_policy\": {\n \"allow_rule_count\": 0,\n \"deny_rule_count\": 0,\n \"host_loopback\": \"none\",\n \"mode\": \"none\",\n \"status\": \"not-requested\",\n \"status_code\": 0\n },\n \"outcome\": {\n \"category\": \"success\",\n \"operation\": \"managed\",\n \"status_code\": 0\n },\n \"schema_version\": 1,\n \"teardown\": {\n \"control_channels_closed\": true,\n \"guest_workload_stopped\": true,\n \"network_released\": true,\n \"openvmm_process_terminated\": true,\n \"temporary_storage_removed\": true,\n \"virtiofs_released\": true,\n \"vm_stopped\": true\n }\n}\n"},"state/openvmm.log":{"text":""}}},{"argv":["sandbox","start","--state-dir","{root}/state"],"check":["state","state/config.json","state/runtime.json","state/control.capability","state/outcome.json","state/openvmm.log"],"status":0,"stdout":"","stderr":"","files":{"state":{"entries":["config.json","control.capability","control.sock","openvmm.log","runtime.json","sandbox.lock"],"mode":448},"state/config.json":{"text":"{\n \"cmdline\": \"\",\n \"distro_binding\": {\n \"format\": \"erofs\",\n \"identity\": \"11111111-1111-1111-1111-111111111111\",\n \"image\": {\n \"changed\": {\n \"nanoseconds\": {int},\n \"seconds\": {int}\n },\n \"device\": {int},\n \"fileId\": \"{hex32}\",\n \"kind\": \"regular\",\n \"length\": 7,\n \"modified\": {\n \"nanoseconds\": {int},\n \"seconds\": {int}\n },\n \"scheme\": \"linux\",\n \"version\": 1\n },\n \"manifest\": null,\n \"policy\": {\n \"result\": \"accepted\",\n \"revision\": 1\n },\n \"version\": 1\n },\n \"format\": 1,\n \"hostname\": \"nvx-sandbox\",\n \"hypervisor\": \"kvm\",\n \"layers\": [\n {\n \"path\": \"{root}/distro.erofs\",\n \"role\": \"distro\",\n \"uuid\": \"11111111-1111-1111-1111-111111111111\"\n }\n ],\n \"memory_max\": null,\n \"memory_mib\": 256,\n \"mount\": null,\n \"network\": null,\n \"pids_max\": null,\n \"scratch\": \"{root}/scratch.ext4\",\n \"scratch_binding\": {\n \"device\": {int},\n \"fileId\": \"{hex32}\",\n \"kind\": \"regular\",\n \"length\": 8,\n \"scheme\": \"linux\",\n \"version\": 1\n },\n \"workload_gid\": 65534,\n \"workload_uid\": 65534\n}\n","mode":384},"state/runtime.json":{"text":"{\n \"format\": 4,\n \"launch\": \"{hex32}\",\n \"process\": {\n \"pid\": {int},\n \"startTime\": {int},\n \"boot\": \"{hex32}\"\n },\n \"endpoint\": \"{root}/state/control.sock\",\n \"runtime\": {\n \"openvmm\": \"sha256:1e8c924cdaac227bf74b4a4a9bcdb9e8836a1355fd0408cc81dab5d9aa71eb4d\",\n \"kernel\": \"sha256:a0c936696eb7d5ee3192bf53b9d281cecbb40ca9db520de72cb95817ad92ac72\",\n \"initramfs\": \"sha256:2f77c2c97621e8bf69794e9d12815bb7c46338638f126bea8b18dfe02a684d62\",\n \"bootContract\": 3,\n \"controlContract\": \"nvx-microvm-v2-control-v2\",\n \"controlSession\": 1\n }\n}\n","mode":384},"state/control.capability":{"size":32,"mode":384},"state/outcome.json":null,"state/openvmm.log":{"text":""}}},{"argv":["sandbox","stop","--state-dir","{root}/state"],"check":["state","state/config.json","state/runtime.json","state/control.capability","state/outcome.json","state/openvmm.log"],"status":0,"stdout":"","stderr":"","files":{"state":{"entries":["config.json","openvmm.log","outcome.json","sandbox.lock"],"mode":448},"state/config.json":{"text":"{\n \"cmdline\": \"\",\n \"distro_binding\": {\n \"format\": \"erofs\",\n \"identity\": \"11111111-1111-1111-1111-111111111111\",\n \"image\": {\n \"changed\": {\n \"nanoseconds\": {int},\n \"seconds\": {int}\n },\n \"device\": {int},\n \"fileId\": \"{hex32}\",\n \"kind\": \"regular\",\n \"length\": 7,\n \"modified\": {\n \"nanoseconds\": {int},\n \"seconds\": {int}\n },\n \"scheme\": \"linux\",\n \"version\": 1\n },\n \"manifest\": null,\n \"policy\": {\n \"result\": \"accepted\",\n \"revision\": 1\n },\n \"version\": 1\n },\n \"format\": 1,\n \"hostname\": \"nvx-sandbox\",\n \"hypervisor\": \"kvm\",\n \"layers\": [\n {\n \"path\": \"{root}/distro.erofs\",\n \"role\": \"distro\",\n \"uuid\": \"11111111-1111-1111-1111-111111111111\"\n }\n ],\n \"memory_max\": null,\n \"memory_mib\": 256,\n \"mount\": null,\n \"network\": null,\n \"pids_max\": null,\n \"scratch\": \"{root}/scratch.ext4\",\n \"scratch_binding\": {\n \"device\": {int},\n \"fileId\": \"{hex32}\",\n \"kind\": \"regular\",\n \"length\": 8,\n \"scheme\": \"linux\",\n \"version\": 1\n },\n \"workload_gid\": 65534,\n \"workload_uid\": 65534\n}\n","mode":384},"state/runtime.json":null,"state/control.capability":null,"state/outcome.json":{"text":"{\n \"backend\": \"kvm\",\n \"instance_id\": \"{hex32}\",\n \"network_policy\": {\n \"allow_rule_count\": 0,\n \"deny_rule_count\": 0,\n \"host_loopback\": \"none\",\n \"mode\": \"none\",\n \"status\": \"not-requested\",\n \"status_code\": 0\n },\n \"outcome\": {\n \"category\": \"success\",\n \"operation\": \"managed\",\n \"status_code\": 0\n },\n \"schema_version\": 1,\n \"teardown\": {\n \"control_channels_closed\": true,\n \"guest_workload_stopped\": true,\n \"network_released\": true,\n \"openvmm_process_terminated\": true,\n \"temporary_storage_removed\": true,\n \"virtiofs_released\": true,\n \"vm_stopped\": true\n }\n}\n"},"state/openvmm.log":{"text":""}}},{"argv":["sandbox","deprovision","--state-dir","{root}/state"],"check":["state"],"status":0,"stdout":"","stderr":"","files":{"state":null}}],"interop":true}, +{"name":"lifecycle: one share","steps":[{"argv":["sandbox","provision","--state-dir","{root}/state","--layer","distro,{root}/distro.erofs,11111111-1111-1111-1111-111111111111","--scratch","{root}/scratch.ext4","--mount","/data,{root}/share"],"check":["state","state/config.json","state/runtime.json","state/control.capability","state/outcome.json","state/openvmm.log"],"status":0,"stdout":"","stderr":"","files":{"state":{"entries":["config.json","sandbox.lock"],"mode":448},"state/config.json":{"text":"{\n \"cmdline\": \"\",\n \"distro_binding\": {\n \"format\": \"erofs\",\n \"identity\": \"11111111-1111-1111-1111-111111111111\",\n \"image\": {\n \"changed\": {\n \"nanoseconds\": {int},\n \"seconds\": {int}\n },\n \"device\": {int},\n \"fileId\": \"{hex32}\",\n \"kind\": \"regular\",\n \"length\": 7,\n \"modified\": {\n \"nanoseconds\": {int},\n \"seconds\": {int}\n },\n \"scheme\": \"linux\",\n \"version\": 1\n },\n \"manifest\": null,\n \"policy\": {\n \"result\": \"accepted\",\n \"revision\": 1\n },\n \"version\": 1\n },\n \"export\": {\n \"binds\": [\n {\n \"child\": 0,\n \"readOnly\": true,\n \"source\": \"\",\n \"target\": \"/data\"\n }\n ],\n \"children\": [\n {\n \"allowed\": [],\n \"denied\": [],\n \"deniedIdentities\": [],\n \"root\": \"{root}/share\",\n \"writable\": false,\n \"write\": []\n }\n ]\n },\n \"format\": 7,\n \"hostname\": \"nvx-sandbox\",\n \"hypervisor\": \"kvm\",\n \"layers\": [\n {\n \"path\": \"{root}/distro.erofs\",\n \"role\": \"distro\",\n \"uuid\": \"11111111-1111-1111-1111-111111111111\"\n }\n ],\n \"memory_max\": null,\n \"memory_mib\": 256,\n \"network\": null,\n \"pids_max\": null,\n \"scratch\": \"{root}/scratch.ext4\",\n \"scratch_binding\": {\n \"device\": {int},\n \"fileId\": \"{hex32}\",\n \"kind\": \"regular\",\n \"length\": 8,\n \"scheme\": \"linux\",\n \"version\": 1\n },\n \"workload_gid\": 65534,\n \"workload_uid\": 65534\n}\n","mode":384},"state/runtime.json":null,"state/control.capability":null,"state/outcome.json":null,"state/openvmm.log":null}},{"argv":["sandbox","start","--state-dir","{root}/state"],"check":["state","state/config.json","state/runtime.json","state/control.capability","state/outcome.json","state/openvmm.log","build/fake-openvmm-state.json","build/fake-openvmm-state-maps.json"],"status":0,"stdout":"","stderr":"","files":{"state":{"entries":["config.json","control.capability","control.sock","openvmm.log","runtime.json","sandbox.lock"],"mode":448},"state/config.json":{"text":"{\n \"cmdline\": \"\",\n \"distro_binding\": {\n \"format\": \"erofs\",\n \"identity\": \"11111111-1111-1111-1111-111111111111\",\n \"image\": {\n \"changed\": {\n \"nanoseconds\": {int},\n \"seconds\": {int}\n },\n \"device\": {int},\n \"fileId\": \"{hex32}\",\n \"kind\": \"regular\",\n \"length\": 7,\n \"modified\": {\n \"nanoseconds\": {int},\n \"seconds\": {int}\n },\n \"scheme\": \"linux\",\n \"version\": 1\n },\n \"manifest\": null,\n \"policy\": {\n \"result\": \"accepted\",\n \"revision\": 1\n },\n \"version\": 1\n },\n \"export\": {\n \"binds\": [\n {\n \"child\": 0,\n \"readOnly\": true,\n \"source\": \"\",\n \"target\": \"/data\"\n }\n ],\n \"children\": [\n {\n \"allowed\": [],\n \"denied\": [],\n \"deniedIdentities\": [],\n \"root\": \"{root}/share\",\n \"writable\": false,\n \"write\": []\n }\n ]\n },\n \"format\": 7,\n \"hostname\": \"nvx-sandbox\",\n \"hypervisor\": \"kvm\",\n \"layers\": [\n {\n \"path\": \"{root}/distro.erofs\",\n \"role\": \"distro\",\n \"uuid\": \"11111111-1111-1111-1111-111111111111\"\n }\n ],\n \"memory_max\": null,\n \"memory_mib\": 256,\n \"network\": null,\n \"pids_max\": null,\n \"scratch\": \"{root}/scratch.ext4\",\n \"scratch_binding\": {\n \"device\": {int},\n \"fileId\": \"{hex32}\",\n \"kind\": \"regular\",\n \"length\": 8,\n \"scheme\": \"linux\",\n \"version\": 1\n },\n \"workload_gid\": 65534,\n \"workload_uid\": 65534\n}\n","mode":384},"state/runtime.json":{"text":"{\n \"format\": 4,\n \"launch\": \"{hex32}\",\n \"process\": {\n \"pid\": {int},\n \"startTime\": {int},\n \"boot\": \"{hex32}\"\n },\n \"endpoint\": \"{root}/state/control.sock\",\n \"runtime\": {\n \"openvmm\": \"sha256:1e8c924cdaac227bf74b4a4a9bcdb9e8836a1355fd0408cc81dab5d9aa71eb4d\",\n \"kernel\": \"sha256:a0c936696eb7d5ee3192bf53b9d281cecbb40ca9db520de72cb95817ad92ac72\",\n \"initramfs\": \"sha256:2f77c2c97621e8bf69794e9d12815bb7c46338638f126bea8b18dfe02a684d62\",\n \"bootContract\": 3,\n \"controlContract\": \"nvx-microvm-v2-control-v2\",\n \"controlSession\": 1\n }\n}\n","mode":384},"state/control.capability":{"size":32,"mode":384},"state/outcome.json":null,"state/openvmm.log":{"text":""},"build/fake-openvmm-state.json":{"text":"[\"--machine\",\"microvm\",\"--microvm-sandbox-block\",\"distro:file:/proc/self/fd/{int},ro\",\"--microvm-sandbox-block\",\"scratch:file:/proc/self/fd/{int}\",\"--microvm-workload-identity\",\"65534:65534\",\"--mount-aggregate\",\"/run/nvx/hostfs/root\",\"--mount-child\",\"0,{root}/share,ro\",\"--microvm-lifecycle\",\"managed\",\"--single-process\",\"--hypervisor\",\"kvm\",\"--memory\",\"256M\",\"--kernel\",\"{root}/build/vmlinux\",\"--initrd\",\"{root}/build/initramfs.cpio.gz\",\"--cmdline\",\"nvx_sandbox=1 nvx_layer=distro,0xd0003000,erofs:11111111-1111-1111-1111-111111111111 nvx_scratch=0xd0006000,ext4 nvx_entrypoint=/bin/sh nvx_hostname=nvx-sandbox nvx_maps=1\",\"--virtio-console\",\"none\",\"--microvm-control-console\",\"listen={root}/state/control.sock\",\"--microvm-control-auth-stdin\",\"--microvm-report\",\"{root}/state/outcome.json\"]"},"build/fake-openvmm-state-maps.json":{"text":"[{\"source\":\"0\",\"target\":\"/data\",\"read_only\":true,\"directory\":true}]"}}},{"argv":["sandbox","exec","--state-dir","{root}/state","--entrypoint","/bin/pwd","--cwd","/data"],"status":0,"stdout":"/data\n","stderr":""},{"argv":["sandbox","stop","--state-dir","{root}/state"],"check":["state","state/config.json","state/runtime.json","state/control.capability","state/outcome.json","state/openvmm.log"],"status":0,"stdout":"","stderr":"","files":{"state":{"entries":["config.json","openvmm.log","outcome.json","sandbox.lock"],"mode":448},"state/config.json":{"text":"{\n \"cmdline\": \"\",\n \"distro_binding\": {\n \"format\": \"erofs\",\n \"identity\": \"11111111-1111-1111-1111-111111111111\",\n \"image\": {\n \"changed\": {\n \"nanoseconds\": {int},\n \"seconds\": {int}\n },\n \"device\": {int},\n \"fileId\": \"{hex32}\",\n \"kind\": \"regular\",\n \"length\": 7,\n \"modified\": {\n \"nanoseconds\": {int},\n \"seconds\": {int}\n },\n \"scheme\": \"linux\",\n \"version\": 1\n },\n \"manifest\": null,\n \"policy\": {\n \"result\": \"accepted\",\n \"revision\": 1\n },\n \"version\": 1\n },\n \"export\": {\n \"binds\": [\n {\n \"child\": 0,\n \"readOnly\": true,\n \"source\": \"\",\n \"target\": \"/data\"\n }\n ],\n \"children\": [\n {\n \"allowed\": [],\n \"denied\": [],\n \"deniedIdentities\": [],\n \"root\": \"{root}/share\",\n \"writable\": false,\n \"write\": []\n }\n ]\n },\n \"format\": 7,\n \"hostname\": \"nvx-sandbox\",\n \"hypervisor\": \"kvm\",\n \"layers\": [\n {\n \"path\": \"{root}/distro.erofs\",\n \"role\": \"distro\",\n \"uuid\": \"11111111-1111-1111-1111-111111111111\"\n }\n ],\n \"memory_max\": null,\n \"memory_mib\": 256,\n \"network\": null,\n \"pids_max\": null,\n \"scratch\": \"{root}/scratch.ext4\",\n \"scratch_binding\": {\n \"device\": {int},\n \"fileId\": \"{hex32}\",\n \"kind\": \"regular\",\n \"length\": 8,\n \"scheme\": \"linux\",\n \"version\": 1\n },\n \"workload_gid\": 65534,\n \"workload_uid\": 65534\n}\n","mode":384},"state/runtime.json":null,"state/control.capability":null,"state/outcome.json":{"text":"{\n \"backend\": \"kvm\",\n \"instance_id\": \"{hex32}\",\n \"network_policy\": {\n \"allow_rule_count\": 0,\n \"deny_rule_count\": 0,\n \"host_loopback\": \"none\",\n \"mode\": \"none\",\n \"status\": \"not-requested\",\n \"status_code\": 0\n },\n \"outcome\": {\n \"category\": \"success\",\n \"operation\": \"managed\",\n \"status_code\": 0\n },\n \"schema_version\": 1,\n \"teardown\": {\n \"control_channels_closed\": true,\n \"guest_workload_stopped\": true,\n \"network_released\": true,\n \"openvmm_process_terminated\": true,\n \"temporary_storage_removed\": true,\n \"virtiofs_released\": true,\n \"vm_stopped\": true\n }\n}\n"},"state/openvmm.log":{"text":""}}},{"argv":["sandbox","start","--state-dir","{root}/state"],"check":["state","state/config.json","state/runtime.json","state/control.capability","state/outcome.json","state/openvmm.log"],"status":0,"stdout":"","stderr":"","files":{"state":{"entries":["config.json","control.capability","control.sock","openvmm.log","runtime.json","sandbox.lock"],"mode":448},"state/config.json":{"text":"{\n \"cmdline\": \"\",\n \"distro_binding\": {\n \"format\": \"erofs\",\n \"identity\": \"11111111-1111-1111-1111-111111111111\",\n \"image\": {\n \"changed\": {\n \"nanoseconds\": {int},\n \"seconds\": {int}\n },\n \"device\": {int},\n \"fileId\": \"{hex32}\",\n \"kind\": \"regular\",\n \"length\": 7,\n \"modified\": {\n \"nanoseconds\": {int},\n \"seconds\": {int}\n },\n \"scheme\": \"linux\",\n \"version\": 1\n },\n \"manifest\": null,\n \"policy\": {\n \"result\": \"accepted\",\n \"revision\": 1\n },\n \"version\": 1\n },\n \"export\": {\n \"binds\": [\n {\n \"child\": 0,\n \"readOnly\": true,\n \"source\": \"\",\n \"target\": \"/data\"\n }\n ],\n \"children\": [\n {\n \"allowed\": [],\n \"denied\": [],\n \"deniedIdentities\": [],\n \"root\": \"{root}/share\",\n \"writable\": false,\n \"write\": []\n }\n ]\n },\n \"format\": 7,\n \"hostname\": \"nvx-sandbox\",\n \"hypervisor\": \"kvm\",\n \"layers\": [\n {\n \"path\": \"{root}/distro.erofs\",\n \"role\": \"distro\",\n \"uuid\": \"11111111-1111-1111-1111-111111111111\"\n }\n ],\n \"memory_max\": null,\n \"memory_mib\": 256,\n \"network\": null,\n \"pids_max\": null,\n \"scratch\": \"{root}/scratch.ext4\",\n \"scratch_binding\": {\n \"device\": {int},\n \"fileId\": \"{hex32}\",\n \"kind\": \"regular\",\n \"length\": 8,\n \"scheme\": \"linux\",\n \"version\": 1\n },\n \"workload_gid\": 65534,\n \"workload_uid\": 65534\n}\n","mode":384},"state/runtime.json":{"text":"{\n \"format\": 4,\n \"launch\": \"{hex32}\",\n \"process\": {\n \"pid\": {int},\n \"startTime\": {int},\n \"boot\": \"{hex32}\"\n },\n \"endpoint\": \"{root}/state/control.sock\",\n \"runtime\": {\n \"openvmm\": \"sha256:1e8c924cdaac227bf74b4a4a9bcdb9e8836a1355fd0408cc81dab5d9aa71eb4d\",\n \"kernel\": \"sha256:a0c936696eb7d5ee3192bf53b9d281cecbb40ca9db520de72cb95817ad92ac72\",\n \"initramfs\": \"sha256:2f77c2c97621e8bf69794e9d12815bb7c46338638f126bea8b18dfe02a684d62\",\n \"bootContract\": 3,\n \"controlContract\": \"nvx-microvm-v2-control-v2\",\n \"controlSession\": 1\n }\n}\n","mode":384},"state/control.capability":{"size":32,"mode":384},"state/outcome.json":null,"state/openvmm.log":{"text":""}}},{"argv":["sandbox","stop","--state-dir","{root}/state"],"check":["state","state/config.json","state/runtime.json","state/control.capability","state/outcome.json","state/openvmm.log"],"status":0,"stdout":"","stderr":"","files":{"state":{"entries":["config.json","openvmm.log","outcome.json","sandbox.lock"],"mode":448},"state/config.json":{"text":"{\n \"cmdline\": \"\",\n \"distro_binding\": {\n \"format\": \"erofs\",\n \"identity\": \"11111111-1111-1111-1111-111111111111\",\n \"image\": {\n \"changed\": {\n \"nanoseconds\": {int},\n \"seconds\": {int}\n },\n \"device\": {int},\n \"fileId\": \"{hex32}\",\n \"kind\": \"regular\",\n \"length\": 7,\n \"modified\": {\n \"nanoseconds\": {int},\n \"seconds\": {int}\n },\n \"scheme\": \"linux\",\n \"version\": 1\n },\n \"manifest\": null,\n \"policy\": {\n \"result\": \"accepted\",\n \"revision\": 1\n },\n \"version\": 1\n },\n \"export\": {\n \"binds\": [\n {\n \"child\": 0,\n \"readOnly\": true,\n \"source\": \"\",\n \"target\": \"/data\"\n }\n ],\n \"children\": [\n {\n \"allowed\": [],\n \"denied\": [],\n \"deniedIdentities\": [],\n \"root\": \"{root}/share\",\n \"writable\": false,\n \"write\": []\n }\n ]\n },\n \"format\": 7,\n \"hostname\": \"nvx-sandbox\",\n \"hypervisor\": \"kvm\",\n \"layers\": [\n {\n \"path\": \"{root}/distro.erofs\",\n \"role\": \"distro\",\n \"uuid\": \"11111111-1111-1111-1111-111111111111\"\n }\n ],\n \"memory_max\": null,\n \"memory_mib\": 256,\n \"network\": null,\n \"pids_max\": null,\n \"scratch\": \"{root}/scratch.ext4\",\n \"scratch_binding\": {\n \"device\": {int},\n \"fileId\": \"{hex32}\",\n \"kind\": \"regular\",\n \"length\": 8,\n \"scheme\": \"linux\",\n \"version\": 1\n },\n \"workload_gid\": 65534,\n \"workload_uid\": 65534\n}\n","mode":384},"state/runtime.json":null,"state/control.capability":null,"state/outcome.json":{"text":"{\n \"backend\": \"kvm\",\n \"instance_id\": \"{hex32}\",\n \"network_policy\": {\n \"allow_rule_count\": 0,\n \"deny_rule_count\": 0,\n \"host_loopback\": \"none\",\n \"mode\": \"none\",\n \"status\": \"not-requested\",\n \"status_code\": 0\n },\n \"outcome\": {\n \"category\": \"success\",\n \"operation\": \"managed\",\n \"status_code\": 0\n },\n \"schema_version\": 1,\n \"teardown\": {\n \"control_channels_closed\": true,\n \"guest_workload_stopped\": true,\n \"network_released\": true,\n \"openvmm_process_terminated\": true,\n \"temporary_storage_removed\": true,\n \"virtiofs_released\": true,\n \"vm_stopped\": true\n }\n}\n"},"state/openvmm.log":{"text":""}}},{"argv":["sandbox","deprovision","--state-dir","{root}/state"],"check":["state"],"status":0,"stdout":"","stderr":"","files":{"state":null}}],"interop":true}, +{"name":"lifecycle: caller-owned share","steps":[{"argv":["sandbox","provision","--state-dir","{root}/state","--layer","distro,{root}/distro.erofs,11111111-1111-1111-1111-111111111111","--scratch","{root}/scratch.ext4","--mount","/data,{root}/share,rw","--mount-owner","caller"],"check":["state","state/config.json","state/runtime.json","state/control.capability","state/outcome.json","state/openvmm.log"],"status":0,"stdout":"","stderr":"","files":{"state":{"entries":["config.json","sandbox.lock"],"mode":448},"state/config.json":{"text":"{\n \"cmdline\": \"\",\n \"distro_binding\": {\n \"format\": \"erofs\",\n \"identity\": \"11111111-1111-1111-1111-111111111111\",\n \"image\": {\n \"changed\": {\n \"nanoseconds\": {int},\n \"seconds\": {int}\n },\n \"device\": {int},\n \"fileId\": \"{hex32}\",\n \"kind\": \"regular\",\n \"length\": 7,\n \"modified\": {\n \"nanoseconds\": {int},\n \"seconds\": {int}\n },\n \"scheme\": \"linux\",\n \"version\": 1\n },\n \"manifest\": null,\n \"policy\": {\n \"result\": \"accepted\",\n \"revision\": 1\n },\n \"version\": 1\n },\n \"export\": {\n \"binds\": [\n {\n \"child\": 0,\n \"readOnly\": false,\n \"source\": \"\",\n \"target\": \"/data\"\n }\n ],\n \"children\": [\n {\n \"allowed\": [],\n \"denied\": [],\n \"deniedIdentities\": [],\n \"root\": \"{root}/share\",\n \"writable\": true,\n \"write\": []\n }\n ],\n \"owner\": \"caller\"\n },\n \"format\": 7,\n \"hostname\": \"nvx-sandbox\",\n \"hypervisor\": \"kvm\",\n \"layers\": [\n {\n \"path\": \"{root}/distro.erofs\",\n \"role\": \"distro\",\n \"uuid\": \"11111111-1111-1111-1111-111111111111\"\n }\n ],\n \"memory_max\": null,\n \"memory_mib\": 256,\n \"network\": null,\n \"pids_max\": null,\n \"scratch\": \"{root}/scratch.ext4\",\n \"scratch_binding\": {\n \"device\": {int},\n \"fileId\": \"{hex32}\",\n \"kind\": \"regular\",\n \"length\": 8,\n \"scheme\": \"linux\",\n \"version\": 1\n },\n \"workload_gid\": 65534,\n \"workload_uid\": 65534\n}\n","mode":384},"state/runtime.json":null,"state/control.capability":null,"state/outcome.json":null,"state/openvmm.log":null}},{"argv":["sandbox","start","--state-dir","{root}/state"],"check":["state","state/config.json","state/runtime.json","state/control.capability","state/outcome.json","state/openvmm.log","build/fake-openvmm-state.json","build/fake-openvmm-state-maps.json"],"status":0,"stdout":"","stderr":"","files":{"state":{"entries":["config.json","control.capability","control.sock","openvmm.log","runtime.json","sandbox.lock"],"mode":448},"state/config.json":{"text":"{\n \"cmdline\": \"\",\n \"distro_binding\": {\n \"format\": \"erofs\",\n \"identity\": \"11111111-1111-1111-1111-111111111111\",\n \"image\": {\n \"changed\": {\n \"nanoseconds\": {int},\n \"seconds\": {int}\n },\n \"device\": {int},\n \"fileId\": \"{hex32}\",\n \"kind\": \"regular\",\n \"length\": 7,\n \"modified\": {\n \"nanoseconds\": {int},\n \"seconds\": {int}\n },\n \"scheme\": \"linux\",\n \"version\": 1\n },\n \"manifest\": null,\n \"policy\": {\n \"result\": \"accepted\",\n \"revision\": 1\n },\n \"version\": 1\n },\n \"export\": {\n \"binds\": [\n {\n \"child\": 0,\n \"readOnly\": false,\n \"source\": \"\",\n \"target\": \"/data\"\n }\n ],\n \"children\": [\n {\n \"allowed\": [],\n \"denied\": [],\n \"deniedIdentities\": [],\n \"root\": \"{root}/share\",\n \"writable\": true,\n \"write\": []\n }\n ],\n \"owner\": \"caller\"\n },\n \"format\": 7,\n \"hostname\": \"nvx-sandbox\",\n \"hypervisor\": \"kvm\",\n \"layers\": [\n {\n \"path\": \"{root}/distro.erofs\",\n \"role\": \"distro\",\n \"uuid\": \"11111111-1111-1111-1111-111111111111\"\n }\n ],\n \"memory_max\": null,\n \"memory_mib\": 256,\n \"network\": null,\n \"pids_max\": null,\n \"scratch\": \"{root}/scratch.ext4\",\n \"scratch_binding\": {\n \"device\": {int},\n \"fileId\": \"{hex32}\",\n \"kind\": \"regular\",\n \"length\": 8,\n \"scheme\": \"linux\",\n \"version\": 1\n },\n \"workload_gid\": 65534,\n \"workload_uid\": 65534\n}\n","mode":384},"state/runtime.json":{"text":"{\n \"format\": 4,\n \"launch\": \"{hex32}\",\n \"process\": {\n \"pid\": {int},\n \"startTime\": {int},\n \"boot\": \"{hex32}\"\n },\n \"endpoint\": \"{root}/state/control.sock\",\n \"runtime\": {\n \"openvmm\": \"sha256:1e8c924cdaac227bf74b4a4a9bcdb9e8836a1355fd0408cc81dab5d9aa71eb4d\",\n \"kernel\": \"sha256:a0c936696eb7d5ee3192bf53b9d281cecbb40ca9db520de72cb95817ad92ac72\",\n \"initramfs\": \"sha256:2f77c2c97621e8bf69794e9d12815bb7c46338638f126bea8b18dfe02a684d62\",\n \"bootContract\": 3,\n \"controlContract\": \"nvx-microvm-v2-control-v2\",\n \"controlSession\": 1\n }\n}\n","mode":384},"state/control.capability":{"size":32,"mode":384},"state/outcome.json":null,"state/openvmm.log":{"text":""},"build/fake-openvmm-state.json":{"text":"[\"--machine\",\"microvm\",\"--microvm-sandbox-block\",\"distro:file:/proc/self/fd/{int},ro\",\"--microvm-sandbox-block\",\"scratch:file:/proc/self/fd/{int}\",\"--microvm-workload-identity\",\"65534:65534\",\"--mount-aggregate\",\"/run/nvx/hostfs/root\",\"--mount-child\",\"0,{root}/share,rw\",\"--mount-owner\",\"caller\",\"--microvm-lifecycle\",\"managed\",\"--single-process\",\"--hypervisor\",\"kvm\",\"--memory\",\"256M\",\"--kernel\",\"{root}/build/vmlinux\",\"--initrd\",\"{root}/build/initramfs.cpio.gz\",\"--cmdline\",\"nvx_sandbox=1 nvx_layer=distro,0xd0003000,erofs:11111111-1111-1111-1111-111111111111 nvx_scratch=0xd0006000,ext4 nvx_entrypoint=/bin/sh nvx_hostname=nvx-sandbox nvx_maps=1\",\"--virtio-console\",\"none\",\"--microvm-control-console\",\"listen={root}/state/control.sock\",\"--microvm-control-auth-stdin\",\"--microvm-report\",\"{root}/state/outcome.json\"]"},"build/fake-openvmm-state-maps.json":{"text":"[{\"source\":\"0\",\"target\":\"/data\",\"read_only\":false,\"directory\":true}]"}}},{"argv":["sandbox","stop","--state-dir","{root}/state"],"check":["state","state/config.json","state/runtime.json","state/control.capability","state/outcome.json","state/openvmm.log"],"status":0,"stdout":"","stderr":"","files":{"state":{"entries":["config.json","openvmm.log","outcome.json","sandbox.lock"],"mode":448},"state/config.json":{"text":"{\n \"cmdline\": \"\",\n \"distro_binding\": {\n \"format\": \"erofs\",\n \"identity\": \"11111111-1111-1111-1111-111111111111\",\n \"image\": {\n \"changed\": {\n \"nanoseconds\": {int},\n \"seconds\": {int}\n },\n \"device\": {int},\n \"fileId\": \"{hex32}\",\n \"kind\": \"regular\",\n \"length\": 7,\n \"modified\": {\n \"nanoseconds\": {int},\n \"seconds\": {int}\n },\n \"scheme\": \"linux\",\n \"version\": 1\n },\n \"manifest\": null,\n \"policy\": {\n \"result\": \"accepted\",\n \"revision\": 1\n },\n \"version\": 1\n },\n \"export\": {\n \"binds\": [\n {\n \"child\": 0,\n \"readOnly\": false,\n \"source\": \"\",\n \"target\": \"/data\"\n }\n ],\n \"children\": [\n {\n \"allowed\": [],\n \"denied\": [],\n \"deniedIdentities\": [],\n \"root\": \"{root}/share\",\n \"writable\": true,\n \"write\": []\n }\n ],\n \"owner\": \"caller\"\n },\n \"format\": 7,\n \"hostname\": \"nvx-sandbox\",\n \"hypervisor\": \"kvm\",\n \"layers\": [\n {\n \"path\": \"{root}/distro.erofs\",\n \"role\": \"distro\",\n \"uuid\": \"11111111-1111-1111-1111-111111111111\"\n }\n ],\n \"memory_max\": null,\n \"memory_mib\": 256,\n \"network\": null,\n \"pids_max\": null,\n \"scratch\": \"{root}/scratch.ext4\",\n \"scratch_binding\": {\n \"device\": {int},\n \"fileId\": \"{hex32}\",\n \"kind\": \"regular\",\n \"length\": 8,\n \"scheme\": \"linux\",\n \"version\": 1\n },\n \"workload_gid\": 65534,\n \"workload_uid\": 65534\n}\n","mode":384},"state/runtime.json":null,"state/control.capability":null,"state/outcome.json":{"text":"{\n \"backend\": \"kvm\",\n \"instance_id\": \"{hex32}\",\n \"network_policy\": {\n \"allow_rule_count\": 0,\n \"deny_rule_count\": 0,\n \"host_loopback\": \"none\",\n \"mode\": \"none\",\n \"status\": \"not-requested\",\n \"status_code\": 0\n },\n \"outcome\": {\n \"category\": \"success\",\n \"operation\": \"managed\",\n \"status_code\": 0\n },\n \"schema_version\": 1,\n \"teardown\": {\n \"control_channels_closed\": true,\n \"guest_workload_stopped\": true,\n \"network_released\": true,\n \"openvmm_process_terminated\": true,\n \"temporary_storage_removed\": true,\n \"virtiofs_released\": true,\n \"vm_stopped\": true\n }\n}\n"},"state/openvmm.log":{"text":""}}},{"argv":["sandbox","start","--state-dir","{root}/state"],"check":["state","state/config.json","state/runtime.json","state/control.capability","state/outcome.json","state/openvmm.log"],"status":0,"stdout":"","stderr":"","files":{"state":{"entries":["config.json","control.capability","control.sock","openvmm.log","runtime.json","sandbox.lock"],"mode":448},"state/config.json":{"text":"{\n \"cmdline\": \"\",\n \"distro_binding\": {\n \"format\": \"erofs\",\n \"identity\": \"11111111-1111-1111-1111-111111111111\",\n \"image\": {\n \"changed\": {\n \"nanoseconds\": {int},\n \"seconds\": {int}\n },\n \"device\": {int},\n \"fileId\": \"{hex32}\",\n \"kind\": \"regular\",\n \"length\": 7,\n \"modified\": {\n \"nanoseconds\": {int},\n \"seconds\": {int}\n },\n \"scheme\": \"linux\",\n \"version\": 1\n },\n \"manifest\": null,\n \"policy\": {\n \"result\": \"accepted\",\n \"revision\": 1\n },\n \"version\": 1\n },\n \"export\": {\n \"binds\": [\n {\n \"child\": 0,\n \"readOnly\": false,\n \"source\": \"\",\n \"target\": \"/data\"\n }\n ],\n \"children\": [\n {\n \"allowed\": [],\n \"denied\": [],\n \"deniedIdentities\": [],\n \"root\": \"{root}/share\",\n \"writable\": true,\n \"write\": []\n }\n ],\n \"owner\": \"caller\"\n },\n \"format\": 7,\n \"hostname\": \"nvx-sandbox\",\n \"hypervisor\": \"kvm\",\n \"layers\": [\n {\n \"path\": \"{root}/distro.erofs\",\n \"role\": \"distro\",\n \"uuid\": \"11111111-1111-1111-1111-111111111111\"\n }\n ],\n \"memory_max\": null,\n \"memory_mib\": 256,\n \"network\": null,\n \"pids_max\": null,\n \"scratch\": \"{root}/scratch.ext4\",\n \"scratch_binding\": {\n \"device\": {int},\n \"fileId\": \"{hex32}\",\n \"kind\": \"regular\",\n \"length\": 8,\n \"scheme\": \"linux\",\n \"version\": 1\n },\n \"workload_gid\": 65534,\n \"workload_uid\": 65534\n}\n","mode":384},"state/runtime.json":{"text":"{\n \"format\": 4,\n \"launch\": \"{hex32}\",\n \"process\": {\n \"pid\": {int},\n \"startTime\": {int},\n \"boot\": \"{hex32}\"\n },\n \"endpoint\": \"{root}/state/control.sock\",\n \"runtime\": {\n \"openvmm\": \"sha256:1e8c924cdaac227bf74b4a4a9bcdb9e8836a1355fd0408cc81dab5d9aa71eb4d\",\n \"kernel\": \"sha256:a0c936696eb7d5ee3192bf53b9d281cecbb40ca9db520de72cb95817ad92ac72\",\n \"initramfs\": \"sha256:2f77c2c97621e8bf69794e9d12815bb7c46338638f126bea8b18dfe02a684d62\",\n \"bootContract\": 3,\n \"controlContract\": \"nvx-microvm-v2-control-v2\",\n \"controlSession\": 1\n }\n}\n","mode":384},"state/control.capability":{"size":32,"mode":384},"state/outcome.json":null,"state/openvmm.log":{"text":""}}},{"argv":["sandbox","stop","--state-dir","{root}/state"],"check":["state","state/config.json","state/runtime.json","state/control.capability","state/outcome.json","state/openvmm.log"],"status":0,"stdout":"","stderr":"","files":{"state":{"entries":["config.json","openvmm.log","outcome.json","sandbox.lock"],"mode":448},"state/config.json":{"text":"{\n \"cmdline\": \"\",\n \"distro_binding\": {\n \"format\": \"erofs\",\n \"identity\": \"11111111-1111-1111-1111-111111111111\",\n \"image\": {\n \"changed\": {\n \"nanoseconds\": {int},\n \"seconds\": {int}\n },\n \"device\": {int},\n \"fileId\": \"{hex32}\",\n \"kind\": \"regular\",\n \"length\": 7,\n \"modified\": {\n \"nanoseconds\": {int},\n \"seconds\": {int}\n },\n \"scheme\": \"linux\",\n \"version\": 1\n },\n \"manifest\": null,\n \"policy\": {\n \"result\": \"accepted\",\n \"revision\": 1\n },\n \"version\": 1\n },\n \"export\": {\n \"binds\": [\n {\n \"child\": 0,\n \"readOnly\": false,\n \"source\": \"\",\n \"target\": \"/data\"\n }\n ],\n \"children\": [\n {\n \"allowed\": [],\n \"denied\": [],\n \"deniedIdentities\": [],\n \"root\": \"{root}/share\",\n \"writable\": true,\n \"write\": []\n }\n ],\n \"owner\": \"caller\"\n },\n \"format\": 7,\n \"hostname\": \"nvx-sandbox\",\n \"hypervisor\": \"kvm\",\n \"layers\": [\n {\n \"path\": \"{root}/distro.erofs\",\n \"role\": \"distro\",\n \"uuid\": \"11111111-1111-1111-1111-111111111111\"\n }\n ],\n \"memory_max\": null,\n \"memory_mib\": 256,\n \"network\": null,\n \"pids_max\": null,\n \"scratch\": \"{root}/scratch.ext4\",\n \"scratch_binding\": {\n \"device\": {int},\n \"fileId\": \"{hex32}\",\n \"kind\": \"regular\",\n \"length\": 8,\n \"scheme\": \"linux\",\n \"version\": 1\n },\n \"workload_gid\": 65534,\n \"workload_uid\": 65534\n}\n","mode":384},"state/runtime.json":null,"state/control.capability":null,"state/outcome.json":{"text":"{\n \"backend\": \"kvm\",\n \"instance_id\": \"{hex32}\",\n \"network_policy\": {\n \"allow_rule_count\": 0,\n \"deny_rule_count\": 0,\n \"host_loopback\": \"none\",\n \"mode\": \"none\",\n \"status\": \"not-requested\",\n \"status_code\": 0\n },\n \"outcome\": {\n \"category\": \"success\",\n \"operation\": \"managed\",\n \"status_code\": 0\n },\n \"schema_version\": 1,\n \"teardown\": {\n \"control_channels_closed\": true,\n \"guest_workload_stopped\": true,\n \"network_released\": true,\n \"openvmm_process_terminated\": true,\n \"temporary_storage_removed\": true,\n \"virtiofs_released\": true,\n \"vm_stopped\": true\n }\n}\n"},"state/openvmm.log":{"text":""}}},{"argv":["sandbox","deprovision","--state-dir","{root}/state"],"check":["state"],"status":0,"stdout":"","stderr":"","files":{"state":null}}],"interop":true}, +{"name":"lifecycle: several shares","steps":[{"argv":["sandbox","provision","--state-dir","{root}/state","--layer","distro,{root}/distro.erofs,11111111-1111-1111-1111-111111111111","--scratch","{root}/scratch.ext4","--mount","/data,{root}/share","--mount","/other,{root}/share2,rw"],"check":["state","state/config.json","state/runtime.json","state/control.capability","state/outcome.json","state/openvmm.log"],"status":0,"stdout":"","stderr":"","files":{"state":{"entries":["config.json","sandbox.lock"],"mode":448},"state/config.json":{"text":"{\n \"cmdline\": \"\",\n \"distro_binding\": {\n \"format\": \"erofs\",\n \"identity\": \"11111111-1111-1111-1111-111111111111\",\n \"image\": {\n \"changed\": {\n \"nanoseconds\": {int},\n \"seconds\": {int}\n },\n \"device\": {int},\n \"fileId\": \"{hex32}\",\n \"kind\": \"regular\",\n \"length\": 7,\n \"modified\": {\n \"nanoseconds\": {int},\n \"seconds\": {int}\n },\n \"scheme\": \"linux\",\n \"version\": 1\n },\n \"manifest\": null,\n \"policy\": {\n \"result\": \"accepted\",\n \"revision\": 1\n },\n \"version\": 1\n },\n \"export\": {\n \"binds\": [\n {\n \"child\": 0,\n \"readOnly\": true,\n \"source\": \"\",\n \"target\": \"/data\"\n },\n {\n \"child\": 1,\n \"readOnly\": false,\n \"source\": \"\",\n \"target\": \"/other\"\n }\n ],\n \"children\": [\n {\n \"allowed\": [],\n \"denied\": [],\n \"deniedIdentities\": [],\n \"root\": \"{root}/share\",\n \"writable\": false,\n \"write\": []\n },\n {\n \"allowed\": [],\n \"denied\": [],\n \"deniedIdentities\": [],\n \"root\": \"{root}/share2\",\n \"writable\": true,\n \"write\": []\n }\n ]\n },\n \"format\": 7,\n \"hostname\": \"nvx-sandbox\",\n \"hypervisor\": \"kvm\",\n \"layers\": [\n {\n \"path\": \"{root}/distro.erofs\",\n \"role\": \"distro\",\n \"uuid\": \"11111111-1111-1111-1111-111111111111\"\n }\n ],\n \"memory_max\": null,\n \"memory_mib\": 256,\n \"network\": null,\n \"pids_max\": null,\n \"scratch\": \"{root}/scratch.ext4\",\n \"scratch_binding\": {\n \"device\": {int},\n \"fileId\": \"{hex32}\",\n \"kind\": \"regular\",\n \"length\": 8,\n \"scheme\": \"linux\",\n \"version\": 1\n },\n \"workload_gid\": 65534,\n \"workload_uid\": 65534\n}\n","mode":384},"state/runtime.json":null,"state/control.capability":null,"state/outcome.json":null,"state/openvmm.log":null}},{"argv":["sandbox","start","--state-dir","{root}/state"],"check":["state","state/config.json","state/runtime.json","state/control.capability","state/outcome.json","state/openvmm.log","build/fake-openvmm-state.json","build/fake-openvmm-state-maps.json"],"status":0,"stdout":"","stderr":"","files":{"state":{"entries":["config.json","control.capability","control.sock","openvmm.log","runtime.json","sandbox.lock"],"mode":448},"state/config.json":{"text":"{\n \"cmdline\": \"\",\n \"distro_binding\": {\n \"format\": \"erofs\",\n \"identity\": \"11111111-1111-1111-1111-111111111111\",\n \"image\": {\n \"changed\": {\n \"nanoseconds\": {int},\n \"seconds\": {int}\n },\n \"device\": {int},\n \"fileId\": \"{hex32}\",\n \"kind\": \"regular\",\n \"length\": 7,\n \"modified\": {\n \"nanoseconds\": {int},\n \"seconds\": {int}\n },\n \"scheme\": \"linux\",\n \"version\": 1\n },\n \"manifest\": null,\n \"policy\": {\n \"result\": \"accepted\",\n \"revision\": 1\n },\n \"version\": 1\n },\n \"export\": {\n \"binds\": [\n {\n \"child\": 0,\n \"readOnly\": true,\n \"source\": \"\",\n \"target\": \"/data\"\n },\n {\n \"child\": 1,\n \"readOnly\": false,\n \"source\": \"\",\n \"target\": \"/other\"\n }\n ],\n \"children\": [\n {\n \"allowed\": [],\n \"denied\": [],\n \"deniedIdentities\": [],\n \"root\": \"{root}/share\",\n \"writable\": false,\n \"write\": []\n },\n {\n \"allowed\": [],\n \"denied\": [],\n \"deniedIdentities\": [],\n \"root\": \"{root}/share2\",\n \"writable\": true,\n \"write\": []\n }\n ]\n },\n \"format\": 7,\n \"hostname\": \"nvx-sandbox\",\n \"hypervisor\": \"kvm\",\n \"layers\": [\n {\n \"path\": \"{root}/distro.erofs\",\n \"role\": \"distro\",\n \"uuid\": \"11111111-1111-1111-1111-111111111111\"\n }\n ],\n \"memory_max\": null,\n \"memory_mib\": 256,\n \"network\": null,\n \"pids_max\": null,\n \"scratch\": \"{root}/scratch.ext4\",\n \"scratch_binding\": {\n \"device\": {int},\n \"fileId\": \"{hex32}\",\n \"kind\": \"regular\",\n \"length\": 8,\n \"scheme\": \"linux\",\n \"version\": 1\n },\n \"workload_gid\": 65534,\n \"workload_uid\": 65534\n}\n","mode":384},"state/runtime.json":{"text":"{\n \"format\": 4,\n \"launch\": \"{hex32}\",\n \"process\": {\n \"pid\": {int},\n \"startTime\": {int},\n \"boot\": \"{hex32}\"\n },\n \"endpoint\": \"{root}/state/control.sock\",\n \"runtime\": {\n \"openvmm\": \"sha256:1e8c924cdaac227bf74b4a4a9bcdb9e8836a1355fd0408cc81dab5d9aa71eb4d\",\n \"kernel\": \"sha256:a0c936696eb7d5ee3192bf53b9d281cecbb40ca9db520de72cb95817ad92ac72\",\n \"initramfs\": \"sha256:2f77c2c97621e8bf69794e9d12815bb7c46338638f126bea8b18dfe02a684d62\",\n \"bootContract\": 3,\n \"controlContract\": \"nvx-microvm-v2-control-v2\",\n \"controlSession\": 1\n }\n}\n","mode":384},"state/control.capability":{"size":32,"mode":384},"state/outcome.json":null,"state/openvmm.log":{"text":""},"build/fake-openvmm-state.json":{"text":"[\"--machine\",\"microvm\",\"--microvm-sandbox-block\",\"distro:file:/proc/self/fd/{int},ro\",\"--microvm-sandbox-block\",\"scratch:file:/proc/self/fd/{int}\",\"--microvm-workload-identity\",\"65534:65534\",\"--mount-aggregate\",\"/run/nvx/hostfs/root\",\"--mount-child\",\"0,{root}/share,ro\",\"--mount-child\",\"1,{root}/share2,rw\",\"--microvm-lifecycle\",\"managed\",\"--single-process\",\"--hypervisor\",\"kvm\",\"--memory\",\"256M\",\"--kernel\",\"{root}/build/vmlinux\",\"--initrd\",\"{root}/build/initramfs.cpio.gz\",\"--cmdline\",\"nvx_sandbox=1 nvx_layer=distro,0xd0003000,erofs:11111111-1111-1111-1111-111111111111 nvx_scratch=0xd0006000,ext4 nvx_entrypoint=/bin/sh nvx_hostname=nvx-sandbox nvx_maps=2\",\"--virtio-console\",\"none\",\"--microvm-control-console\",\"listen={root}/state/control.sock\",\"--microvm-control-auth-stdin\",\"--microvm-report\",\"{root}/state/outcome.json\"]"},"build/fake-openvmm-state-maps.json":{"text":"[{\"source\":\"0\",\"target\":\"/data\",\"read_only\":true,\"directory\":true},{\"source\":\"1\",\"target\":\"/other\",\"read_only\":false,\"directory\":true}]"}}},{"argv":["sandbox","exec","--state-dir","{root}/state","--entrypoint","/bin/pwd","--cwd","/other"],"status":0,"stdout":"/other\n","stderr":""},{"argv":["sandbox","stop","--state-dir","{root}/state"],"check":["state","state/config.json","state/runtime.json","state/control.capability","state/outcome.json","state/openvmm.log"],"status":0,"stdout":"","stderr":"","files":{"state":{"entries":["config.json","openvmm.log","outcome.json","sandbox.lock"],"mode":448},"state/config.json":{"text":"{\n \"cmdline\": \"\",\n \"distro_binding\": {\n \"format\": \"erofs\",\n \"identity\": \"11111111-1111-1111-1111-111111111111\",\n \"image\": {\n \"changed\": {\n \"nanoseconds\": {int},\n \"seconds\": {int}\n },\n \"device\": {int},\n \"fileId\": \"{hex32}\",\n \"kind\": \"regular\",\n \"length\": 7,\n \"modified\": {\n \"nanoseconds\": {int},\n \"seconds\": {int}\n },\n \"scheme\": \"linux\",\n \"version\": 1\n },\n \"manifest\": null,\n \"policy\": {\n \"result\": \"accepted\",\n \"revision\": 1\n },\n \"version\": 1\n },\n \"export\": {\n \"binds\": [\n {\n \"child\": 0,\n \"readOnly\": true,\n \"source\": \"\",\n \"target\": \"/data\"\n },\n {\n \"child\": 1,\n \"readOnly\": false,\n \"source\": \"\",\n \"target\": \"/other\"\n }\n ],\n \"children\": [\n {\n \"allowed\": [],\n \"denied\": [],\n \"deniedIdentities\": [],\n \"root\": \"{root}/share\",\n \"writable\": false,\n \"write\": []\n },\n {\n \"allowed\": [],\n \"denied\": [],\n \"deniedIdentities\": [],\n \"root\": \"{root}/share2\",\n \"writable\": true,\n \"write\": []\n }\n ]\n },\n \"format\": 7,\n \"hostname\": \"nvx-sandbox\",\n \"hypervisor\": \"kvm\",\n \"layers\": [\n {\n \"path\": \"{root}/distro.erofs\",\n \"role\": \"distro\",\n \"uuid\": \"11111111-1111-1111-1111-111111111111\"\n }\n ],\n \"memory_max\": null,\n \"memory_mib\": 256,\n \"network\": null,\n \"pids_max\": null,\n \"scratch\": \"{root}/scratch.ext4\",\n \"scratch_binding\": {\n \"device\": {int},\n \"fileId\": \"{hex32}\",\n \"kind\": \"regular\",\n \"length\": 8,\n \"scheme\": \"linux\",\n \"version\": 1\n },\n \"workload_gid\": 65534,\n \"workload_uid\": 65534\n}\n","mode":384},"state/runtime.json":null,"state/control.capability":null,"state/outcome.json":{"text":"{\n \"backend\": \"kvm\",\n \"instance_id\": \"{hex32}\",\n \"network_policy\": {\n \"allow_rule_count\": 0,\n \"deny_rule_count\": 0,\n \"host_loopback\": \"none\",\n \"mode\": \"none\",\n \"status\": \"not-requested\",\n \"status_code\": 0\n },\n \"outcome\": {\n \"category\": \"success\",\n \"operation\": \"managed\",\n \"status_code\": 0\n },\n \"schema_version\": 1,\n \"teardown\": {\n \"control_channels_closed\": true,\n \"guest_workload_stopped\": true,\n \"network_released\": true,\n \"openvmm_process_terminated\": true,\n \"temporary_storage_removed\": true,\n \"virtiofs_released\": true,\n \"vm_stopped\": true\n }\n}\n"},"state/openvmm.log":{"text":""}}},{"argv":["sandbox","start","--state-dir","{root}/state"],"check":["state","state/config.json","state/runtime.json","state/control.capability","state/outcome.json","state/openvmm.log"],"status":0,"stdout":"","stderr":"","files":{"state":{"entries":["config.json","control.capability","control.sock","openvmm.log","runtime.json","sandbox.lock"],"mode":448},"state/config.json":{"text":"{\n \"cmdline\": \"\",\n \"distro_binding\": {\n \"format\": \"erofs\",\n \"identity\": \"11111111-1111-1111-1111-111111111111\",\n \"image\": {\n \"changed\": {\n \"nanoseconds\": {int},\n \"seconds\": {int}\n },\n \"device\": {int},\n \"fileId\": \"{hex32}\",\n \"kind\": \"regular\",\n \"length\": 7,\n \"modified\": {\n \"nanoseconds\": {int},\n \"seconds\": {int}\n },\n \"scheme\": \"linux\",\n \"version\": 1\n },\n \"manifest\": null,\n \"policy\": {\n \"result\": \"accepted\",\n \"revision\": 1\n },\n \"version\": 1\n },\n \"export\": {\n \"binds\": [\n {\n \"child\": 0,\n \"readOnly\": true,\n \"source\": \"\",\n \"target\": \"/data\"\n },\n {\n \"child\": 1,\n \"readOnly\": false,\n \"source\": \"\",\n \"target\": \"/other\"\n }\n ],\n \"children\": [\n {\n \"allowed\": [],\n \"denied\": [],\n \"deniedIdentities\": [],\n \"root\": \"{root}/share\",\n \"writable\": false,\n \"write\": []\n },\n {\n \"allowed\": [],\n \"denied\": [],\n \"deniedIdentities\": [],\n \"root\": \"{root}/share2\",\n \"writable\": true,\n \"write\": []\n }\n ]\n },\n \"format\": 7,\n \"hostname\": \"nvx-sandbox\",\n \"hypervisor\": \"kvm\",\n \"layers\": [\n {\n \"path\": \"{root}/distro.erofs\",\n \"role\": \"distro\",\n \"uuid\": \"11111111-1111-1111-1111-111111111111\"\n }\n ],\n \"memory_max\": null,\n \"memory_mib\": 256,\n \"network\": null,\n \"pids_max\": null,\n \"scratch\": \"{root}/scratch.ext4\",\n \"scratch_binding\": {\n \"device\": {int},\n \"fileId\": \"{hex32}\",\n \"kind\": \"regular\",\n \"length\": 8,\n \"scheme\": \"linux\",\n \"version\": 1\n },\n \"workload_gid\": 65534,\n \"workload_uid\": 65534\n}\n","mode":384},"state/runtime.json":{"text":"{\n \"format\": 4,\n \"launch\": \"{hex32}\",\n \"process\": {\n \"pid\": {int},\n \"startTime\": {int},\n \"boot\": \"{hex32}\"\n },\n \"endpoint\": \"{root}/state/control.sock\",\n \"runtime\": {\n \"openvmm\": \"sha256:1e8c924cdaac227bf74b4a4a9bcdb9e8836a1355fd0408cc81dab5d9aa71eb4d\",\n \"kernel\": \"sha256:a0c936696eb7d5ee3192bf53b9d281cecbb40ca9db520de72cb95817ad92ac72\",\n \"initramfs\": \"sha256:2f77c2c97621e8bf69794e9d12815bb7c46338638f126bea8b18dfe02a684d62\",\n \"bootContract\": 3,\n \"controlContract\": \"nvx-microvm-v2-control-v2\",\n \"controlSession\": 1\n }\n}\n","mode":384},"state/control.capability":{"size":32,"mode":384},"state/outcome.json":null,"state/openvmm.log":{"text":""}}},{"argv":["sandbox","stop","--state-dir","{root}/state"],"check":["state","state/config.json","state/runtime.json","state/control.capability","state/outcome.json","state/openvmm.log"],"status":0,"stdout":"","stderr":"","files":{"state":{"entries":["config.json","openvmm.log","outcome.json","sandbox.lock"],"mode":448},"state/config.json":{"text":"{\n \"cmdline\": \"\",\n \"distro_binding\": {\n \"format\": \"erofs\",\n \"identity\": \"11111111-1111-1111-1111-111111111111\",\n \"image\": {\n \"changed\": {\n \"nanoseconds\": {int},\n \"seconds\": {int}\n },\n \"device\": {int},\n \"fileId\": \"{hex32}\",\n \"kind\": \"regular\",\n \"length\": 7,\n \"modified\": {\n \"nanoseconds\": {int},\n \"seconds\": {int}\n },\n \"scheme\": \"linux\",\n \"version\": 1\n },\n \"manifest\": null,\n \"policy\": {\n \"result\": \"accepted\",\n \"revision\": 1\n },\n \"version\": 1\n },\n \"export\": {\n \"binds\": [\n {\n \"child\": 0,\n \"readOnly\": true,\n \"source\": \"\",\n \"target\": \"/data\"\n },\n {\n \"child\": 1,\n \"readOnly\": false,\n \"source\": \"\",\n \"target\": \"/other\"\n }\n ],\n \"children\": [\n {\n \"allowed\": [],\n \"denied\": [],\n \"deniedIdentities\": [],\n \"root\": \"{root}/share\",\n \"writable\": false,\n \"write\": []\n },\n {\n \"allowed\": [],\n \"denied\": [],\n \"deniedIdentities\": [],\n \"root\": \"{root}/share2\",\n \"writable\": true,\n \"write\": []\n }\n ]\n },\n \"format\": 7,\n \"hostname\": \"nvx-sandbox\",\n \"hypervisor\": \"kvm\",\n \"layers\": [\n {\n \"path\": \"{root}/distro.erofs\",\n \"role\": \"distro\",\n \"uuid\": \"11111111-1111-1111-1111-111111111111\"\n }\n ],\n \"memory_max\": null,\n \"memory_mib\": 256,\n \"network\": null,\n \"pids_max\": null,\n \"scratch\": \"{root}/scratch.ext4\",\n \"scratch_binding\": {\n \"device\": {int},\n \"fileId\": \"{hex32}\",\n \"kind\": \"regular\",\n \"length\": 8,\n \"scheme\": \"linux\",\n \"version\": 1\n },\n \"workload_gid\": 65534,\n \"workload_uid\": 65534\n}\n","mode":384},"state/runtime.json":null,"state/control.capability":null,"state/outcome.json":{"text":"{\n \"backend\": \"kvm\",\n \"instance_id\": \"{hex32}\",\n \"network_policy\": {\n \"allow_rule_count\": 0,\n \"deny_rule_count\": 0,\n \"host_loopback\": \"none\",\n \"mode\": \"none\",\n \"status\": \"not-requested\",\n \"status_code\": 0\n },\n \"outcome\": {\n \"category\": \"success\",\n \"operation\": \"managed\",\n \"status_code\": 0\n },\n \"schema_version\": 1,\n \"teardown\": {\n \"control_channels_closed\": true,\n \"guest_workload_stopped\": true,\n \"network_released\": true,\n \"openvmm_process_terminated\": true,\n \"temporary_storage_removed\": true,\n \"virtiofs_released\": true,\n \"vm_stopped\": true\n }\n}\n"},"state/openvmm.log":{"text":""}}},{"argv":["sandbox","deprovision","--state-dir","{root}/state"],"check":["state"],"status":0,"stdout":"","stderr":"","files":{"state":null}}],"interop":true}, +{"name":"lifecycle: share policies","steps":[{"argv":["sandbox","provision","--state-dir","{root}/state","--layer","distro,{root}/distro.erofs,11111111-1111-1111-1111-111111111111","--scratch","{root}/scratch.ext4","--mount","/data,{root}/share,rw","--mount-deny","{root}/share/hidden","--mount-allow","{root}/share/hidden/shown","--mount-write","{root}/share/writable"],"check":["state","state/config.json","state/runtime.json","state/control.capability","state/outcome.json","state/openvmm.log"],"status":0,"stdout":"","stderr":"","files":{"state":{"entries":["config.json","sandbox.lock"],"mode":448},"state/config.json":{"text":"{\n \"cmdline\": \"\",\n \"distro_binding\": {\n \"format\": \"erofs\",\n \"identity\": \"11111111-1111-1111-1111-111111111111\",\n \"image\": {\n \"changed\": {\n \"nanoseconds\": {int},\n \"seconds\": {int}\n },\n \"device\": {int},\n \"fileId\": \"{hex32}\",\n \"kind\": \"regular\",\n \"length\": 7,\n \"modified\": {\n \"nanoseconds\": {int},\n \"seconds\": {int}\n },\n \"scheme\": \"linux\",\n \"version\": 1\n },\n \"manifest\": null,\n \"policy\": {\n \"result\": \"accepted\",\n \"revision\": 1\n },\n \"version\": 1\n },\n \"export\": {\n \"binds\": [\n {\n \"child\": 0,\n \"readOnly\": false,\n \"source\": \"\",\n \"target\": \"/data\"\n }\n ],\n \"children\": [\n {\n \"allowed\": [\n \"{root}/share/hidden/shown\"\n ],\n \"denied\": [\n \"{root}/share/hidden\"\n ],\n \"deniedIdentities\": [\n null\n ],\n \"root\": \"{root}/share\",\n \"writable\": true,\n \"write\": [\n \"{root}/share/writable\"\n ]\n }\n ]\n },\n \"format\": 7,\n \"hostname\": \"nvx-sandbox\",\n \"hypervisor\": \"kvm\",\n \"layers\": [\n {\n \"path\": \"{root}/distro.erofs\",\n \"role\": \"distro\",\n \"uuid\": \"11111111-1111-1111-1111-111111111111\"\n }\n ],\n \"memory_max\": null,\n \"memory_mib\": 256,\n \"network\": null,\n \"pids_max\": null,\n \"scratch\": \"{root}/scratch.ext4\",\n \"scratch_binding\": {\n \"device\": {int},\n \"fileId\": \"{hex32}\",\n \"kind\": \"regular\",\n \"length\": 8,\n \"scheme\": \"linux\",\n \"version\": 1\n },\n \"workload_gid\": 65534,\n \"workload_uid\": 65534\n}\n","mode":384},"state/runtime.json":null,"state/control.capability":null,"state/outcome.json":null,"state/openvmm.log":null}},{"argv":["sandbox","start","--state-dir","{root}/state"],"check":["state","state/config.json","state/runtime.json","state/control.capability","state/outcome.json","state/openvmm.log","build/fake-openvmm-state.json","build/fake-openvmm-state-maps.json"],"status":0,"stdout":"","stderr":"","files":{"state":{"entries":["config.json","control.capability","control.sock","openvmm.log","runtime.json","sandbox.lock"],"mode":448},"state/config.json":{"text":"{\n \"cmdline\": \"\",\n \"distro_binding\": {\n \"format\": \"erofs\",\n \"identity\": \"11111111-1111-1111-1111-111111111111\",\n \"image\": {\n \"changed\": {\n \"nanoseconds\": {int},\n \"seconds\": {int}\n },\n \"device\": {int},\n \"fileId\": \"{hex32}\",\n \"kind\": \"regular\",\n \"length\": 7,\n \"modified\": {\n \"nanoseconds\": {int},\n \"seconds\": {int}\n },\n \"scheme\": \"linux\",\n \"version\": 1\n },\n \"manifest\": null,\n \"policy\": {\n \"result\": \"accepted\",\n \"revision\": 1\n },\n \"version\": 1\n },\n \"export\": {\n \"binds\": [\n {\n \"child\": 0,\n \"readOnly\": false,\n \"source\": \"\",\n \"target\": \"/data\"\n }\n ],\n \"children\": [\n {\n \"allowed\": [\n \"{root}/share/hidden/shown\"\n ],\n \"denied\": [\n \"{root}/share/hidden\"\n ],\n \"deniedIdentities\": [\n null\n ],\n \"root\": \"{root}/share\",\n \"writable\": true,\n \"write\": [\n \"{root}/share/writable\"\n ]\n }\n ]\n },\n \"format\": 7,\n \"hostname\": \"nvx-sandbox\",\n \"hypervisor\": \"kvm\",\n \"layers\": [\n {\n \"path\": \"{root}/distro.erofs\",\n \"role\": \"distro\",\n \"uuid\": \"11111111-1111-1111-1111-111111111111\"\n }\n ],\n \"memory_max\": null,\n \"memory_mib\": 256,\n \"network\": null,\n \"pids_max\": null,\n \"scratch\": \"{root}/scratch.ext4\",\n \"scratch_binding\": {\n \"device\": {int},\n \"fileId\": \"{hex32}\",\n \"kind\": \"regular\",\n \"length\": 8,\n \"scheme\": \"linux\",\n \"version\": 1\n },\n \"workload_gid\": 65534,\n \"workload_uid\": 65534\n}\n","mode":384},"state/runtime.json":{"text":"{\n \"format\": 4,\n \"launch\": \"{hex32}\",\n \"process\": {\n \"pid\": {int},\n \"startTime\": {int},\n \"boot\": \"{hex32}\"\n },\n \"endpoint\": \"{root}/state/control.sock\",\n \"runtime\": {\n \"openvmm\": \"sha256:1e8c924cdaac227bf74b4a4a9bcdb9e8836a1355fd0408cc81dab5d9aa71eb4d\",\n \"kernel\": \"sha256:a0c936696eb7d5ee3192bf53b9d281cecbb40ca9db520de72cb95817ad92ac72\",\n \"initramfs\": \"sha256:2f77c2c97621e8bf69794e9d12815bb7c46338638f126bea8b18dfe02a684d62\",\n \"bootContract\": 3,\n \"controlContract\": \"nvx-microvm-v2-control-v2\",\n \"controlSession\": 1\n }\n}\n","mode":384},"state/control.capability":{"size":32,"mode":384},"state/outcome.json":null,"state/openvmm.log":{"text":""},"build/fake-openvmm-state.json":{"text":"[\"--machine\",\"microvm\",\"--microvm-sandbox-block\",\"distro:file:/proc/self/fd/{int},ro\",\"--microvm-sandbox-block\",\"scratch:file:/proc/self/fd/{int}\",\"--microvm-workload-identity\",\"65534:65534\",\"--mount-aggregate\",\"/run/nvx/hostfs/root\",\"--mount-child\",\"0,{root}/share,rw\",\"--mount-deny\",\"{root}/share/hidden\",\"--mount-allow\",\"{root}/share/hidden/shown\",\"--mount-write\",\"{root}/share/writable\",\"--microvm-lifecycle\",\"managed\",\"--single-process\",\"--hypervisor\",\"kvm\",\"--memory\",\"256M\",\"--kernel\",\"{root}/build/vmlinux\",\"--initrd\",\"{root}/build/initramfs.cpio.gz\",\"--cmdline\",\"nvx_sandbox=1 nvx_layer=distro,0xd0003000,erofs:11111111-1111-1111-1111-111111111111 nvx_scratch=0xd0006000,ext4 nvx_entrypoint=/bin/sh nvx_hostname=nvx-sandbox nvx_maps=1\",\"--virtio-console\",\"none\",\"--microvm-control-console\",\"listen={root}/state/control.sock\",\"--microvm-control-auth-stdin\",\"--microvm-report\",\"{root}/state/outcome.json\"]"},"build/fake-openvmm-state-maps.json":{"text":"[{\"source\":\"0\",\"target\":\"/data\",\"read_only\":false,\"directory\":true}]"}}},{"argv":["sandbox","stop","--state-dir","{root}/state"],"check":["state","state/config.json","state/runtime.json","state/control.capability","state/outcome.json","state/openvmm.log"],"status":0,"stdout":"","stderr":"","files":{"state":{"entries":["config.json","openvmm.log","outcome.json","sandbox.lock"],"mode":448},"state/config.json":{"text":"{\n \"cmdline\": \"\",\n \"distro_binding\": {\n \"format\": \"erofs\",\n \"identity\": \"11111111-1111-1111-1111-111111111111\",\n \"image\": {\n \"changed\": {\n \"nanoseconds\": {int},\n \"seconds\": {int}\n },\n \"device\": {int},\n \"fileId\": \"{hex32}\",\n \"kind\": \"regular\",\n \"length\": 7,\n \"modified\": {\n \"nanoseconds\": {int},\n \"seconds\": {int}\n },\n \"scheme\": \"linux\",\n \"version\": 1\n },\n \"manifest\": null,\n \"policy\": {\n \"result\": \"accepted\",\n \"revision\": 1\n },\n \"version\": 1\n },\n \"export\": {\n \"binds\": [\n {\n \"child\": 0,\n \"readOnly\": false,\n \"source\": \"\",\n \"target\": \"/data\"\n }\n ],\n \"children\": [\n {\n \"allowed\": [\n \"{root}/share/hidden/shown\"\n ],\n \"denied\": [\n \"{root}/share/hidden\"\n ],\n \"deniedIdentities\": [\n null\n ],\n \"root\": \"{root}/share\",\n \"writable\": true,\n \"write\": [\n \"{root}/share/writable\"\n ]\n }\n ]\n },\n \"format\": 7,\n \"hostname\": \"nvx-sandbox\",\n \"hypervisor\": \"kvm\",\n \"layers\": [\n {\n \"path\": \"{root}/distro.erofs\",\n \"role\": \"distro\",\n \"uuid\": \"11111111-1111-1111-1111-111111111111\"\n }\n ],\n \"memory_max\": null,\n \"memory_mib\": 256,\n \"network\": null,\n \"pids_max\": null,\n \"scratch\": \"{root}/scratch.ext4\",\n \"scratch_binding\": {\n \"device\": {int},\n \"fileId\": \"{hex32}\",\n \"kind\": \"regular\",\n \"length\": 8,\n \"scheme\": \"linux\",\n \"version\": 1\n },\n \"workload_gid\": 65534,\n \"workload_uid\": 65534\n}\n","mode":384},"state/runtime.json":null,"state/control.capability":null,"state/outcome.json":{"text":"{\n \"backend\": \"kvm\",\n \"instance_id\": \"{hex32}\",\n \"network_policy\": {\n \"allow_rule_count\": 0,\n \"deny_rule_count\": 0,\n \"host_loopback\": \"none\",\n \"mode\": \"none\",\n \"status\": \"not-requested\",\n \"status_code\": 0\n },\n \"outcome\": {\n \"category\": \"success\",\n \"operation\": \"managed\",\n \"status_code\": 0\n },\n \"schema_version\": 1,\n \"teardown\": {\n \"control_channels_closed\": true,\n \"guest_workload_stopped\": true,\n \"network_released\": true,\n \"openvmm_process_terminated\": true,\n \"temporary_storage_removed\": true,\n \"virtiofs_released\": true,\n \"vm_stopped\": true\n }\n}\n"},"state/openvmm.log":{"text":""}}},{"argv":["sandbox","start","--state-dir","{root}/state"],"check":["state","state/config.json","state/runtime.json","state/control.capability","state/outcome.json","state/openvmm.log"],"status":0,"stdout":"","stderr":"","files":{"state":{"entries":["config.json","control.capability","control.sock","openvmm.log","runtime.json","sandbox.lock"],"mode":448},"state/config.json":{"text":"{\n \"cmdline\": \"\",\n \"distro_binding\": {\n \"format\": \"erofs\",\n \"identity\": \"11111111-1111-1111-1111-111111111111\",\n \"image\": {\n \"changed\": {\n \"nanoseconds\": {int},\n \"seconds\": {int}\n },\n \"device\": {int},\n \"fileId\": \"{hex32}\",\n \"kind\": \"regular\",\n \"length\": 7,\n \"modified\": {\n \"nanoseconds\": {int},\n \"seconds\": {int}\n },\n \"scheme\": \"linux\",\n \"version\": 1\n },\n \"manifest\": null,\n \"policy\": {\n \"result\": \"accepted\",\n \"revision\": 1\n },\n \"version\": 1\n },\n \"export\": {\n \"binds\": [\n {\n \"child\": 0,\n \"readOnly\": false,\n \"source\": \"\",\n \"target\": \"/data\"\n }\n ],\n \"children\": [\n {\n \"allowed\": [\n \"{root}/share/hidden/shown\"\n ],\n \"denied\": [\n \"{root}/share/hidden\"\n ],\n \"deniedIdentities\": [\n null\n ],\n \"root\": \"{root}/share\",\n \"writable\": true,\n \"write\": [\n \"{root}/share/writable\"\n ]\n }\n ]\n },\n \"format\": 7,\n \"hostname\": \"nvx-sandbox\",\n \"hypervisor\": \"kvm\",\n \"layers\": [\n {\n \"path\": \"{root}/distro.erofs\",\n \"role\": \"distro\",\n \"uuid\": \"11111111-1111-1111-1111-111111111111\"\n }\n ],\n \"memory_max\": null,\n \"memory_mib\": 256,\n \"network\": null,\n \"pids_max\": null,\n \"scratch\": \"{root}/scratch.ext4\",\n \"scratch_binding\": {\n \"device\": {int},\n \"fileId\": \"{hex32}\",\n \"kind\": \"regular\",\n \"length\": 8,\n \"scheme\": \"linux\",\n \"version\": 1\n },\n \"workload_gid\": 65534,\n \"workload_uid\": 65534\n}\n","mode":384},"state/runtime.json":{"text":"{\n \"format\": 4,\n \"launch\": \"{hex32}\",\n \"process\": {\n \"pid\": {int},\n \"startTime\": {int},\n \"boot\": \"{hex32}\"\n },\n \"endpoint\": \"{root}/state/control.sock\",\n \"runtime\": {\n \"openvmm\": \"sha256:1e8c924cdaac227bf74b4a4a9bcdb9e8836a1355fd0408cc81dab5d9aa71eb4d\",\n \"kernel\": \"sha256:a0c936696eb7d5ee3192bf53b9d281cecbb40ca9db520de72cb95817ad92ac72\",\n \"initramfs\": \"sha256:2f77c2c97621e8bf69794e9d12815bb7c46338638f126bea8b18dfe02a684d62\",\n \"bootContract\": 3,\n \"controlContract\": \"nvx-microvm-v2-control-v2\",\n \"controlSession\": 1\n }\n}\n","mode":384},"state/control.capability":{"size":32,"mode":384},"state/outcome.json":null,"state/openvmm.log":{"text":""}}},{"argv":["sandbox","stop","--state-dir","{root}/state"],"check":["state","state/config.json","state/runtime.json","state/control.capability","state/outcome.json","state/openvmm.log"],"status":0,"stdout":"","stderr":"","files":{"state":{"entries":["config.json","openvmm.log","outcome.json","sandbox.lock"],"mode":448},"state/config.json":{"text":"{\n \"cmdline\": \"\",\n \"distro_binding\": {\n \"format\": \"erofs\",\n \"identity\": \"11111111-1111-1111-1111-111111111111\",\n \"image\": {\n \"changed\": {\n \"nanoseconds\": {int},\n \"seconds\": {int}\n },\n \"device\": {int},\n \"fileId\": \"{hex32}\",\n \"kind\": \"regular\",\n \"length\": 7,\n \"modified\": {\n \"nanoseconds\": {int},\n \"seconds\": {int}\n },\n \"scheme\": \"linux\",\n \"version\": 1\n },\n \"manifest\": null,\n \"policy\": {\n \"result\": \"accepted\",\n \"revision\": 1\n },\n \"version\": 1\n },\n \"export\": {\n \"binds\": [\n {\n \"child\": 0,\n \"readOnly\": false,\n \"source\": \"\",\n \"target\": \"/data\"\n }\n ],\n \"children\": [\n {\n \"allowed\": [\n \"{root}/share/hidden/shown\"\n ],\n \"denied\": [\n \"{root}/share/hidden\"\n ],\n \"deniedIdentities\": [\n null\n ],\n \"root\": \"{root}/share\",\n \"writable\": true,\n \"write\": [\n \"{root}/share/writable\"\n ]\n }\n ]\n },\n \"format\": 7,\n \"hostname\": \"nvx-sandbox\",\n \"hypervisor\": \"kvm\",\n \"layers\": [\n {\n \"path\": \"{root}/distro.erofs\",\n \"role\": \"distro\",\n \"uuid\": \"11111111-1111-1111-1111-111111111111\"\n }\n ],\n \"memory_max\": null,\n \"memory_mib\": 256,\n \"network\": null,\n \"pids_max\": null,\n \"scratch\": \"{root}/scratch.ext4\",\n \"scratch_binding\": {\n \"device\": {int},\n \"fileId\": \"{hex32}\",\n \"kind\": \"regular\",\n \"length\": 8,\n \"scheme\": \"linux\",\n \"version\": 1\n },\n \"workload_gid\": 65534,\n \"workload_uid\": 65534\n}\n","mode":384},"state/runtime.json":null,"state/control.capability":null,"state/outcome.json":{"text":"{\n \"backend\": \"kvm\",\n \"instance_id\": \"{hex32}\",\n \"network_policy\": {\n \"allow_rule_count\": 0,\n \"deny_rule_count\": 0,\n \"host_loopback\": \"none\",\n \"mode\": \"none\",\n \"status\": \"not-requested\",\n \"status_code\": 0\n },\n \"outcome\": {\n \"category\": \"success\",\n \"operation\": \"managed\",\n \"status_code\": 0\n },\n \"schema_version\": 1,\n \"teardown\": {\n \"control_channels_closed\": true,\n \"guest_workload_stopped\": true,\n \"network_released\": true,\n \"openvmm_process_terminated\": true,\n \"temporary_storage_removed\": true,\n \"virtiofs_released\": true,\n \"vm_stopped\": true\n }\n}\n"},"state/openvmm.log":{"text":""}}},{"argv":["sandbox","deprovision","--state-dir","{root}/state"],"check":["state"],"status":0,"stdout":"","stderr":"","files":{"state":null}}],"interop":true}, +{"name":"lifecycle: file share","steps":[{"argv":["sandbox","provision","--state-dir","{root}/state","--layer","distro,{root}/distro.erofs,11111111-1111-1111-1111-111111111111","--scratch","{root}/scratch.ext4","--mount","/etc/single.txt,{root}/single.txt,ro"],"check":["state","state/config.json","state/runtime.json","state/control.capability","state/outcome.json","state/openvmm.log"],"status":0,"stdout":"","stderr":"","files":{"state":{"entries":["config.json","sandbox.lock"],"mode":448},"state/config.json":{"text":"{\n \"cmdline\": \"\",\n \"distro_binding\": {\n \"format\": \"erofs\",\n \"identity\": \"11111111-1111-1111-1111-111111111111\",\n \"image\": {\n \"changed\": {\n \"nanoseconds\": {int},\n \"seconds\": {int}\n },\n \"device\": {int},\n \"fileId\": \"{hex32}\",\n \"kind\": \"regular\",\n \"length\": 7,\n \"modified\": {\n \"nanoseconds\": {int},\n \"seconds\": {int}\n },\n \"scheme\": \"linux\",\n \"version\": 1\n },\n \"manifest\": null,\n \"policy\": {\n \"result\": \"accepted\",\n \"revision\": 1\n },\n \"version\": 1\n },\n \"export\": {\n \"binds\": [\n {\n \"child\": 0,\n \"readOnly\": true,\n \"source\": \"\",\n \"target\": \"/etc/single.txt\"\n }\n ],\n \"children\": [\n {\n \"allowed\": [],\n \"denied\": [],\n \"deniedIdentities\": [],\n \"file\": true,\n \"root\": \"{root}/single.txt\",\n \"writable\": false,\n \"write\": []\n }\n ]\n },\n \"format\": 7,\n \"hostname\": \"nvx-sandbox\",\n \"hypervisor\": \"kvm\",\n \"layers\": [\n {\n \"path\": \"{root}/distro.erofs\",\n \"role\": \"distro\",\n \"uuid\": \"11111111-1111-1111-1111-111111111111\"\n }\n ],\n \"memory_max\": null,\n \"memory_mib\": 256,\n \"network\": null,\n \"pids_max\": null,\n \"scratch\": \"{root}/scratch.ext4\",\n \"scratch_binding\": {\n \"device\": {int},\n \"fileId\": \"{hex32}\",\n \"kind\": \"regular\",\n \"length\": 8,\n \"scheme\": \"linux\",\n \"version\": 1\n },\n \"workload_gid\": 65534,\n \"workload_uid\": 65534\n}\n","mode":384},"state/runtime.json":null,"state/control.capability":null,"state/outcome.json":null,"state/openvmm.log":null}},{"argv":["sandbox","start","--state-dir","{root}/state"],"check":["state","state/config.json","state/runtime.json","state/control.capability","state/outcome.json","state/openvmm.log","build/fake-openvmm-state.json","build/fake-openvmm-state-maps.json"],"status":0,"stdout":"","stderr":"","files":{"state":{"entries":["config.json","control.capability","control.sock","openvmm.log","runtime.json","sandbox.lock"],"mode":448},"state/config.json":{"text":"{\n \"cmdline\": \"\",\n \"distro_binding\": {\n \"format\": \"erofs\",\n \"identity\": \"11111111-1111-1111-1111-111111111111\",\n \"image\": {\n \"changed\": {\n \"nanoseconds\": {int},\n \"seconds\": {int}\n },\n \"device\": {int},\n \"fileId\": \"{hex32}\",\n \"kind\": \"regular\",\n \"length\": 7,\n \"modified\": {\n \"nanoseconds\": {int},\n \"seconds\": {int}\n },\n \"scheme\": \"linux\",\n \"version\": 1\n },\n \"manifest\": null,\n \"policy\": {\n \"result\": \"accepted\",\n \"revision\": 1\n },\n \"version\": 1\n },\n \"export\": {\n \"binds\": [\n {\n \"child\": 0,\n \"readOnly\": true,\n \"source\": \"\",\n \"target\": \"/etc/single.txt\"\n }\n ],\n \"children\": [\n {\n \"allowed\": [],\n \"denied\": [],\n \"deniedIdentities\": [],\n \"file\": true,\n \"root\": \"{root}/single.txt\",\n \"writable\": false,\n \"write\": []\n }\n ]\n },\n \"format\": 7,\n \"hostname\": \"nvx-sandbox\",\n \"hypervisor\": \"kvm\",\n \"layers\": [\n {\n \"path\": \"{root}/distro.erofs\",\n \"role\": \"distro\",\n \"uuid\": \"11111111-1111-1111-1111-111111111111\"\n }\n ],\n \"memory_max\": null,\n \"memory_mib\": 256,\n \"network\": null,\n \"pids_max\": null,\n \"scratch\": \"{root}/scratch.ext4\",\n \"scratch_binding\": {\n \"device\": {int},\n \"fileId\": \"{hex32}\",\n \"kind\": \"regular\",\n \"length\": 8,\n \"scheme\": \"linux\",\n \"version\": 1\n },\n \"workload_gid\": 65534,\n \"workload_uid\": 65534\n}\n","mode":384},"state/runtime.json":{"text":"{\n \"format\": 4,\n \"launch\": \"{hex32}\",\n \"process\": {\n \"pid\": {int},\n \"startTime\": {int},\n \"boot\": \"{hex32}\"\n },\n \"endpoint\": \"{root}/state/control.sock\",\n \"runtime\": {\n \"openvmm\": \"sha256:1e8c924cdaac227bf74b4a4a9bcdb9e8836a1355fd0408cc81dab5d9aa71eb4d\",\n \"kernel\": \"sha256:a0c936696eb7d5ee3192bf53b9d281cecbb40ca9db520de72cb95817ad92ac72\",\n \"initramfs\": \"sha256:2f77c2c97621e8bf69794e9d12815bb7c46338638f126bea8b18dfe02a684d62\",\n \"bootContract\": 3,\n \"controlContract\": \"nvx-microvm-v2-control-v2\",\n \"controlSession\": 1\n }\n}\n","mode":384},"state/control.capability":{"size":32,"mode":384},"state/outcome.json":null,"state/openvmm.log":{"text":""},"build/fake-openvmm-state.json":{"text":"[\"--machine\",\"microvm\",\"--microvm-sandbox-block\",\"distro:file:/proc/self/fd/{int},ro\",\"--microvm-sandbox-block\",\"scratch:file:/proc/self/fd/{int}\",\"--microvm-workload-identity\",\"65534:65534\",\"--mount-aggregate\",\"/run/nvx/hostfs/root\",\"--mount-child\",\"0,{root}/single.txt,ro,file\",\"--microvm-lifecycle\",\"managed\",\"--single-process\",\"--hypervisor\",\"kvm\",\"--memory\",\"256M\",\"--kernel\",\"{root}/build/vmlinux\",\"--initrd\",\"{root}/build/initramfs.cpio.gz\",\"--cmdline\",\"nvx_sandbox=1 nvx_layer=distro,0xd0003000,erofs:11111111-1111-1111-1111-111111111111 nvx_scratch=0xd0006000,ext4 nvx_entrypoint=/bin/sh nvx_hostname=nvx-sandbox nvx_maps=1\",\"--virtio-console\",\"none\",\"--microvm-control-console\",\"listen={root}/state/control.sock\",\"--microvm-control-auth-stdin\",\"--microvm-report\",\"{root}/state/outcome.json\"]"},"build/fake-openvmm-state-maps.json":{"text":"[{\"source\":\"0\",\"target\":\"/etc/single.txt\",\"read_only\":true,\"directory\":false}]"}}},{"argv":["sandbox","stop","--state-dir","{root}/state"],"check":["state","state/config.json","state/runtime.json","state/control.capability","state/outcome.json","state/openvmm.log"],"status":0,"stdout":"","stderr":"","files":{"state":{"entries":["config.json","openvmm.log","outcome.json","sandbox.lock"],"mode":448},"state/config.json":{"text":"{\n \"cmdline\": \"\",\n \"distro_binding\": {\n \"format\": \"erofs\",\n \"identity\": \"11111111-1111-1111-1111-111111111111\",\n \"image\": {\n \"changed\": {\n \"nanoseconds\": {int},\n \"seconds\": {int}\n },\n \"device\": {int},\n \"fileId\": \"{hex32}\",\n \"kind\": \"regular\",\n \"length\": 7,\n \"modified\": {\n \"nanoseconds\": {int},\n \"seconds\": {int}\n },\n \"scheme\": \"linux\",\n \"version\": 1\n },\n \"manifest\": null,\n \"policy\": {\n \"result\": \"accepted\",\n \"revision\": 1\n },\n \"version\": 1\n },\n \"export\": {\n \"binds\": [\n {\n \"child\": 0,\n \"readOnly\": true,\n \"source\": \"\",\n \"target\": \"/etc/single.txt\"\n }\n ],\n \"children\": [\n {\n \"allowed\": [],\n \"denied\": [],\n \"deniedIdentities\": [],\n \"file\": true,\n \"root\": \"{root}/single.txt\",\n \"writable\": false,\n \"write\": []\n }\n ]\n },\n \"format\": 7,\n \"hostname\": \"nvx-sandbox\",\n \"hypervisor\": \"kvm\",\n \"layers\": [\n {\n \"path\": \"{root}/distro.erofs\",\n \"role\": \"distro\",\n \"uuid\": \"11111111-1111-1111-1111-111111111111\"\n }\n ],\n \"memory_max\": null,\n \"memory_mib\": 256,\n \"network\": null,\n \"pids_max\": null,\n \"scratch\": \"{root}/scratch.ext4\",\n \"scratch_binding\": {\n \"device\": {int},\n \"fileId\": \"{hex32}\",\n \"kind\": \"regular\",\n \"length\": 8,\n \"scheme\": \"linux\",\n \"version\": 1\n },\n \"workload_gid\": 65534,\n \"workload_uid\": 65534\n}\n","mode":384},"state/runtime.json":null,"state/control.capability":null,"state/outcome.json":{"text":"{\n \"backend\": \"kvm\",\n \"instance_id\": \"{hex32}\",\n \"network_policy\": {\n \"allow_rule_count\": 0,\n \"deny_rule_count\": 0,\n \"host_loopback\": \"none\",\n \"mode\": \"none\",\n \"status\": \"not-requested\",\n \"status_code\": 0\n },\n \"outcome\": {\n \"category\": \"success\",\n \"operation\": \"managed\",\n \"status_code\": 0\n },\n \"schema_version\": 1,\n \"teardown\": {\n \"control_channels_closed\": true,\n \"guest_workload_stopped\": true,\n \"network_released\": true,\n \"openvmm_process_terminated\": true,\n \"temporary_storage_removed\": true,\n \"virtiofs_released\": true,\n \"vm_stopped\": true\n }\n}\n"},"state/openvmm.log":{"text":""}}},{"argv":["sandbox","start","--state-dir","{root}/state"],"check":["state","state/config.json","state/runtime.json","state/control.capability","state/outcome.json","state/openvmm.log"],"status":0,"stdout":"","stderr":"","files":{"state":{"entries":["config.json","control.capability","control.sock","openvmm.log","runtime.json","sandbox.lock"],"mode":448},"state/config.json":{"text":"{\n \"cmdline\": \"\",\n \"distro_binding\": {\n \"format\": \"erofs\",\n \"identity\": \"11111111-1111-1111-1111-111111111111\",\n \"image\": {\n \"changed\": {\n \"nanoseconds\": {int},\n \"seconds\": {int}\n },\n \"device\": {int},\n \"fileId\": \"{hex32}\",\n \"kind\": \"regular\",\n \"length\": 7,\n \"modified\": {\n \"nanoseconds\": {int},\n \"seconds\": {int}\n },\n \"scheme\": \"linux\",\n \"version\": 1\n },\n \"manifest\": null,\n \"policy\": {\n \"result\": \"accepted\",\n \"revision\": 1\n },\n \"version\": 1\n },\n \"export\": {\n \"binds\": [\n {\n \"child\": 0,\n \"readOnly\": true,\n \"source\": \"\",\n \"target\": \"/etc/single.txt\"\n }\n ],\n \"children\": [\n {\n \"allowed\": [],\n \"denied\": [],\n \"deniedIdentities\": [],\n \"file\": true,\n \"root\": \"{root}/single.txt\",\n \"writable\": false,\n \"write\": []\n }\n ]\n },\n \"format\": 7,\n \"hostname\": \"nvx-sandbox\",\n \"hypervisor\": \"kvm\",\n \"layers\": [\n {\n \"path\": \"{root}/distro.erofs\",\n \"role\": \"distro\",\n \"uuid\": \"11111111-1111-1111-1111-111111111111\"\n }\n ],\n \"memory_max\": null,\n \"memory_mib\": 256,\n \"network\": null,\n \"pids_max\": null,\n \"scratch\": \"{root}/scratch.ext4\",\n \"scratch_binding\": {\n \"device\": {int},\n \"fileId\": \"{hex32}\",\n \"kind\": \"regular\",\n \"length\": 8,\n \"scheme\": \"linux\",\n \"version\": 1\n },\n \"workload_gid\": 65534,\n \"workload_uid\": 65534\n}\n","mode":384},"state/runtime.json":{"text":"{\n \"format\": 4,\n \"launch\": \"{hex32}\",\n \"process\": {\n \"pid\": {int},\n \"startTime\": {int},\n \"boot\": \"{hex32}\"\n },\n \"endpoint\": \"{root}/state/control.sock\",\n \"runtime\": {\n \"openvmm\": \"sha256:1e8c924cdaac227bf74b4a4a9bcdb9e8836a1355fd0408cc81dab5d9aa71eb4d\",\n \"kernel\": \"sha256:a0c936696eb7d5ee3192bf53b9d281cecbb40ca9db520de72cb95817ad92ac72\",\n \"initramfs\": \"sha256:2f77c2c97621e8bf69794e9d12815bb7c46338638f126bea8b18dfe02a684d62\",\n \"bootContract\": 3,\n \"controlContract\": \"nvx-microvm-v2-control-v2\",\n \"controlSession\": 1\n }\n}\n","mode":384},"state/control.capability":{"size":32,"mode":384},"state/outcome.json":null,"state/openvmm.log":{"text":""}}},{"argv":["sandbox","stop","--state-dir","{root}/state"],"check":["state","state/config.json","state/runtime.json","state/control.capability","state/outcome.json","state/openvmm.log"],"status":0,"stdout":"","stderr":"","files":{"state":{"entries":["config.json","openvmm.log","outcome.json","sandbox.lock"],"mode":448},"state/config.json":{"text":"{\n \"cmdline\": \"\",\n \"distro_binding\": {\n \"format\": \"erofs\",\n \"identity\": \"11111111-1111-1111-1111-111111111111\",\n \"image\": {\n \"changed\": {\n \"nanoseconds\": {int},\n \"seconds\": {int}\n },\n \"device\": {int},\n \"fileId\": \"{hex32}\",\n \"kind\": \"regular\",\n \"length\": 7,\n \"modified\": {\n \"nanoseconds\": {int},\n \"seconds\": {int}\n },\n \"scheme\": \"linux\",\n \"version\": 1\n },\n \"manifest\": null,\n \"policy\": {\n \"result\": \"accepted\",\n \"revision\": 1\n },\n \"version\": 1\n },\n \"export\": {\n \"binds\": [\n {\n \"child\": 0,\n \"readOnly\": true,\n \"source\": \"\",\n \"target\": \"/etc/single.txt\"\n }\n ],\n \"children\": [\n {\n \"allowed\": [],\n \"denied\": [],\n \"deniedIdentities\": [],\n \"file\": true,\n \"root\": \"{root}/single.txt\",\n \"writable\": false,\n \"write\": []\n }\n ]\n },\n \"format\": 7,\n \"hostname\": \"nvx-sandbox\",\n \"hypervisor\": \"kvm\",\n \"layers\": [\n {\n \"path\": \"{root}/distro.erofs\",\n \"role\": \"distro\",\n \"uuid\": \"11111111-1111-1111-1111-111111111111\"\n }\n ],\n \"memory_max\": null,\n \"memory_mib\": 256,\n \"network\": null,\n \"pids_max\": null,\n \"scratch\": \"{root}/scratch.ext4\",\n \"scratch_binding\": {\n \"device\": {int},\n \"fileId\": \"{hex32}\",\n \"kind\": \"regular\",\n \"length\": 8,\n \"scheme\": \"linux\",\n \"version\": 1\n },\n \"workload_gid\": 65534,\n \"workload_uid\": 65534\n}\n","mode":384},"state/runtime.json":null,"state/control.capability":null,"state/outcome.json":{"text":"{\n \"backend\": \"kvm\",\n \"instance_id\": \"{hex32}\",\n \"network_policy\": {\n \"allow_rule_count\": 0,\n \"deny_rule_count\": 0,\n \"host_loopback\": \"none\",\n \"mode\": \"none\",\n \"status\": \"not-requested\",\n \"status_code\": 0\n },\n \"outcome\": {\n \"category\": \"success\",\n \"operation\": \"managed\",\n \"status_code\": 0\n },\n \"schema_version\": 1,\n \"teardown\": {\n \"control_channels_closed\": true,\n \"guest_workload_stopped\": true,\n \"network_released\": true,\n \"openvmm_process_terminated\": true,\n \"temporary_storage_removed\": true,\n \"virtiofs_released\": true,\n \"vm_stopped\": true\n }\n}\n"},"state/openvmm.log":{"text":""}}},{"argv":["sandbox","deprovision","--state-dir","{root}/state"],"check":["state"],"status":0,"stdout":"","stderr":"","files":{"state":null}}],"interop":true}, {"name":"lifecycle: network and launch options","steps":[{"argv":["sandbox","provision","--state-dir","{root}/state","--layer","distro,{root}/distro.erofs,11111111-1111-1111-1111-111111111111","--scratch","{root}/scratch.ext4","--entrypoint","/bin/server","--arg=--serve","--hostname","worker","--workload-user","1000:1000","--memory-max","268435456","--pids-max","64","--memory-mib","384","--hypervisor","auto","--cmdline","quiet","--net","10.0.0.2/24","--network-profile","portable","--network-egress","allow","--network-ingress","deny","--network-egress-policy-file","{root}/policy.json","--host-loopback","allow","--host-loopback-forward","tcp:18080:8080","--host-loopback-forward","udp:19090:9090"],"write":{"policy.json":"{\"allow\": [{\"cidr\": \"192.0.2.0/24\", \"protocol\": \"tcp\", \"port\": 443}], \"deny\": [{\"cidr\": \"192.0.2.128/25\"}]}"},"check":["state","state/config.json","state/runtime.json","state/control.capability","state/outcome.json","state/openvmm.log"],"status":0,"stdout":"","stderr":"","files":{"state":{"entries":["config.json","sandbox.lock"],"mode":448},"state/config.json":{"mode":384,"text":"{\n \"cmdline\": \"quiet\",\n \"distro_binding\": {\n \"format\": \"erofs\",\n \"identity\": \"11111111-1111-1111-1111-111111111111\",\n \"image\": {\n \"changed\": {\n \"nanoseconds\": {int},\n \"seconds\": {int}\n },\n \"device\": {int},\n \"fileId\": \"{hex32}\",\n \"kind\": \"regular\",\n \"length\": 7,\n \"modified\": {\n \"nanoseconds\": {int},\n \"seconds\": {int}\n },\n \"scheme\": \"linux\",\n \"version\": 1\n },\n \"manifest\": null,\n \"policy\": {\n \"result\": \"accepted\",\n \"revision\": 1\n },\n \"version\": 1\n },\n \"format\": 1,\n \"hostname\": \"worker\",\n \"hypervisor\": \"kvm\",\n \"layers\": [\n {\n \"path\": \"{root}/distro.erofs\",\n \"role\": \"distro\",\n \"uuid\": \"11111111-1111-1111-1111-111111111111\"\n }\n ],\n \"memory_max\": 268435456,\n \"memory_mib\": 384,\n \"mount\": null,\n \"network\": {\n \"allow\": {\n \"name\": \"--network-egress-allow\",\n \"rules\": [\n {\n \"ports\": [\n {\n \"endPort\": null,\n \"port\": 443,\n \"protocol\": \"tcp\"\n }\n ],\n \"to\": [\n {\n \"cidr\": \"192.0.2.0/24\",\n \"except\": []\n }\n ]\n }\n ]\n },\n \"deny\": {\n \"name\": \"--network-egress-deny\",\n \"rules\": [\n {\n \"ports\": [],\n \"to\": [\n {\n \"cidr\": \"192.0.2.128/25\",\n \"except\": []\n }\n ]\n }\n ]\n },\n \"egress\": \"allow\",\n \"guestNetwork\": \"10.0.0.2/24\",\n \"hostLoopback\": \"allow\",\n \"hostLoopbackForwards\": [\n {\n \"guestPort\": 8080,\n \"hostPort\": 18080,\n \"protocol\": \"tcp\"\n },\n {\n \"guestPort\": 9090,\n \"hostPort\": 19090,\n \"protocol\": \"udp\"\n }\n ],\n \"ingress\": \"deny\",\n \"proxy\": null\n },\n \"pids_max\": 64,\n \"scratch\": \"{root}/scratch.ext4\",\n \"scratch_binding\": {\n \"device\": {int},\n \"fileId\": \"{hex32}\",\n \"kind\": \"regular\",\n \"length\": 8,\n \"scheme\": \"linux\",\n \"version\": 1\n },\n \"workload_gid\": 1000,\n \"workload_uid\": 1000\n}\n"},"state/runtime.json":null,"state/control.capability":null,"state/outcome.json":null,"state/openvmm.log":null}},{"argv":["sandbox","start","--state-dir","{root}/state"],"check":["state","state/config.json","state/runtime.json","state/control.capability","state/outcome.json","state/openvmm.log","build/fake-openvmm-state.json"],"status":0,"stdout":"","stderr":"","files":{"state":{"entries":["config.json","control.capability","control.sock","openvmm.log","runtime.json","sandbox.lock"],"mode":448},"state/config.json":{"mode":384,"text":"{\n \"cmdline\": \"quiet\",\n \"distro_binding\": {\n \"format\": \"erofs\",\n \"identity\": \"11111111-1111-1111-1111-111111111111\",\n \"image\": {\n \"changed\": {\n \"nanoseconds\": {int},\n \"seconds\": {int}\n },\n \"device\": {int},\n \"fileId\": \"{hex32}\",\n \"kind\": \"regular\",\n \"length\": 7,\n \"modified\": {\n \"nanoseconds\": {int},\n \"seconds\": {int}\n },\n \"scheme\": \"linux\",\n \"version\": 1\n },\n \"manifest\": null,\n \"policy\": {\n \"result\": \"accepted\",\n \"revision\": 1\n },\n \"version\": 1\n },\n \"format\": 1,\n \"hostname\": \"worker\",\n \"hypervisor\": \"kvm\",\n \"layers\": [\n {\n \"path\": \"{root}/distro.erofs\",\n \"role\": \"distro\",\n \"uuid\": \"11111111-1111-1111-1111-111111111111\"\n }\n ],\n \"memory_max\": 268435456,\n \"memory_mib\": 384,\n \"mount\": null,\n \"network\": {\n \"allow\": {\n \"name\": \"--network-egress-allow\",\n \"rules\": [\n {\n \"ports\": [\n {\n \"endPort\": null,\n \"port\": 443,\n \"protocol\": \"tcp\"\n }\n ],\n \"to\": [\n {\n \"cidr\": \"192.0.2.0/24\",\n \"except\": []\n }\n ]\n }\n ]\n },\n \"deny\": {\n \"name\": \"--network-egress-deny\",\n \"rules\": [\n {\n \"ports\": [],\n \"to\": [\n {\n \"cidr\": \"192.0.2.128/25\",\n \"except\": []\n }\n ]\n }\n ]\n },\n \"egress\": \"allow\",\n \"guestNetwork\": \"10.0.0.2/24\",\n \"hostLoopback\": \"allow\",\n \"hostLoopbackForwards\": [\n {\n \"guestPort\": 8080,\n \"hostPort\": 18080,\n \"protocol\": \"tcp\"\n },\n {\n \"guestPort\": 9090,\n \"hostPort\": 19090,\n \"protocol\": \"udp\"\n }\n ],\n \"ingress\": \"deny\",\n \"proxy\": null\n },\n \"pids_max\": 64,\n \"scratch\": \"{root}/scratch.ext4\",\n \"scratch_binding\": {\n \"device\": {int},\n \"fileId\": \"{hex32}\",\n \"kind\": \"regular\",\n \"length\": 8,\n \"scheme\": \"linux\",\n \"version\": 1\n },\n \"workload_gid\": 1000,\n \"workload_uid\": 1000\n}\n"},"state/runtime.json":{"text":"{\n \"format\": 4,\n \"launch\": \"{hex32}\",\n \"process\": {\n \"pid\": {int},\n \"startTime\": {int},\n \"boot\": \"{hex32}\"\n },\n \"endpoint\": \"{root}/state/control.sock\",\n \"runtime\": {\n \"openvmm\": \"sha256:1e8c924cdaac227bf74b4a4a9bcdb9e8836a1355fd0408cc81dab5d9aa71eb4d\",\n \"kernel\": \"sha256:a0c936696eb7d5ee3192bf53b9d281cecbb40ca9db520de72cb95817ad92ac72\",\n \"initramfs\": \"sha256:2f77c2c97621e8bf69794e9d12815bb7c46338638f126bea8b18dfe02a684d62\",\n \"bootContract\": 3,\n \"controlContract\": \"nvx-microvm-v2-control-v2\",\n \"controlSession\": 1\n }\n}\n","mode":384},"state/control.capability":{"size":32,"mode":384},"state/outcome.json":null,"state/openvmm.log":{"text":""},"build/fake-openvmm-state.json":{"text":"[\"--machine\",\"microvm\",\"--microvm-sandbox-block\",\"distro:file:/proc/self/fd/{int},ro\",\"--microvm-sandbox-block\",\"scratch:file:/proc/self/fd/{int}\",\"--microvm-workload-identity\",\"1000:1000\",\"--net\",\"10.0.0.2/24\",\"--network-profile\",\"portable\",\"--network-egress\",\"allow\",\"--network-ingress\",\"deny\",\"--host-loopback\",\"allow\",\"--network-egress-allow\",\"192.0.2.0/24:tcp:443\",\"--network-egress-deny\",\"192.0.2.128/25\",\"--host-loopback-forward\",\"tcp:18080:8080\",\"--host-loopback-forward\",\"udp:19090:9090\",\"--microvm-lifecycle\",\"managed\",\"--single-process\",\"--hypervisor\",\"kvm\",\"--memory\",\"384M\",\"--kernel\",\"{root}/build/vmlinux\",\"--initrd\",\"{root}/build/initramfs.cpio.gz\",\"--cmdline\",\"quiet nvx_sandbox=1 nvx_layer=distro,0xd0003000,erofs:11111111-1111-1111-1111-111111111111 nvx_scratch=0xd0006000,ext4 nvx_entrypoint=/bin/sh nvx_hostname=worker nvx_memory_max=268435456 nvx_pids_max=65\",\"--virtio-console\",\"none\",\"--microvm-control-console\",\"listen={root}/state/control.sock\",\"--microvm-control-auth-stdin\",\"--microvm-report\",\"{root}/state/outcome.json\"]"}}},{"argv":["sandbox","stop","--state-dir","{root}/state"],"check":["state","state/config.json","state/runtime.json","state/control.capability","state/outcome.json","state/openvmm.log"],"status":0,"stdout":"","stderr":"","files":{"state":{"entries":["config.json","openvmm.log","outcome.json","sandbox.lock"],"mode":448},"state/config.json":{"mode":384,"text":"{\n \"cmdline\": \"quiet\",\n \"distro_binding\": {\n \"format\": \"erofs\",\n \"identity\": \"11111111-1111-1111-1111-111111111111\",\n \"image\": {\n \"changed\": {\n \"nanoseconds\": {int},\n \"seconds\": {int}\n },\n \"device\": {int},\n \"fileId\": \"{hex32}\",\n \"kind\": \"regular\",\n \"length\": 7,\n \"modified\": {\n \"nanoseconds\": {int},\n \"seconds\": {int}\n },\n \"scheme\": \"linux\",\n \"version\": 1\n },\n \"manifest\": null,\n \"policy\": {\n \"result\": \"accepted\",\n \"revision\": 1\n },\n \"version\": 1\n },\n \"format\": 1,\n \"hostname\": \"worker\",\n \"hypervisor\": \"kvm\",\n \"layers\": [\n {\n \"path\": \"{root}/distro.erofs\",\n \"role\": \"distro\",\n \"uuid\": \"11111111-1111-1111-1111-111111111111\"\n }\n ],\n \"memory_max\": 268435456,\n \"memory_mib\": 384,\n \"mount\": null,\n \"network\": {\n \"allow\": {\n \"name\": \"--network-egress-allow\",\n \"rules\": [\n {\n \"ports\": [\n {\n \"endPort\": null,\n \"port\": 443,\n \"protocol\": \"tcp\"\n }\n ],\n \"to\": [\n {\n \"cidr\": \"192.0.2.0/24\",\n \"except\": []\n }\n ]\n }\n ]\n },\n \"deny\": {\n \"name\": \"--network-egress-deny\",\n \"rules\": [\n {\n \"ports\": [],\n \"to\": [\n {\n \"cidr\": \"192.0.2.128/25\",\n \"except\": []\n }\n ]\n }\n ]\n },\n \"egress\": \"allow\",\n \"guestNetwork\": \"10.0.0.2/24\",\n \"hostLoopback\": \"allow\",\n \"hostLoopbackForwards\": [\n {\n \"guestPort\": 8080,\n \"hostPort\": 18080,\n \"protocol\": \"tcp\"\n },\n {\n \"guestPort\": 9090,\n \"hostPort\": 19090,\n \"protocol\": \"udp\"\n }\n ],\n \"ingress\": \"deny\",\n \"proxy\": null\n },\n \"pids_max\": 64,\n \"scratch\": \"{root}/scratch.ext4\",\n \"scratch_binding\": {\n \"device\": {int},\n \"fileId\": \"{hex32}\",\n \"kind\": \"regular\",\n \"length\": 8,\n \"scheme\": \"linux\",\n \"version\": 1\n },\n \"workload_gid\": 1000,\n \"workload_uid\": 1000\n}\n"},"state/runtime.json":null,"state/control.capability":null,"state/outcome.json":{"text":"{\n \"backend\": \"kvm\",\n \"instance_id\": \"{hex32}\",\n \"network_policy\": {\n \"allow_rule_count\": 1,\n \"deny_rule_count\": 1,\n \"host_loopback\": \"allow\",\n \"mode\": \"rules\",\n \"status\": \"applied\",\n \"status_code\": 0\n },\n \"outcome\": {\n \"category\": \"success\",\n \"operation\": \"managed\",\n \"status_code\": 0\n },\n \"schema_version\": 1,\n \"teardown\": {\n \"control_channels_closed\": true,\n \"guest_workload_stopped\": true,\n \"network_released\": true,\n \"openvmm_process_terminated\": true,\n \"temporary_storage_removed\": true,\n \"virtiofs_released\": true,\n \"vm_stopped\": true\n }\n}\n"},"state/openvmm.log":{"text":""}}},{"argv":["sandbox","start","--state-dir","{root}/state"],"check":["state","state/config.json","state/runtime.json","state/control.capability","state/outcome.json","state/openvmm.log"],"status":0,"stdout":"","stderr":"","files":{"state":{"entries":["config.json","control.capability","control.sock","openvmm.log","runtime.json","sandbox.lock"],"mode":448},"state/config.json":{"mode":384,"text":"{\n \"cmdline\": \"quiet\",\n \"distro_binding\": {\n \"format\": \"erofs\",\n \"identity\": \"11111111-1111-1111-1111-111111111111\",\n \"image\": {\n \"changed\": {\n \"nanoseconds\": {int},\n \"seconds\": {int}\n },\n \"device\": {int},\n \"fileId\": \"{hex32}\",\n \"kind\": \"regular\",\n \"length\": 7,\n \"modified\": {\n \"nanoseconds\": {int},\n \"seconds\": {int}\n },\n \"scheme\": \"linux\",\n \"version\": 1\n },\n \"manifest\": null,\n \"policy\": {\n \"result\": \"accepted\",\n \"revision\": 1\n },\n \"version\": 1\n },\n \"format\": 1,\n \"hostname\": \"worker\",\n \"hypervisor\": \"kvm\",\n \"layers\": [\n {\n \"path\": \"{root}/distro.erofs\",\n \"role\": \"distro\",\n \"uuid\": \"11111111-1111-1111-1111-111111111111\"\n }\n ],\n \"memory_max\": 268435456,\n \"memory_mib\": 384,\n \"mount\": null,\n \"network\": {\n \"allow\": {\n \"name\": \"--network-egress-allow\",\n \"rules\": [\n {\n \"ports\": [\n {\n \"endPort\": null,\n \"port\": 443,\n \"protocol\": \"tcp\"\n }\n ],\n \"to\": [\n {\n \"cidr\": \"192.0.2.0/24\",\n \"except\": []\n }\n ]\n }\n ]\n },\n \"deny\": {\n \"name\": \"--network-egress-deny\",\n \"rules\": [\n {\n \"ports\": [],\n \"to\": [\n {\n \"cidr\": \"192.0.2.128/25\",\n \"except\": []\n }\n ]\n }\n ]\n },\n \"egress\": \"allow\",\n \"guestNetwork\": \"10.0.0.2/24\",\n \"hostLoopback\": \"allow\",\n \"hostLoopbackForwards\": [\n {\n \"guestPort\": 8080,\n \"hostPort\": 18080,\n \"protocol\": \"tcp\"\n },\n {\n \"guestPort\": 9090,\n \"hostPort\": 19090,\n \"protocol\": \"udp\"\n }\n ],\n \"ingress\": \"deny\",\n \"proxy\": null\n },\n \"pids_max\": 64,\n \"scratch\": \"{root}/scratch.ext4\",\n \"scratch_binding\": {\n \"device\": {int},\n \"fileId\": \"{hex32}\",\n \"kind\": \"regular\",\n \"length\": 8,\n \"scheme\": \"linux\",\n \"version\": 1\n },\n \"workload_gid\": 1000,\n \"workload_uid\": 1000\n}\n"},"state/runtime.json":{"text":"{\n \"format\": 4,\n \"launch\": \"{hex32}\",\n \"process\": {\n \"pid\": {int},\n \"startTime\": {int},\n \"boot\": \"{hex32}\"\n },\n \"endpoint\": \"{root}/state/control.sock\",\n \"runtime\": {\n \"openvmm\": \"sha256:1e8c924cdaac227bf74b4a4a9bcdb9e8836a1355fd0408cc81dab5d9aa71eb4d\",\n \"kernel\": \"sha256:a0c936696eb7d5ee3192bf53b9d281cecbb40ca9db520de72cb95817ad92ac72\",\n \"initramfs\": \"sha256:2f77c2c97621e8bf69794e9d12815bb7c46338638f126bea8b18dfe02a684d62\",\n \"bootContract\": 3,\n \"controlContract\": \"nvx-microvm-v2-control-v2\",\n \"controlSession\": 1\n }\n}\n","mode":384},"state/control.capability":{"size":32,"mode":384},"state/outcome.json":null,"state/openvmm.log":{"text":""}}},{"argv":["sandbox","stop","--state-dir","{root}/state"],"check":["state","state/config.json","state/runtime.json","state/control.capability","state/outcome.json","state/openvmm.log"],"status":0,"stdout":"","stderr":"","files":{"state":{"entries":["config.json","openvmm.log","outcome.json","sandbox.lock"],"mode":448},"state/config.json":{"mode":384,"text":"{\n \"cmdline\": \"quiet\",\n \"distro_binding\": {\n \"format\": \"erofs\",\n \"identity\": \"11111111-1111-1111-1111-111111111111\",\n \"image\": {\n \"changed\": {\n \"nanoseconds\": {int},\n \"seconds\": {int}\n },\n \"device\": {int},\n \"fileId\": \"{hex32}\",\n \"kind\": \"regular\",\n \"length\": 7,\n \"modified\": {\n \"nanoseconds\": {int},\n \"seconds\": {int}\n },\n \"scheme\": \"linux\",\n \"version\": 1\n },\n \"manifest\": null,\n \"policy\": {\n \"result\": \"accepted\",\n \"revision\": 1\n },\n \"version\": 1\n },\n \"format\": 1,\n \"hostname\": \"worker\",\n \"hypervisor\": \"kvm\",\n \"layers\": [\n {\n \"path\": \"{root}/distro.erofs\",\n \"role\": \"distro\",\n \"uuid\": \"11111111-1111-1111-1111-111111111111\"\n }\n ],\n \"memory_max\": 268435456,\n \"memory_mib\": 384,\n \"mount\": null,\n \"network\": {\n \"allow\": {\n \"name\": \"--network-egress-allow\",\n \"rules\": [\n {\n \"ports\": [\n {\n \"endPort\": null,\n \"port\": 443,\n \"protocol\": \"tcp\"\n }\n ],\n \"to\": [\n {\n \"cidr\": \"192.0.2.0/24\",\n \"except\": []\n }\n ]\n }\n ]\n },\n \"deny\": {\n \"name\": \"--network-egress-deny\",\n \"rules\": [\n {\n \"ports\": [],\n \"to\": [\n {\n \"cidr\": \"192.0.2.128/25\",\n \"except\": []\n }\n ]\n }\n ]\n },\n \"egress\": \"allow\",\n \"guestNetwork\": \"10.0.0.2/24\",\n \"hostLoopback\": \"allow\",\n \"hostLoopbackForwards\": [\n {\n \"guestPort\": 8080,\n \"hostPort\": 18080,\n \"protocol\": \"tcp\"\n },\n {\n \"guestPort\": 9090,\n \"hostPort\": 19090,\n \"protocol\": \"udp\"\n }\n ],\n \"ingress\": \"deny\",\n \"proxy\": null\n },\n \"pids_max\": 64,\n \"scratch\": \"{root}/scratch.ext4\",\n \"scratch_binding\": {\n \"device\": {int},\n \"fileId\": \"{hex32}\",\n \"kind\": \"regular\",\n \"length\": 8,\n \"scheme\": \"linux\",\n \"version\": 1\n },\n \"workload_gid\": 1000,\n \"workload_uid\": 1000\n}\n"},"state/runtime.json":null,"state/control.capability":null,"state/outcome.json":{"text":"{\n \"backend\": \"kvm\",\n \"instance_id\": \"{hex32}\",\n \"network_policy\": {\n \"allow_rule_count\": 1,\n \"deny_rule_count\": 1,\n \"host_loopback\": \"allow\",\n \"mode\": \"rules\",\n \"status\": \"applied\",\n \"status_code\": 0\n },\n \"outcome\": {\n \"category\": \"success\",\n \"operation\": \"managed\",\n \"status_code\": 0\n },\n \"schema_version\": 1,\n \"teardown\": {\n \"control_channels_closed\": true,\n \"guest_workload_stopped\": true,\n \"network_released\": true,\n \"openvmm_process_terminated\": true,\n \"temporary_storage_removed\": true,\n \"virtiofs_released\": true,\n \"vm_stopped\": true\n }\n}\n"},"state/openvmm.log":{"text":""}}},{"argv":["sandbox","deprovision","--state-dir","{root}/state"],"check":["state"],"status":0,"stdout":"","stderr":"","files":{"state":null}}],"interop":true}, {"name":"lifecycle: proxy-only network","steps":[{"argv":["sandbox","provision","--state-dir","{root}/state","--layer","distro,{root}/distro.erofs,11111111-1111-1111-1111-111111111111","--scratch","{root}/scratch.ext4","--net","10.0.0.2/24","--network-profile","portable","--network-egress","deny","--host-loopback","deny","--network-proxy","10.0.0.1:3128"],"check":["state/config.json"],"status":0,"stdout":"","stderr":"","files":{"state/config.json":{"mode":384,"text":"{\n \"cmdline\": \"\",\n \"distro_binding\": {\n \"format\": \"erofs\",\n \"identity\": \"11111111-1111-1111-1111-111111111111\",\n \"image\": {\n \"changed\": {\n \"nanoseconds\": {int},\n \"seconds\": {int}\n },\n \"device\": {int},\n \"fileId\": \"{hex32}\",\n \"kind\": \"regular\",\n \"length\": 7,\n \"modified\": {\n \"nanoseconds\": {int},\n \"seconds\": {int}\n },\n \"scheme\": \"linux\",\n \"version\": 1\n },\n \"manifest\": null,\n \"policy\": {\n \"result\": \"accepted\",\n \"revision\": 1\n },\n \"version\": 1\n },\n \"format\": 1,\n \"hostname\": \"nvx-sandbox\",\n \"hypervisor\": \"kvm\",\n \"layers\": [\n {\n \"path\": \"{root}/distro.erofs\",\n \"role\": \"distro\",\n \"uuid\": \"11111111-1111-1111-1111-111111111111\"\n }\n ],\n \"memory_max\": null,\n \"memory_mib\": 256,\n \"mount\": null,\n \"network\": {\n \"allow\": {\n \"name\": \"--network-egress-allow\",\n \"rules\": []\n },\n \"deny\": {\n \"name\": \"--network-egress-deny\",\n \"rules\": []\n },\n \"egress\": \"deny\",\n \"guestNetwork\": \"10.0.0.2/24\",\n \"hostLoopback\": \"deny\",\n \"hostLoopbackForwards\": [],\n \"ingress\": \"deny\",\n \"proxy\": {\n \"port\": 3128,\n \"scheme\": null\n }\n },\n \"pids_max\": null,\n \"scratch\": \"{root}/scratch.ext4\",\n \"scratch_binding\": {\n \"device\": {int},\n \"fileId\": \"{hex32}\",\n \"kind\": \"regular\",\n \"length\": 8,\n \"scheme\": \"linux\",\n \"version\": 1\n },\n \"workload_gid\": 65534,\n \"workload_uid\": 65534\n}\n"}}},{"argv":["sandbox","start","--state-dir","{root}/state"],"check":["build/fake-openvmm-state.json"],"status":0,"stdout":"","stderr":"","files":{"build/fake-openvmm-state.json":{"text":"[\"--machine\",\"microvm\",\"--microvm-sandbox-block\",\"distro:file:/proc/self/fd/{int},ro\",\"--microvm-sandbox-block\",\"scratch:file:/proc/self/fd/{int}\",\"--microvm-workload-identity\",\"65534:65534\",\"--net\",\"10.0.0.2/24\",\"--network-profile\",\"portable\",\"--network-egress\",\"deny\",\"--network-ingress\",\"deny\",\"--host-loopback\",\"deny\",\"--network-proxy\",\"10.0.0.1:3128\",\"--microvm-lifecycle\",\"managed\",\"--single-process\",\"--hypervisor\",\"kvm\",\"--memory\",\"256M\",\"--kernel\",\"{root}/build/vmlinux\",\"--initrd\",\"{root}/build/initramfs.cpio.gz\",\"--cmdline\",\"nvx_sandbox=1 nvx_layer=distro,0xd0003000,erofs:11111111-1111-1111-1111-111111111111 nvx_scratch=0xd0006000,ext4 nvx_entrypoint=/bin/sh nvx_hostname=nvx-sandbox\",\"--virtio-console\",\"none\",\"--microvm-control-console\",\"listen={root}/state/control.sock\",\"--microvm-control-auth-stdin\",\"--microvm-report\",\"{root}/state/outcome.json\"]"}}},{"argv":["sandbox","stop","--state-dir","{root}/state"],"status":0,"stdout":"","stderr":""},{"argv":["sandbox","deprovision","--state-dir","{root}/state"],"check":["state"],"status":0,"stdout":"","stderr":"","files":{"state":null}}]}, {"name":"state: operations without a sandbox","steps":[{"argv":["sandbox","start","--state-dir","{root}/state"],"status":1,"stdout":"","stderr":"error: sandbox state path is not a plain directory: {root}/state\n"},{"argv":["sandbox","exec","--state-dir","{root}/state"],"status":1,"stdout":"","stderr":"error: sandbox state path is not a plain directory: {root}/state\n"},{"argv":["sandbox","stop","--state-dir","{root}/state"],"status":1,"stdout":"","stderr":"error: sandbox state path is not a plain directory: {root}/state\n"},{"argv":["sandbox","deprovision","--state-dir","{root}/state"],"status":1,"stdout":"","stderr":"error: sandbox state path is not a plain directory: {root}/state\n"}]}, @@ -463,11 +463,11 @@ {"name":"run: missing OpenVMM","steps":[{"argv":["sandbox","run","--layer","distro,{root}\\distro.erofs,11111111-1111-1111-1111-111111111111","--scratch","{root}\\scratch.ext4"],"remove":["openvmm/target/release/openvmm{exe}"],"status":1,"stdout":"","stderr":"error: OpenVMM release binary not found: {root}\\openvmm\\target\\release\\openvmm.exe\r\n"}]}, {"name":"run: missing kernel","steps":[{"argv":["sandbox","run","--layer","distro,{root}\\distro.erofs,11111111-1111-1111-1111-111111111111","--scratch","{root}\\scratch.ext4"],"remove":["build/vmlinux"],"status":1,"stdout":"","stderr":"error: Linux direct kernel not found: {root}\\build\\vmlinux\r\n"}]}, {"name":"run: missing initramfs","steps":[{"argv":["sandbox","run","--layer","distro,{root}\\distro.erofs,11111111-1111-1111-1111-111111111111","--scratch","{root}\\scratch.ext4"],"remove":["build/initramfs.cpio.gz"],"status":1,"stdout":"","stderr":"error: initramfs not found: {root}\\build\\initramfs.cpio.gz\r\n"}]}, -{"name":"lifecycle: minimal","steps":[{"argv":["sandbox","provision","--state-dir","{root}\\state","--layer","distro,{root}\\distro.erofs,11111111-1111-1111-1111-111111111111","--scratch","{root}\\scratch.ext4"],"check":["state","state/config.json","state/runtime.json","state/control.capability","state/outcome.json","state/openvmm.log"],"status":0,"stdout":"","stderr":"","files":{"state":{"entries":["config.json","sandbox.lock"]},"state/config.json":{"text":"{\r\n \"cmdline\": \"\",\r\n \"distro_binding\": {\r\n \"format\": \"erofs\",\r\n \"identity\": \"11111111-1111-1111-1111-111111111111\",\r\n \"image\": {\r\n \"changed\": null,\r\n \"device\": {int},\r\n \"fileId\": \"{hex32}\",\r\n \"kind\": \"regular\",\r\n \"length\": 7,\r\n \"modified\": {\r\n \"nanoseconds\": {int},\r\n \"seconds\": {int}\r\n },\r\n \"scheme\": \"windows\",\r\n \"version\": 1\r\n },\r\n \"manifest\": null,\r\n \"policy\": {\r\n \"result\": \"accepted\",\r\n \"revision\": 1\r\n },\r\n \"version\": 1\r\n },\r\n \"format\": 1,\r\n \"hostname\": \"nvx-sandbox\",\r\n \"hypervisor\": \"whp\",\r\n \"layers\": [\r\n {\r\n \"path\": \"{root_json}\\\\distro.erofs\",\r\n \"role\": \"distro\",\r\n \"uuid\": \"11111111-1111-1111-1111-111111111111\"\r\n }\r\n ],\r\n \"memory_max\": null,\r\n \"memory_mib\": 256,\r\n \"mount\": null,\r\n \"network\": null,\r\n \"pids_max\": null,\r\n \"scratch\": \"{root_json}\\\\scratch.ext4\",\r\n \"scratch_binding\": {\r\n \"device\": {int},\r\n \"fileId\": \"{hex32}\",\r\n \"kind\": \"regular\",\r\n \"length\": 8,\r\n \"scheme\": \"windows\",\r\n \"version\": 1\r\n },\r\n \"workload_gid\": 65534,\r\n \"workload_uid\": 65534\r\n}\r\n"},"state/runtime.json":null,"state/control.capability":null,"state/outcome.json":null,"state/openvmm.log":null}},{"argv":["sandbox","start","--state-dir","{root}\\state"],"check":["state","state/config.json","state/runtime.json","state/control.capability","state/outcome.json","state/openvmm.log","build/fake-openvmm-state.json"],"status":0,"stdout":"","stderr":"","files":{"state":{"entries":["config.json","control.capability","openvmm.log","runtime.json","sandbox.lock"]},"state/config.json":{"text":"{\r\n \"cmdline\": \"\",\r\n \"distro_binding\": {\r\n \"format\": \"erofs\",\r\n \"identity\": \"11111111-1111-1111-1111-111111111111\",\r\n \"image\": {\r\n \"changed\": null,\r\n \"device\": {int},\r\n \"fileId\": \"{hex32}\",\r\n \"kind\": \"regular\",\r\n \"length\": 7,\r\n \"modified\": {\r\n \"nanoseconds\": {int},\r\n \"seconds\": {int}\r\n },\r\n \"scheme\": \"windows\",\r\n \"version\": 1\r\n },\r\n \"manifest\": null,\r\n \"policy\": {\r\n \"result\": \"accepted\",\r\n \"revision\": 1\r\n },\r\n \"version\": 1\r\n },\r\n \"format\": 1,\r\n \"hostname\": \"nvx-sandbox\",\r\n \"hypervisor\": \"whp\",\r\n \"layers\": [\r\n {\r\n \"path\": \"{root_json}\\\\distro.erofs\",\r\n \"role\": \"distro\",\r\n \"uuid\": \"11111111-1111-1111-1111-111111111111\"\r\n }\r\n ],\r\n \"memory_max\": null,\r\n \"memory_mib\": 256,\r\n \"mount\": null,\r\n \"network\": null,\r\n \"pids_max\": null,\r\n \"scratch\": \"{root_json}\\\\scratch.ext4\",\r\n \"scratch_binding\": {\r\n \"device\": {int},\r\n \"fileId\": \"{hex32}\",\r\n \"kind\": \"regular\",\r\n \"length\": 8,\r\n \"scheme\": \"windows\",\r\n \"version\": 1\r\n },\r\n \"workload_gid\": 65534,\r\n \"workload_uid\": 65534\r\n}\r\n"},"state/runtime.json":{"text":"{\n \"format\": 4,\n \"launch\": \"{hex32}\",\n \"process\": {\n \"pid\": {int},\n \"startTime\": {int},\n \"boot\": \"{hex32}\"\n },\n \"endpoint\": \"//./pipe/openvmm-microvm-{hex32}\",\n \"runtime\": {\n \"openvmm\": \"sha256:1e8c924cdaac227bf74b4a4a9bcdb9e8836a1355fd0408cc81dab5d9aa71eb4d\",\n \"kernel\": \"sha256:a0c936696eb7d5ee3192bf53b9d281cecbb40ca9db520de72cb95817ad92ac72\",\n \"initramfs\": \"sha256:2f77c2c97621e8bf69794e9d12815bb7c46338638f126bea8b18dfe02a684d62\",\n \"bootContract\": 3,\n \"controlContract\": \"nvx-microvm-v2-control-v2\",\n \"controlSession\": 1\n }\n}\n"},"state/control.capability":{"size":32},"state/outcome.json":null,"state/openvmm.log":{"text":""},"build/fake-openvmm-state.json":{"text":"[\"--machine\",\"microvm\",\"--microvm-sandbox-block\",\"distro:file:\\\\\\\\?\\\\{root_json}\\\\distro.erofs,ro\",\"--microvm-sandbox-block\",\"scratch:file:\\\\\\\\?\\\\{root_json}\\\\scratch.ext4\",\"--microvm-workload-identity\",\"65534:65534\",\"--microvm-lifecycle\",\"managed\",\"--single-process\",\"--hypervisor\",\"whp\",\"--memory\",\"256M\",\"--kernel\",\"{root_json}\\\\build\\\\vmlinux\",\"--initrd\",\"{root_json}\\\\build\\\\initramfs.cpio.gz\",\"--cmdline\",\"nvx_sandbox=1 nvx_layer=distro,0xd0003000,erofs:11111111-1111-1111-1111-111111111111 nvx_scratch=0xd0006000,ext4 nvx_entrypoint=/bin/sh nvx_hostname=nvx-sandbox\",\"--virtio-console\",\"none\",\"--microvm-control-console\",\"listen=//./pipe/openvmm-microvm-{hex32}\",\"--microvm-control-auth-stdin\",\"--microvm-report\",\"{root_json}\\\\state\\\\outcome.json\"]"}}},{"argv":["sandbox","exec","--state-dir","{root}\\state","--entrypoint","/bin/echo","--arg","hello","--arg","world"],"status":0,"stdout":"hello world\n","stderr":""},{"argv":["sandbox","exec","--state-dir","{root}\\state","--entrypoint","/bin/pwd","--cwd","/tmp"],"status":0,"stdout":"/tmp\n","stderr":""},{"argv":["sandbox","exec","--state-dir","{root}\\state","--entrypoint","/bin/sh","--arg=-c","--arg","echo out; echoerr err; exit 3","--outcome-report","{root}\\reports\\exec.json"],"check":["reports/exec.json"],"status":3,"stdout":"out\n","stderr":"err\n","files":{"reports/exec.json":{"text":"{\n \"operation_id\": \"{hex32}\",\n \"outcome\": {\n \"category\": \"exit\",\n \"operation\": \"exec\",\n \"status_code\": 3\n },\n \"schema_version\": 1\n}\n"}}},{"argv":["sandbox","exec","--state-dir","{root}\\state","--entrypoint","/usr/bin/env","--environment","A=1","--environment","B=two"],"status":0,"stdout":"A=1\nB=two\n","stderr":""},{"argv":["sandbox","exec","--state-dir","{root}\\state","--entrypoint","/usr/bin/printenv","--arg","PATH","--inherit-default-environment","--environment","A=1"],"status":0,"stdout":"/usr/sbin:/usr/bin:/sbin:/bin\n","stderr":""},{"argv":["sandbox","exec","--state-dir","{root}\\state","--entrypoint","/usr/bin/env","--environment-file","{root}\\env.json"],"write":{"env.json":"[\"X=1\", \"Y=two words\"]"},"status":0,"stdout":"X=1\nY=two words\n","stderr":""},{"argv":["sandbox","exec","--state-dir","{root}\\state","--entrypoint","/usr/bin/env","--environment-file","{root}\\empty.json"],"write":{"empty.json":"[]"},"status":0,"stdout":"","stderr":""},{"argv":["sandbox","exec","--state-dir","{root}\\state","--entrypoint","/bin/sh","--arg=-c","--arg","sleep 5000","--exec-timeout-ms","50","--outcome-report","{root}\\reports\\exec-timeout.json"],"check":["reports/exec-timeout.json"],"status":124,"stdout":"","stderr":"","files":{"reports/exec-timeout.json":{"text":"{\n \"operation_id\": \"{hex32}\",\n \"outcome\": {\n \"category\": \"timeout\",\n \"operation\": \"exec\",\n \"status_code\": 124\n },\n \"schema_version\": 1\n}\n"}}},{"argv":["sandbox","exec","--state-dir","{root}\\state","--entrypoint","/bin/sh","--arg=-c","--arg","signal 9"],"status":137,"stdout":"","stderr":""},{"argv":["sandbox","exec","--state-dir","{root}\\state","--entrypoint","/bin/missing"],"status":127,"stdout":"","stderr":"openvmm: /bin/missing: not found\n"},{"argv":["sandbox","exec","--state-dir","{root}\\state","--entrypoint","/bin/pwd","--cwd","/missing"],"status":1,"stdout":"","stderr":"error: managed guest rejected exec (status=2, category=cwd-failed)\r\n"},{"argv":["sandbox","exec","--state-dir","{root}\\state","--entrypoint","/bin/pwd","--cwd","relative"],"status":1,"stdout":"","stderr":"error: managed exec working directory must be an absolute path of at most 4096 bytes\r\n"},{"argv":["sandbox","exec","--state-dir","{root}\\state","--entrypoint","/bin/echo","--outcome-report","{root}\\reports\\exec.json"],"status":1,"stdout":"","stderr":"error: outcome report already exists: {root}\\reports\\exec.json\r\n"},{"argv":["sandbox","exec","--state-dir","{root}\\state","--entrypoint","/bin/echo","--outcome-report","{root}\\missing\\exec.json"],"status":1,"stdout":"","stderr":"error: outcome report parent is not a plain directory: {root}\\missing\r\n"},{"argv":["sandbox","stop","--state-dir","{root}\\state"],"check":["state","state/config.json","state/runtime.json","state/control.capability","state/outcome.json","state/openvmm.log"],"status":0,"stdout":"","stderr":"","files":{"state":{"entries":["config.json","openvmm.log","outcome.json","sandbox.lock"]},"state/config.json":{"text":"{\r\n \"cmdline\": \"\",\r\n \"distro_binding\": {\r\n \"format\": \"erofs\",\r\n \"identity\": \"11111111-1111-1111-1111-111111111111\",\r\n \"image\": {\r\n \"changed\": null,\r\n \"device\": {int},\r\n \"fileId\": \"{hex32}\",\r\n \"kind\": \"regular\",\r\n \"length\": 7,\r\n \"modified\": {\r\n \"nanoseconds\": {int},\r\n \"seconds\": {int}\r\n },\r\n \"scheme\": \"windows\",\r\n \"version\": 1\r\n },\r\n \"manifest\": null,\r\n \"policy\": {\r\n \"result\": \"accepted\",\r\n \"revision\": 1\r\n },\r\n \"version\": 1\r\n },\r\n \"format\": 1,\r\n \"hostname\": \"nvx-sandbox\",\r\n \"hypervisor\": \"whp\",\r\n \"layers\": [\r\n {\r\n \"path\": \"{root_json}\\\\distro.erofs\",\r\n \"role\": \"distro\",\r\n \"uuid\": \"11111111-1111-1111-1111-111111111111\"\r\n }\r\n ],\r\n \"memory_max\": null,\r\n \"memory_mib\": 256,\r\n \"mount\": null,\r\n \"network\": null,\r\n \"pids_max\": null,\r\n \"scratch\": \"{root_json}\\\\scratch.ext4\",\r\n \"scratch_binding\": {\r\n \"device\": {int},\r\n \"fileId\": \"{hex32}\",\r\n \"kind\": \"regular\",\r\n \"length\": 8,\r\n \"scheme\": \"windows\",\r\n \"version\": 1\r\n },\r\n \"workload_gid\": 65534,\r\n \"workload_uid\": 65534\r\n}\r\n"},"state/runtime.json":null,"state/control.capability":null,"state/outcome.json":{"text":"{\n \"backend\": \"whp\",\n \"instance_id\": \"{hex32}\",\n \"network_policy\": {\n \"allow_rule_count\": 0,\n \"deny_rule_count\": 0,\n \"host_loopback\": \"none\",\n \"mode\": \"none\",\n \"status\": \"not-requested\",\n \"status_code\": 0\n },\n \"outcome\": {\n \"category\": \"success\",\n \"operation\": \"managed\",\n \"status_code\": 0\n },\n \"schema_version\": 1,\n \"teardown\": {\n \"control_channels_closed\": true,\n \"guest_workload_stopped\": true,\n \"network_released\": true,\n \"openvmm_process_terminated\": true,\n \"temporary_storage_removed\": true,\n \"virtiofs_released\": true,\n \"vm_stopped\": true\n }\n}\n"},"state/openvmm.log":{"text":""}}},{"argv":["sandbox","start","--state-dir","{root}\\state"],"check":["state","state/config.json","state/runtime.json","state/control.capability","state/outcome.json","state/openvmm.log"],"status":0,"stdout":"","stderr":"","files":{"state":{"entries":["config.json","control.capability","openvmm.log","runtime.json","sandbox.lock"]},"state/config.json":{"text":"{\r\n \"cmdline\": \"\",\r\n \"distro_binding\": {\r\n \"format\": \"erofs\",\r\n \"identity\": \"11111111-1111-1111-1111-111111111111\",\r\n \"image\": {\r\n \"changed\": null,\r\n \"device\": {int},\r\n \"fileId\": \"{hex32}\",\r\n \"kind\": \"regular\",\r\n \"length\": 7,\r\n \"modified\": {\r\n \"nanoseconds\": {int},\r\n \"seconds\": {int}\r\n },\r\n \"scheme\": \"windows\",\r\n \"version\": 1\r\n },\r\n \"manifest\": null,\r\n \"policy\": {\r\n \"result\": \"accepted\",\r\n \"revision\": 1\r\n },\r\n \"version\": 1\r\n },\r\n \"format\": 1,\r\n \"hostname\": \"nvx-sandbox\",\r\n \"hypervisor\": \"whp\",\r\n \"layers\": [\r\n {\r\n \"path\": \"{root_json}\\\\distro.erofs\",\r\n \"role\": \"distro\",\r\n \"uuid\": \"11111111-1111-1111-1111-111111111111\"\r\n }\r\n ],\r\n \"memory_max\": null,\r\n \"memory_mib\": 256,\r\n \"mount\": null,\r\n \"network\": null,\r\n \"pids_max\": null,\r\n \"scratch\": \"{root_json}\\\\scratch.ext4\",\r\n \"scratch_binding\": {\r\n \"device\": {int},\r\n \"fileId\": \"{hex32}\",\r\n \"kind\": \"regular\",\r\n \"length\": 8,\r\n \"scheme\": \"windows\",\r\n \"version\": 1\r\n },\r\n \"workload_gid\": 65534,\r\n \"workload_uid\": 65534\r\n}\r\n"},"state/runtime.json":{"text":"{\n \"format\": 4,\n \"launch\": \"{hex32}\",\n \"process\": {\n \"pid\": {int},\n \"startTime\": {int},\n \"boot\": \"{hex32}\"\n },\n \"endpoint\": \"//./pipe/openvmm-microvm-{hex32}\",\n \"runtime\": {\n \"openvmm\": \"sha256:1e8c924cdaac227bf74b4a4a9bcdb9e8836a1355fd0408cc81dab5d9aa71eb4d\",\n \"kernel\": \"sha256:a0c936696eb7d5ee3192bf53b9d281cecbb40ca9db520de72cb95817ad92ac72\",\n \"initramfs\": \"sha256:2f77c2c97621e8bf69794e9d12815bb7c46338638f126bea8b18dfe02a684d62\",\n \"bootContract\": 3,\n \"controlContract\": \"nvx-microvm-v2-control-v2\",\n \"controlSession\": 1\n }\n}\n"},"state/control.capability":{"size":32},"state/outcome.json":null,"state/openvmm.log":{"text":""}}},{"argv":["sandbox","stop","--state-dir","{root}\\state"],"check":["state","state/config.json","state/runtime.json","state/control.capability","state/outcome.json","state/openvmm.log"],"status":0,"stdout":"","stderr":"","files":{"state":{"entries":["config.json","openvmm.log","outcome.json","sandbox.lock"]},"state/config.json":{"text":"{\r\n \"cmdline\": \"\",\r\n \"distro_binding\": {\r\n \"format\": \"erofs\",\r\n \"identity\": \"11111111-1111-1111-1111-111111111111\",\r\n \"image\": {\r\n \"changed\": null,\r\n \"device\": {int},\r\n \"fileId\": \"{hex32}\",\r\n \"kind\": \"regular\",\r\n \"length\": 7,\r\n \"modified\": {\r\n \"nanoseconds\": {int},\r\n \"seconds\": {int}\r\n },\r\n \"scheme\": \"windows\",\r\n \"version\": 1\r\n },\r\n \"manifest\": null,\r\n \"policy\": {\r\n \"result\": \"accepted\",\r\n \"revision\": 1\r\n },\r\n \"version\": 1\r\n },\r\n \"format\": 1,\r\n \"hostname\": \"nvx-sandbox\",\r\n \"hypervisor\": \"whp\",\r\n \"layers\": [\r\n {\r\n \"path\": \"{root_json}\\\\distro.erofs\",\r\n \"role\": \"distro\",\r\n \"uuid\": \"11111111-1111-1111-1111-111111111111\"\r\n }\r\n ],\r\n \"memory_max\": null,\r\n \"memory_mib\": 256,\r\n \"mount\": null,\r\n \"network\": null,\r\n \"pids_max\": null,\r\n \"scratch\": \"{root_json}\\\\scratch.ext4\",\r\n \"scratch_binding\": {\r\n \"device\": {int},\r\n \"fileId\": \"{hex32}\",\r\n \"kind\": \"regular\",\r\n \"length\": 8,\r\n \"scheme\": \"windows\",\r\n \"version\": 1\r\n },\r\n \"workload_gid\": 65534,\r\n \"workload_uid\": 65534\r\n}\r\n"},"state/runtime.json":null,"state/control.capability":null,"state/outcome.json":{"text":"{\n \"backend\": \"whp\",\n \"instance_id\": \"{hex32}\",\n \"network_policy\": {\n \"allow_rule_count\": 0,\n \"deny_rule_count\": 0,\n \"host_loopback\": \"none\",\n \"mode\": \"none\",\n \"status\": \"not-requested\",\n \"status_code\": 0\n },\n \"outcome\": {\n \"category\": \"success\",\n \"operation\": \"managed\",\n \"status_code\": 0\n },\n \"schema_version\": 1,\n \"teardown\": {\n \"control_channels_closed\": true,\n \"guest_workload_stopped\": true,\n \"network_released\": true,\n \"openvmm_process_terminated\": true,\n \"temporary_storage_removed\": true,\n \"virtiofs_released\": true,\n \"vm_stopped\": true\n }\n}\n"},"state/openvmm.log":{"text":""}}},{"argv":["sandbox","deprovision","--state-dir","{root}\\state"],"check":["state"],"status":0,"stdout":"","stderr":"","files":{"state":null}}],"interop":true}, -{"name":"lifecycle: one share","steps":[{"argv":["sandbox","provision","--state-dir","{root}\\state","--layer","distro,{root}\\distro.erofs,11111111-1111-1111-1111-111111111111","--scratch","{root}\\scratch.ext4","--mount","/data,{root}\\share"],"check":["state","state/config.json","state/runtime.json","state/control.capability","state/outcome.json","state/openvmm.log"],"status":0,"stdout":"","stderr":"","files":{"state":{"entries":["config.json","sandbox.lock"]},"state/config.json":{"text":"{\r\n \"cmdline\": \"\",\r\n \"distro_binding\": {\r\n \"format\": \"erofs\",\r\n \"identity\": \"11111111-1111-1111-1111-111111111111\",\r\n \"image\": {\r\n \"changed\": null,\r\n \"device\": {int},\r\n \"fileId\": \"{hex32}\",\r\n \"kind\": \"regular\",\r\n \"length\": 7,\r\n \"modified\": {\r\n \"nanoseconds\": {int},\r\n \"seconds\": {int}\r\n },\r\n \"scheme\": \"windows\",\r\n \"version\": 1\r\n },\r\n \"manifest\": null,\r\n \"policy\": {\r\n \"result\": \"accepted\",\r\n \"revision\": 1\r\n },\r\n \"version\": 1\r\n },\r\n \"export\": {\r\n \"binds\": [\r\n {\r\n \"child\": 0,\r\n \"readOnly\": true,\r\n \"source\": \"\",\r\n \"target\": \"/data\"\r\n }\r\n ],\r\n \"children\": [\r\n {\r\n \"allowed\": [],\r\n \"denied\": [],\r\n \"deniedIdentities\": [],\r\n \"root\": \"{root_json}\\\\share\",\r\n \"writable\": false,\r\n \"write\": []\r\n }\r\n ]\r\n },\r\n \"format\": 7,\r\n \"hostname\": \"nvx-sandbox\",\r\n \"hypervisor\": \"whp\",\r\n \"layers\": [\r\n {\r\n \"path\": \"{root_json}\\\\distro.erofs\",\r\n \"role\": \"distro\",\r\n \"uuid\": \"11111111-1111-1111-1111-111111111111\"\r\n }\r\n ],\r\n \"memory_max\": null,\r\n \"memory_mib\": 256,\r\n \"network\": null,\r\n \"pids_max\": null,\r\n \"scratch\": \"{root_json}\\\\scratch.ext4\",\r\n \"scratch_binding\": {\r\n \"device\": {int},\r\n \"fileId\": \"{hex32}\",\r\n \"kind\": \"regular\",\r\n \"length\": 8,\r\n \"scheme\": \"windows\",\r\n \"version\": 1\r\n },\r\n \"workload_gid\": 65534,\r\n \"workload_uid\": 65534\r\n}\r\n"},"state/runtime.json":null,"state/control.capability":null,"state/outcome.json":null,"state/openvmm.log":null}},{"argv":["sandbox","start","--state-dir","{root}\\state"],"check":["state","state/config.json","state/runtime.json","state/control.capability","state/outcome.json","state/openvmm.log","build/fake-openvmm-state.json"],"status":0,"stdout":"","stderr":"","files":{"state":{"entries":["config.json","control.capability","openvmm.log","runtime.json","sandbox.lock"]},"state/config.json":{"text":"{\r\n \"cmdline\": \"\",\r\n \"distro_binding\": {\r\n \"format\": \"erofs\",\r\n \"identity\": \"11111111-1111-1111-1111-111111111111\",\r\n \"image\": {\r\n \"changed\": null,\r\n \"device\": {int},\r\n \"fileId\": \"{hex32}\",\r\n \"kind\": \"regular\",\r\n \"length\": 7,\r\n \"modified\": {\r\n \"nanoseconds\": {int},\r\n \"seconds\": {int}\r\n },\r\n \"scheme\": \"windows\",\r\n \"version\": 1\r\n },\r\n \"manifest\": null,\r\n \"policy\": {\r\n \"result\": \"accepted\",\r\n \"revision\": 1\r\n },\r\n \"version\": 1\r\n },\r\n \"export\": {\r\n \"binds\": [\r\n {\r\n \"child\": 0,\r\n \"readOnly\": true,\r\n \"source\": \"\",\r\n \"target\": \"/data\"\r\n }\r\n ],\r\n \"children\": [\r\n {\r\n \"allowed\": [],\r\n \"denied\": [],\r\n \"deniedIdentities\": [],\r\n \"root\": \"{root_json}\\\\share\",\r\n \"writable\": false,\r\n \"write\": []\r\n }\r\n ]\r\n },\r\n \"format\": 7,\r\n \"hostname\": \"nvx-sandbox\",\r\n \"hypervisor\": \"whp\",\r\n \"layers\": [\r\n {\r\n \"path\": \"{root_json}\\\\distro.erofs\",\r\n \"role\": \"distro\",\r\n \"uuid\": \"11111111-1111-1111-1111-111111111111\"\r\n }\r\n ],\r\n \"memory_max\": null,\r\n \"memory_mib\": 256,\r\n \"network\": null,\r\n \"pids_max\": null,\r\n \"scratch\": \"{root_json}\\\\scratch.ext4\",\r\n \"scratch_binding\": {\r\n \"device\": {int},\r\n \"fileId\": \"{hex32}\",\r\n \"kind\": \"regular\",\r\n \"length\": 8,\r\n \"scheme\": \"windows\",\r\n \"version\": 1\r\n },\r\n \"workload_gid\": 65534,\r\n \"workload_uid\": 65534\r\n}\r\n"},"state/runtime.json":{"text":"{\n \"format\": 4,\n \"launch\": \"{hex32}\",\n \"process\": {\n \"pid\": {int},\n \"startTime\": {int},\n \"boot\": \"{hex32}\"\n },\n \"endpoint\": \"//./pipe/openvmm-microvm-{hex32}\",\n \"runtime\": {\n \"openvmm\": \"sha256:1e8c924cdaac227bf74b4a4a9bcdb9e8836a1355fd0408cc81dab5d9aa71eb4d\",\n \"kernel\": \"sha256:a0c936696eb7d5ee3192bf53b9d281cecbb40ca9db520de72cb95817ad92ac72\",\n \"initramfs\": \"sha256:2f77c2c97621e8bf69794e9d12815bb7c46338638f126bea8b18dfe02a684d62\",\n \"bootContract\": 3,\n \"controlContract\": \"nvx-microvm-v2-control-v2\",\n \"controlSession\": 1\n }\n}\n"},"state/control.capability":{"size":32},"state/outcome.json":null,"state/openvmm.log":{"text":""},"build/fake-openvmm-state.json":{"text":"[\"--machine\",\"microvm\",\"--microvm-sandbox-block\",\"distro:file:\\\\\\\\?\\\\{root_json}\\\\distro.erofs,ro\",\"--microvm-sandbox-block\",\"scratch:file:\\\\\\\\?\\\\{root_json}\\\\scratch.ext4\",\"--microvm-workload-identity\",\"65534:65534\",\"--mount\",\"/data,{root_json}\\\\share,ro\",\"--microvm-lifecycle\",\"managed\",\"--single-process\",\"--hypervisor\",\"whp\",\"--memory\",\"256M\",\"--kernel\",\"{root_json}\\\\build\\\\vmlinux\",\"--initrd\",\"{root_json}\\\\build\\\\initramfs.cpio.gz\",\"--cmdline\",\"nvx_sandbox=1 nvx_layer=distro,0xd0003000,erofs:11111111-1111-1111-1111-111111111111 nvx_scratch=0xd0006000,ext4 nvx_entrypoint=/bin/sh nvx_hostname=nvx-sandbox\",\"--virtio-console\",\"none\",\"--microvm-control-console\",\"listen=//./pipe/openvmm-microvm-{hex32}\",\"--microvm-control-auth-stdin\",\"--microvm-report\",\"{root_json}\\\\state\\\\outcome.json\"]"}}},{"argv":["sandbox","exec","--state-dir","{root}\\state","--entrypoint","/bin/pwd","--cwd","/data"],"status":0,"stdout":"/data\n","stderr":""},{"argv":["sandbox","stop","--state-dir","{root}\\state"],"check":["state","state/config.json","state/runtime.json","state/control.capability","state/outcome.json","state/openvmm.log"],"status":0,"stdout":"","stderr":"","files":{"state":{"entries":["config.json","openvmm.log","outcome.json","sandbox.lock"]},"state/config.json":{"text":"{\r\n \"cmdline\": \"\",\r\n \"distro_binding\": {\r\n \"format\": \"erofs\",\r\n \"identity\": \"11111111-1111-1111-1111-111111111111\",\r\n \"image\": {\r\n \"changed\": null,\r\n \"device\": {int},\r\n \"fileId\": \"{hex32}\",\r\n \"kind\": \"regular\",\r\n \"length\": 7,\r\n \"modified\": {\r\n \"nanoseconds\": {int},\r\n \"seconds\": {int}\r\n },\r\n \"scheme\": \"windows\",\r\n \"version\": 1\r\n },\r\n \"manifest\": null,\r\n \"policy\": {\r\n \"result\": \"accepted\",\r\n \"revision\": 1\r\n },\r\n \"version\": 1\r\n },\r\n \"export\": {\r\n \"binds\": [\r\n {\r\n \"child\": 0,\r\n \"readOnly\": true,\r\n \"source\": \"\",\r\n \"target\": \"/data\"\r\n }\r\n ],\r\n \"children\": [\r\n {\r\n \"allowed\": [],\r\n \"denied\": [],\r\n \"deniedIdentities\": [],\r\n \"root\": \"{root_json}\\\\share\",\r\n \"writable\": false,\r\n \"write\": []\r\n }\r\n ]\r\n },\r\n \"format\": 7,\r\n \"hostname\": \"nvx-sandbox\",\r\n \"hypervisor\": \"whp\",\r\n \"layers\": [\r\n {\r\n \"path\": \"{root_json}\\\\distro.erofs\",\r\n \"role\": \"distro\",\r\n \"uuid\": \"11111111-1111-1111-1111-111111111111\"\r\n }\r\n ],\r\n \"memory_max\": null,\r\n \"memory_mib\": 256,\r\n \"network\": null,\r\n \"pids_max\": null,\r\n \"scratch\": \"{root_json}\\\\scratch.ext4\",\r\n \"scratch_binding\": {\r\n \"device\": {int},\r\n \"fileId\": \"{hex32}\",\r\n \"kind\": \"regular\",\r\n \"length\": 8,\r\n \"scheme\": \"windows\",\r\n \"version\": 1\r\n },\r\n \"workload_gid\": 65534,\r\n \"workload_uid\": 65534\r\n}\r\n"},"state/runtime.json":null,"state/control.capability":null,"state/outcome.json":{"text":"{\n \"backend\": \"whp\",\n \"instance_id\": \"{hex32}\",\n \"network_policy\": {\n \"allow_rule_count\": 0,\n \"deny_rule_count\": 0,\n \"host_loopback\": \"none\",\n \"mode\": \"none\",\n \"status\": \"not-requested\",\n \"status_code\": 0\n },\n \"outcome\": {\n \"category\": \"success\",\n \"operation\": \"managed\",\n \"status_code\": 0\n },\n \"schema_version\": 1,\n \"teardown\": {\n \"control_channels_closed\": true,\n \"guest_workload_stopped\": true,\n \"network_released\": true,\n \"openvmm_process_terminated\": true,\n \"temporary_storage_removed\": true,\n \"virtiofs_released\": true,\n \"vm_stopped\": true\n }\n}\n"},"state/openvmm.log":{"text":""}}},{"argv":["sandbox","start","--state-dir","{root}\\state"],"check":["state","state/config.json","state/runtime.json","state/control.capability","state/outcome.json","state/openvmm.log"],"status":0,"stdout":"","stderr":"","files":{"state":{"entries":["config.json","control.capability","openvmm.log","runtime.json","sandbox.lock"]},"state/config.json":{"text":"{\r\n \"cmdline\": \"\",\r\n \"distro_binding\": {\r\n \"format\": \"erofs\",\r\n \"identity\": \"11111111-1111-1111-1111-111111111111\",\r\n \"image\": {\r\n \"changed\": null,\r\n \"device\": {int},\r\n \"fileId\": \"{hex32}\",\r\n \"kind\": \"regular\",\r\n \"length\": 7,\r\n \"modified\": {\r\n \"nanoseconds\": {int},\r\n \"seconds\": {int}\r\n },\r\n \"scheme\": \"windows\",\r\n \"version\": 1\r\n },\r\n \"manifest\": null,\r\n \"policy\": {\r\n \"result\": \"accepted\",\r\n \"revision\": 1\r\n },\r\n \"version\": 1\r\n },\r\n \"export\": {\r\n \"binds\": [\r\n {\r\n \"child\": 0,\r\n \"readOnly\": true,\r\n \"source\": \"\",\r\n \"target\": \"/data\"\r\n }\r\n ],\r\n \"children\": [\r\n {\r\n \"allowed\": [],\r\n \"denied\": [],\r\n \"deniedIdentities\": [],\r\n \"root\": \"{root_json}\\\\share\",\r\n \"writable\": false,\r\n \"write\": []\r\n }\r\n ]\r\n },\r\n \"format\": 7,\r\n \"hostname\": \"nvx-sandbox\",\r\n \"hypervisor\": \"whp\",\r\n \"layers\": [\r\n {\r\n \"path\": \"{root_json}\\\\distro.erofs\",\r\n \"role\": \"distro\",\r\n \"uuid\": \"11111111-1111-1111-1111-111111111111\"\r\n }\r\n ],\r\n \"memory_max\": null,\r\n \"memory_mib\": 256,\r\n \"network\": null,\r\n \"pids_max\": null,\r\n \"scratch\": \"{root_json}\\\\scratch.ext4\",\r\n \"scratch_binding\": {\r\n \"device\": {int},\r\n \"fileId\": \"{hex32}\",\r\n \"kind\": \"regular\",\r\n \"length\": 8,\r\n \"scheme\": \"windows\",\r\n \"version\": 1\r\n },\r\n \"workload_gid\": 65534,\r\n \"workload_uid\": 65534\r\n}\r\n"},"state/runtime.json":{"text":"{\n \"format\": 4,\n \"launch\": \"{hex32}\",\n \"process\": {\n \"pid\": {int},\n \"startTime\": {int},\n \"boot\": \"{hex32}\"\n },\n \"endpoint\": \"//./pipe/openvmm-microvm-{hex32}\",\n \"runtime\": {\n \"openvmm\": \"sha256:1e8c924cdaac227bf74b4a4a9bcdb9e8836a1355fd0408cc81dab5d9aa71eb4d\",\n \"kernel\": \"sha256:a0c936696eb7d5ee3192bf53b9d281cecbb40ca9db520de72cb95817ad92ac72\",\n \"initramfs\": \"sha256:2f77c2c97621e8bf69794e9d12815bb7c46338638f126bea8b18dfe02a684d62\",\n \"bootContract\": 3,\n \"controlContract\": \"nvx-microvm-v2-control-v2\",\n \"controlSession\": 1\n }\n}\n"},"state/control.capability":{"size":32},"state/outcome.json":null,"state/openvmm.log":{"text":""}}},{"argv":["sandbox","stop","--state-dir","{root}\\state"],"check":["state","state/config.json","state/runtime.json","state/control.capability","state/outcome.json","state/openvmm.log"],"status":0,"stdout":"","stderr":"","files":{"state":{"entries":["config.json","openvmm.log","outcome.json","sandbox.lock"]},"state/config.json":{"text":"{\r\n \"cmdline\": \"\",\r\n \"distro_binding\": {\r\n \"format\": \"erofs\",\r\n \"identity\": \"11111111-1111-1111-1111-111111111111\",\r\n \"image\": {\r\n \"changed\": null,\r\n \"device\": {int},\r\n \"fileId\": \"{hex32}\",\r\n \"kind\": \"regular\",\r\n \"length\": 7,\r\n \"modified\": {\r\n \"nanoseconds\": {int},\r\n \"seconds\": {int}\r\n },\r\n \"scheme\": \"windows\",\r\n \"version\": 1\r\n },\r\n \"manifest\": null,\r\n \"policy\": {\r\n \"result\": \"accepted\",\r\n \"revision\": 1\r\n },\r\n \"version\": 1\r\n },\r\n \"export\": {\r\n \"binds\": [\r\n {\r\n \"child\": 0,\r\n \"readOnly\": true,\r\n \"source\": \"\",\r\n \"target\": \"/data\"\r\n }\r\n ],\r\n \"children\": [\r\n {\r\n \"allowed\": [],\r\n \"denied\": [],\r\n \"deniedIdentities\": [],\r\n \"root\": \"{root_json}\\\\share\",\r\n \"writable\": false,\r\n \"write\": []\r\n }\r\n ]\r\n },\r\n \"format\": 7,\r\n \"hostname\": \"nvx-sandbox\",\r\n \"hypervisor\": \"whp\",\r\n \"layers\": [\r\n {\r\n \"path\": \"{root_json}\\\\distro.erofs\",\r\n \"role\": \"distro\",\r\n \"uuid\": \"11111111-1111-1111-1111-111111111111\"\r\n }\r\n ],\r\n \"memory_max\": null,\r\n \"memory_mib\": 256,\r\n \"network\": null,\r\n \"pids_max\": null,\r\n \"scratch\": \"{root_json}\\\\scratch.ext4\",\r\n \"scratch_binding\": {\r\n \"device\": {int},\r\n \"fileId\": \"{hex32}\",\r\n \"kind\": \"regular\",\r\n \"length\": 8,\r\n \"scheme\": \"windows\",\r\n \"version\": 1\r\n },\r\n \"workload_gid\": 65534,\r\n \"workload_uid\": 65534\r\n}\r\n"},"state/runtime.json":null,"state/control.capability":null,"state/outcome.json":{"text":"{\n \"backend\": \"whp\",\n \"instance_id\": \"{hex32}\",\n \"network_policy\": {\n \"allow_rule_count\": 0,\n \"deny_rule_count\": 0,\n \"host_loopback\": \"none\",\n \"mode\": \"none\",\n \"status\": \"not-requested\",\n \"status_code\": 0\n },\n \"outcome\": {\n \"category\": \"success\",\n \"operation\": \"managed\",\n \"status_code\": 0\n },\n \"schema_version\": 1,\n \"teardown\": {\n \"control_channels_closed\": true,\n \"guest_workload_stopped\": true,\n \"network_released\": true,\n \"openvmm_process_terminated\": true,\n \"temporary_storage_removed\": true,\n \"virtiofs_released\": true,\n \"vm_stopped\": true\n }\n}\n"},"state/openvmm.log":{"text":""}}},{"argv":["sandbox","deprovision","--state-dir","{root}\\state"],"check":["state"],"status":0,"stdout":"","stderr":"","files":{"state":null}}],"interop":true}, -{"name":"lifecycle: several shares","steps":[{"argv":["sandbox","provision","--state-dir","{root}\\state","--layer","distro,{root}\\distro.erofs,11111111-1111-1111-1111-111111111111","--scratch","{root}\\scratch.ext4","--mount","/data,{root}\\share","--mount","/other,{root}\\share2,rw"],"check":["state","state/config.json","state/runtime.json","state/control.capability","state/outcome.json","state/openvmm.log"],"status":0,"stdout":"","stderr":"","files":{"state":{"entries":["config.json","sandbox.lock"]},"state/config.json":{"text":"{\r\n \"cmdline\": \"\",\r\n \"distro_binding\": {\r\n \"format\": \"erofs\",\r\n \"identity\": \"11111111-1111-1111-1111-111111111111\",\r\n \"image\": {\r\n \"changed\": null,\r\n \"device\": {int},\r\n \"fileId\": \"{hex32}\",\r\n \"kind\": \"regular\",\r\n \"length\": 7,\r\n \"modified\": {\r\n \"nanoseconds\": {int},\r\n \"seconds\": {int}\r\n },\r\n \"scheme\": \"windows\",\r\n \"version\": 1\r\n },\r\n \"manifest\": null,\r\n \"policy\": {\r\n \"result\": \"accepted\",\r\n \"revision\": 1\r\n },\r\n \"version\": 1\r\n },\r\n \"export\": {\r\n \"binds\": [\r\n {\r\n \"child\": 0,\r\n \"readOnly\": true,\r\n \"source\": \"\",\r\n \"target\": \"/data\"\r\n },\r\n {\r\n \"child\": 1,\r\n \"readOnly\": false,\r\n \"source\": \"\",\r\n \"target\": \"/other\"\r\n }\r\n ],\r\n \"children\": [\r\n {\r\n \"allowed\": [],\r\n \"denied\": [],\r\n \"deniedIdentities\": [],\r\n \"root\": \"{root_json}\\\\share\",\r\n \"writable\": false,\r\n \"write\": []\r\n },\r\n {\r\n \"allowed\": [],\r\n \"denied\": [],\r\n \"deniedIdentities\": [],\r\n \"root\": \"{root_json}\\\\share2\",\r\n \"writable\": true,\r\n \"write\": []\r\n }\r\n ]\r\n },\r\n \"format\": 7,\r\n \"hostname\": \"nvx-sandbox\",\r\n \"hypervisor\": \"whp\",\r\n \"layers\": [\r\n {\r\n \"path\": \"{root_json}\\\\distro.erofs\",\r\n \"role\": \"distro\",\r\n \"uuid\": \"11111111-1111-1111-1111-111111111111\"\r\n }\r\n ],\r\n \"memory_max\": null,\r\n \"memory_mib\": 256,\r\n \"network\": null,\r\n \"pids_max\": null,\r\n \"scratch\": \"{root_json}\\\\scratch.ext4\",\r\n \"scratch_binding\": {\r\n \"device\": {int},\r\n \"fileId\": \"{hex32}\",\r\n \"kind\": \"regular\",\r\n \"length\": 8,\r\n \"scheme\": \"windows\",\r\n \"version\": 1\r\n },\r\n \"workload_gid\": 65534,\r\n \"workload_uid\": 65534\r\n}\r\n"},"state/runtime.json":null,"state/control.capability":null,"state/outcome.json":null,"state/openvmm.log":null}},{"argv":["sandbox","start","--state-dir","{root}\\state"],"check":["state","state/config.json","state/runtime.json","state/control.capability","state/outcome.json","state/openvmm.log","build/fake-openvmm-state.json"],"status":0,"stdout":"","stderr":"","files":{"state":{"entries":["config.json","control.capability","openvmm.log","runtime.json","sandbox.lock"]},"state/config.json":{"text":"{\r\n \"cmdline\": \"\",\r\n \"distro_binding\": {\r\n \"format\": \"erofs\",\r\n \"identity\": \"11111111-1111-1111-1111-111111111111\",\r\n \"image\": {\r\n \"changed\": null,\r\n \"device\": {int},\r\n \"fileId\": \"{hex32}\",\r\n \"kind\": \"regular\",\r\n \"length\": 7,\r\n \"modified\": {\r\n \"nanoseconds\": {int},\r\n \"seconds\": {int}\r\n },\r\n \"scheme\": \"windows\",\r\n \"version\": 1\r\n },\r\n \"manifest\": null,\r\n \"policy\": {\r\n \"result\": \"accepted\",\r\n \"revision\": 1\r\n },\r\n \"version\": 1\r\n },\r\n \"export\": {\r\n \"binds\": [\r\n {\r\n \"child\": 0,\r\n \"readOnly\": true,\r\n \"source\": \"\",\r\n \"target\": \"/data\"\r\n },\r\n {\r\n \"child\": 1,\r\n \"readOnly\": false,\r\n \"source\": \"\",\r\n \"target\": \"/other\"\r\n }\r\n ],\r\n \"children\": [\r\n {\r\n \"allowed\": [],\r\n \"denied\": [],\r\n \"deniedIdentities\": [],\r\n \"root\": \"{root_json}\\\\share\",\r\n \"writable\": false,\r\n \"write\": []\r\n },\r\n {\r\n \"allowed\": [],\r\n \"denied\": [],\r\n \"deniedIdentities\": [],\r\n \"root\": \"{root_json}\\\\share2\",\r\n \"writable\": true,\r\n \"write\": []\r\n }\r\n ]\r\n },\r\n \"format\": 7,\r\n \"hostname\": \"nvx-sandbox\",\r\n \"hypervisor\": \"whp\",\r\n \"layers\": [\r\n {\r\n \"path\": \"{root_json}\\\\distro.erofs\",\r\n \"role\": \"distro\",\r\n \"uuid\": \"11111111-1111-1111-1111-111111111111\"\r\n }\r\n ],\r\n \"memory_max\": null,\r\n \"memory_mib\": 256,\r\n \"network\": null,\r\n \"pids_max\": null,\r\n \"scratch\": \"{root_json}\\\\scratch.ext4\",\r\n \"scratch_binding\": {\r\n \"device\": {int},\r\n \"fileId\": \"{hex32}\",\r\n \"kind\": \"regular\",\r\n \"length\": 8,\r\n \"scheme\": \"windows\",\r\n \"version\": 1\r\n },\r\n \"workload_gid\": 65534,\r\n \"workload_uid\": 65534\r\n}\r\n"},"state/runtime.json":{"text":"{\n \"format\": 4,\n \"launch\": \"{hex32}\",\n \"process\": {\n \"pid\": {int},\n \"startTime\": {int},\n \"boot\": \"{hex32}\"\n },\n \"endpoint\": \"//./pipe/openvmm-microvm-{hex32}\",\n \"runtime\": {\n \"openvmm\": \"sha256:1e8c924cdaac227bf74b4a4a9bcdb9e8836a1355fd0408cc81dab5d9aa71eb4d\",\n \"kernel\": \"sha256:a0c936696eb7d5ee3192bf53b9d281cecbb40ca9db520de72cb95817ad92ac72\",\n \"initramfs\": \"sha256:2f77c2c97621e8bf69794e9d12815bb7c46338638f126bea8b18dfe02a684d62\",\n \"bootContract\": 3,\n \"controlContract\": \"nvx-microvm-v2-control-v2\",\n \"controlSession\": 1\n }\n}\n"},"state/control.capability":{"size":32},"state/outcome.json":null,"state/openvmm.log":{"text":""},"build/fake-openvmm-state.json":{"text":"[\"--machine\",\"microvm\",\"--microvm-sandbox-block\",\"distro:file:\\\\\\\\?\\\\{root_json}\\\\distro.erofs,ro\",\"--microvm-sandbox-block\",\"scratch:file:\\\\\\\\?\\\\{root_json}\\\\scratch.ext4\",\"--microvm-workload-identity\",\"65534:65534\",\"--mount-aggregate\",\"/run/nvx/shares\",\"--mount-child\",\"0-bd47413b5c03dfc6e4b5b8143fe205ea,{root_json}\\\\share,ro\",\"--mount-child\",\"1-bf2faee2596026620b5cbc997c2d7d45,{root_json}\\\\share2,rw\",\"--microvm-lifecycle\",\"managed\",\"--single-process\",\"--hypervisor\",\"whp\",\"--memory\",\"256M\",\"--kernel\",\"{root_json}\\\\build\\\\vmlinux\",\"--initrd\",\"{root_json}\\\\build\\\\initramfs.cpio.gz\",\"--cmdline\",\"nvx_sandbox=1 nvx_layer=distro,0xd0003000,erofs:11111111-1111-1111-1111-111111111111 nvx_scratch=0xd0006000,ext4 nvx_entrypoint=/bin/sh nvx_hostname=nvx-sandbox nvx_share=0-bd47413b5c03dfc6e4b5b8143fe205ea,/data,ro nvx_share=1-bf2faee2596026620b5cbc997c2d7d45,/other,rw\",\"--virtio-console\",\"none\",\"--microvm-control-console\",\"listen=//./pipe/openvmm-microvm-{hex32}\",\"--microvm-control-auth-stdin\",\"--microvm-report\",\"{root_json}\\\\state\\\\outcome.json\"]"}}},{"argv":["sandbox","exec","--state-dir","{root}\\state","--entrypoint","/bin/pwd","--cwd","/other"],"status":0,"stdout":"/other\n","stderr":""},{"argv":["sandbox","stop","--state-dir","{root}\\state"],"check":["state","state/config.json","state/runtime.json","state/control.capability","state/outcome.json","state/openvmm.log"],"status":0,"stdout":"","stderr":"","files":{"state":{"entries":["config.json","openvmm.log","outcome.json","sandbox.lock"]},"state/config.json":{"text":"{\r\n \"cmdline\": \"\",\r\n \"distro_binding\": {\r\n \"format\": \"erofs\",\r\n \"identity\": \"11111111-1111-1111-1111-111111111111\",\r\n \"image\": {\r\n \"changed\": null,\r\n \"device\": {int},\r\n \"fileId\": \"{hex32}\",\r\n \"kind\": \"regular\",\r\n \"length\": 7,\r\n \"modified\": {\r\n \"nanoseconds\": {int},\r\n \"seconds\": {int}\r\n },\r\n \"scheme\": \"windows\",\r\n \"version\": 1\r\n },\r\n \"manifest\": null,\r\n \"policy\": {\r\n \"result\": \"accepted\",\r\n \"revision\": 1\r\n },\r\n \"version\": 1\r\n },\r\n \"export\": {\r\n \"binds\": [\r\n {\r\n \"child\": 0,\r\n \"readOnly\": true,\r\n \"source\": \"\",\r\n \"target\": \"/data\"\r\n },\r\n {\r\n \"child\": 1,\r\n \"readOnly\": false,\r\n \"source\": \"\",\r\n \"target\": \"/other\"\r\n }\r\n ],\r\n \"children\": [\r\n {\r\n \"allowed\": [],\r\n \"denied\": [],\r\n \"deniedIdentities\": [],\r\n \"root\": \"{root_json}\\\\share\",\r\n \"writable\": false,\r\n \"write\": []\r\n },\r\n {\r\n \"allowed\": [],\r\n \"denied\": [],\r\n \"deniedIdentities\": [],\r\n \"root\": \"{root_json}\\\\share2\",\r\n \"writable\": true,\r\n \"write\": []\r\n }\r\n ]\r\n },\r\n \"format\": 7,\r\n \"hostname\": \"nvx-sandbox\",\r\n \"hypervisor\": \"whp\",\r\n \"layers\": [\r\n {\r\n \"path\": \"{root_json}\\\\distro.erofs\",\r\n \"role\": \"distro\",\r\n \"uuid\": \"11111111-1111-1111-1111-111111111111\"\r\n }\r\n ],\r\n \"memory_max\": null,\r\n \"memory_mib\": 256,\r\n \"network\": null,\r\n \"pids_max\": null,\r\n \"scratch\": \"{root_json}\\\\scratch.ext4\",\r\n \"scratch_binding\": {\r\n \"device\": {int},\r\n \"fileId\": \"{hex32}\",\r\n \"kind\": \"regular\",\r\n \"length\": 8,\r\n \"scheme\": \"windows\",\r\n \"version\": 1\r\n },\r\n \"workload_gid\": 65534,\r\n \"workload_uid\": 65534\r\n}\r\n"},"state/runtime.json":null,"state/control.capability":null,"state/outcome.json":{"text":"{\n \"backend\": \"whp\",\n \"instance_id\": \"{hex32}\",\n \"network_policy\": {\n \"allow_rule_count\": 0,\n \"deny_rule_count\": 0,\n \"host_loopback\": \"none\",\n \"mode\": \"none\",\n \"status\": \"not-requested\",\n \"status_code\": 0\n },\n \"outcome\": {\n \"category\": \"success\",\n \"operation\": \"managed\",\n \"status_code\": 0\n },\n \"schema_version\": 1,\n \"teardown\": {\n \"control_channels_closed\": true,\n \"guest_workload_stopped\": true,\n \"network_released\": true,\n \"openvmm_process_terminated\": true,\n \"temporary_storage_removed\": true,\n \"virtiofs_released\": true,\n \"vm_stopped\": true\n }\n}\n"},"state/openvmm.log":{"text":""}}},{"argv":["sandbox","start","--state-dir","{root}\\state"],"check":["state","state/config.json","state/runtime.json","state/control.capability","state/outcome.json","state/openvmm.log"],"status":0,"stdout":"","stderr":"","files":{"state":{"entries":["config.json","control.capability","openvmm.log","runtime.json","sandbox.lock"]},"state/config.json":{"text":"{\r\n \"cmdline\": \"\",\r\n \"distro_binding\": {\r\n \"format\": \"erofs\",\r\n \"identity\": \"11111111-1111-1111-1111-111111111111\",\r\n \"image\": {\r\n \"changed\": null,\r\n \"device\": {int},\r\n \"fileId\": \"{hex32}\",\r\n \"kind\": \"regular\",\r\n \"length\": 7,\r\n \"modified\": {\r\n \"nanoseconds\": {int},\r\n \"seconds\": {int}\r\n },\r\n \"scheme\": \"windows\",\r\n \"version\": 1\r\n },\r\n \"manifest\": null,\r\n \"policy\": {\r\n \"result\": \"accepted\",\r\n \"revision\": 1\r\n },\r\n \"version\": 1\r\n },\r\n \"export\": {\r\n \"binds\": [\r\n {\r\n \"child\": 0,\r\n \"readOnly\": true,\r\n \"source\": \"\",\r\n \"target\": \"/data\"\r\n },\r\n {\r\n \"child\": 1,\r\n \"readOnly\": false,\r\n \"source\": \"\",\r\n \"target\": \"/other\"\r\n }\r\n ],\r\n \"children\": [\r\n {\r\n \"allowed\": [],\r\n \"denied\": [],\r\n \"deniedIdentities\": [],\r\n \"root\": \"{root_json}\\\\share\",\r\n \"writable\": false,\r\n \"write\": []\r\n },\r\n {\r\n \"allowed\": [],\r\n \"denied\": [],\r\n \"deniedIdentities\": [],\r\n \"root\": \"{root_json}\\\\share2\",\r\n \"writable\": true,\r\n \"write\": []\r\n }\r\n ]\r\n },\r\n \"format\": 7,\r\n \"hostname\": \"nvx-sandbox\",\r\n \"hypervisor\": \"whp\",\r\n \"layers\": [\r\n {\r\n \"path\": \"{root_json}\\\\distro.erofs\",\r\n \"role\": \"distro\",\r\n \"uuid\": \"11111111-1111-1111-1111-111111111111\"\r\n }\r\n ],\r\n \"memory_max\": null,\r\n \"memory_mib\": 256,\r\n \"network\": null,\r\n \"pids_max\": null,\r\n \"scratch\": \"{root_json}\\\\scratch.ext4\",\r\n \"scratch_binding\": {\r\n \"device\": {int},\r\n \"fileId\": \"{hex32}\",\r\n \"kind\": \"regular\",\r\n \"length\": 8,\r\n \"scheme\": \"windows\",\r\n \"version\": 1\r\n },\r\n \"workload_gid\": 65534,\r\n \"workload_uid\": 65534\r\n}\r\n"},"state/runtime.json":{"text":"{\n \"format\": 4,\n \"launch\": \"{hex32}\",\n \"process\": {\n \"pid\": {int},\n \"startTime\": {int},\n \"boot\": \"{hex32}\"\n },\n \"endpoint\": \"//./pipe/openvmm-microvm-{hex32}\",\n \"runtime\": {\n \"openvmm\": \"sha256:1e8c924cdaac227bf74b4a4a9bcdb9e8836a1355fd0408cc81dab5d9aa71eb4d\",\n \"kernel\": \"sha256:a0c936696eb7d5ee3192bf53b9d281cecbb40ca9db520de72cb95817ad92ac72\",\n \"initramfs\": \"sha256:2f77c2c97621e8bf69794e9d12815bb7c46338638f126bea8b18dfe02a684d62\",\n \"bootContract\": 3,\n \"controlContract\": \"nvx-microvm-v2-control-v2\",\n \"controlSession\": 1\n }\n}\n"},"state/control.capability":{"size":32},"state/outcome.json":null,"state/openvmm.log":{"text":""}}},{"argv":["sandbox","stop","--state-dir","{root}\\state"],"check":["state","state/config.json","state/runtime.json","state/control.capability","state/outcome.json","state/openvmm.log"],"status":0,"stdout":"","stderr":"","files":{"state":{"entries":["config.json","openvmm.log","outcome.json","sandbox.lock"]},"state/config.json":{"text":"{\r\n \"cmdline\": \"\",\r\n \"distro_binding\": {\r\n \"format\": \"erofs\",\r\n \"identity\": \"11111111-1111-1111-1111-111111111111\",\r\n \"image\": {\r\n \"changed\": null,\r\n \"device\": {int},\r\n \"fileId\": \"{hex32}\",\r\n \"kind\": \"regular\",\r\n \"length\": 7,\r\n \"modified\": {\r\n \"nanoseconds\": {int},\r\n \"seconds\": {int}\r\n },\r\n \"scheme\": \"windows\",\r\n \"version\": 1\r\n },\r\n \"manifest\": null,\r\n \"policy\": {\r\n \"result\": \"accepted\",\r\n \"revision\": 1\r\n },\r\n \"version\": 1\r\n },\r\n \"export\": {\r\n \"binds\": [\r\n {\r\n \"child\": 0,\r\n \"readOnly\": true,\r\n \"source\": \"\",\r\n \"target\": \"/data\"\r\n },\r\n {\r\n \"child\": 1,\r\n \"readOnly\": false,\r\n \"source\": \"\",\r\n \"target\": \"/other\"\r\n }\r\n ],\r\n \"children\": [\r\n {\r\n \"allowed\": [],\r\n \"denied\": [],\r\n \"deniedIdentities\": [],\r\n \"root\": \"{root_json}\\\\share\",\r\n \"writable\": false,\r\n \"write\": []\r\n },\r\n {\r\n \"allowed\": [],\r\n \"denied\": [],\r\n \"deniedIdentities\": [],\r\n \"root\": \"{root_json}\\\\share2\",\r\n \"writable\": true,\r\n \"write\": []\r\n }\r\n ]\r\n },\r\n \"format\": 7,\r\n \"hostname\": \"nvx-sandbox\",\r\n \"hypervisor\": \"whp\",\r\n \"layers\": [\r\n {\r\n \"path\": \"{root_json}\\\\distro.erofs\",\r\n \"role\": \"distro\",\r\n \"uuid\": \"11111111-1111-1111-1111-111111111111\"\r\n }\r\n ],\r\n \"memory_max\": null,\r\n \"memory_mib\": 256,\r\n \"network\": null,\r\n \"pids_max\": null,\r\n \"scratch\": \"{root_json}\\\\scratch.ext4\",\r\n \"scratch_binding\": {\r\n \"device\": {int},\r\n \"fileId\": \"{hex32}\",\r\n \"kind\": \"regular\",\r\n \"length\": 8,\r\n \"scheme\": \"windows\",\r\n \"version\": 1\r\n },\r\n \"workload_gid\": 65534,\r\n \"workload_uid\": 65534\r\n}\r\n"},"state/runtime.json":null,"state/control.capability":null,"state/outcome.json":{"text":"{\n \"backend\": \"whp\",\n \"instance_id\": \"{hex32}\",\n \"network_policy\": {\n \"allow_rule_count\": 0,\n \"deny_rule_count\": 0,\n \"host_loopback\": \"none\",\n \"mode\": \"none\",\n \"status\": \"not-requested\",\n \"status_code\": 0\n },\n \"outcome\": {\n \"category\": \"success\",\n \"operation\": \"managed\",\n \"status_code\": 0\n },\n \"schema_version\": 1,\n \"teardown\": {\n \"control_channels_closed\": true,\n \"guest_workload_stopped\": true,\n \"network_released\": true,\n \"openvmm_process_terminated\": true,\n \"temporary_storage_removed\": true,\n \"virtiofs_released\": true,\n \"vm_stopped\": true\n }\n}\n"},"state/openvmm.log":{"text":""}}},{"argv":["sandbox","deprovision","--state-dir","{root}\\state"],"check":["state"],"status":0,"stdout":"","stderr":"","files":{"state":null}}],"interop":true}, -{"name":"lifecycle: share policies","steps":[{"argv":["sandbox","provision","--state-dir","{root}\\state","--layer","distro,{root}\\distro.erofs,11111111-1111-1111-1111-111111111111","--scratch","{root}\\scratch.ext4","--mount","/data,{root}\\share,rw","--mount-deny","{root}\\share\\hidden","--mount-allow","{root}\\share\\hidden\\shown","--mount-write","{root}\\share\\writable"],"check":["state","state/config.json","state/runtime.json","state/control.capability","state/outcome.json","state/openvmm.log"],"status":0,"stdout":"","stderr":"","files":{"state":{"entries":["config.json","sandbox.lock"]},"state/config.json":{"text":"{\r\n \"cmdline\": \"\",\r\n \"distro_binding\": {\r\n \"format\": \"erofs\",\r\n \"identity\": \"11111111-1111-1111-1111-111111111111\",\r\n \"image\": {\r\n \"changed\": null,\r\n \"device\": {int},\r\n \"fileId\": \"{hex32}\",\r\n \"kind\": \"regular\",\r\n \"length\": 7,\r\n \"modified\": {\r\n \"nanoseconds\": {int},\r\n \"seconds\": {int}\r\n },\r\n \"scheme\": \"windows\",\r\n \"version\": 1\r\n },\r\n \"manifest\": null,\r\n \"policy\": {\r\n \"result\": \"accepted\",\r\n \"revision\": 1\r\n },\r\n \"version\": 1\r\n },\r\n \"export\": {\r\n \"binds\": [\r\n {\r\n \"child\": 0,\r\n \"readOnly\": false,\r\n \"source\": \"\",\r\n \"target\": \"/data\"\r\n }\r\n ],\r\n \"children\": [\r\n {\r\n \"allowed\": [\r\n \"{root_json}\\\\share\\\\hidden\\\\shown\"\r\n ],\r\n \"denied\": [\r\n \"{root_json}\\\\share\\\\hidden\"\r\n ],\r\n \"deniedIdentities\": [\r\n null\r\n ],\r\n \"root\": \"{root_json}\\\\share\",\r\n \"writable\": true,\r\n \"write\": [\r\n \"{root_json}\\\\share\\\\writable\"\r\n ]\r\n }\r\n ]\r\n },\r\n \"format\": 7,\r\n \"hostname\": \"nvx-sandbox\",\r\n \"hypervisor\": \"whp\",\r\n \"layers\": [\r\n {\r\n \"path\": \"{root_json}\\\\distro.erofs\",\r\n \"role\": \"distro\",\r\n \"uuid\": \"11111111-1111-1111-1111-111111111111\"\r\n }\r\n ],\r\n \"memory_max\": null,\r\n \"memory_mib\": 256,\r\n \"network\": null,\r\n \"pids_max\": null,\r\n \"scratch\": \"{root_json}\\\\scratch.ext4\",\r\n \"scratch_binding\": {\r\n \"device\": {int},\r\n \"fileId\": \"{hex32}\",\r\n \"kind\": \"regular\",\r\n \"length\": 8,\r\n \"scheme\": \"windows\",\r\n \"version\": 1\r\n },\r\n \"workload_gid\": 65534,\r\n \"workload_uid\": 65534\r\n}\r\n"},"state/runtime.json":null,"state/control.capability":null,"state/outcome.json":null,"state/openvmm.log":null}},{"argv":["sandbox","start","--state-dir","{root}\\state"],"check":["state","state/config.json","state/runtime.json","state/control.capability","state/outcome.json","state/openvmm.log","build/fake-openvmm-state.json"],"status":0,"stdout":"","stderr":"","files":{"state":{"entries":["config.json","control.capability","openvmm.log","runtime.json","sandbox.lock"]},"state/config.json":{"text":"{\r\n \"cmdline\": \"\",\r\n \"distro_binding\": {\r\n \"format\": \"erofs\",\r\n \"identity\": \"11111111-1111-1111-1111-111111111111\",\r\n \"image\": {\r\n \"changed\": null,\r\n \"device\": {int},\r\n \"fileId\": \"{hex32}\",\r\n \"kind\": \"regular\",\r\n \"length\": 7,\r\n \"modified\": {\r\n \"nanoseconds\": {int},\r\n \"seconds\": {int}\r\n },\r\n \"scheme\": \"windows\",\r\n \"version\": 1\r\n },\r\n \"manifest\": null,\r\n \"policy\": {\r\n \"result\": \"accepted\",\r\n \"revision\": 1\r\n },\r\n \"version\": 1\r\n },\r\n \"export\": {\r\n \"binds\": [\r\n {\r\n \"child\": 0,\r\n \"readOnly\": false,\r\n \"source\": \"\",\r\n \"target\": \"/data\"\r\n }\r\n ],\r\n \"children\": [\r\n {\r\n \"allowed\": [\r\n \"{root_json}\\\\share\\\\hidden\\\\shown\"\r\n ],\r\n \"denied\": [\r\n \"{root_json}\\\\share\\\\hidden\"\r\n ],\r\n \"deniedIdentities\": [\r\n null\r\n ],\r\n \"root\": \"{root_json}\\\\share\",\r\n \"writable\": true,\r\n \"write\": [\r\n \"{root_json}\\\\share\\\\writable\"\r\n ]\r\n }\r\n ]\r\n },\r\n \"format\": 7,\r\n \"hostname\": \"nvx-sandbox\",\r\n \"hypervisor\": \"whp\",\r\n \"layers\": [\r\n {\r\n \"path\": \"{root_json}\\\\distro.erofs\",\r\n \"role\": \"distro\",\r\n \"uuid\": \"11111111-1111-1111-1111-111111111111\"\r\n }\r\n ],\r\n \"memory_max\": null,\r\n \"memory_mib\": 256,\r\n \"network\": null,\r\n \"pids_max\": null,\r\n \"scratch\": \"{root_json}\\\\scratch.ext4\",\r\n \"scratch_binding\": {\r\n \"device\": {int},\r\n \"fileId\": \"{hex32}\",\r\n \"kind\": \"regular\",\r\n \"length\": 8,\r\n \"scheme\": \"windows\",\r\n \"version\": 1\r\n },\r\n \"workload_gid\": 65534,\r\n \"workload_uid\": 65534\r\n}\r\n"},"state/runtime.json":{"text":"{\n \"format\": 4,\n \"launch\": \"{hex32}\",\n \"process\": {\n \"pid\": {int},\n \"startTime\": {int},\n \"boot\": \"{hex32}\"\n },\n \"endpoint\": \"//./pipe/openvmm-microvm-{hex32}\",\n \"runtime\": {\n \"openvmm\": \"sha256:1e8c924cdaac227bf74b4a4a9bcdb9e8836a1355fd0408cc81dab5d9aa71eb4d\",\n \"kernel\": \"sha256:a0c936696eb7d5ee3192bf53b9d281cecbb40ca9db520de72cb95817ad92ac72\",\n \"initramfs\": \"sha256:2f77c2c97621e8bf69794e9d12815bb7c46338638f126bea8b18dfe02a684d62\",\n \"bootContract\": 3,\n \"controlContract\": \"nvx-microvm-v2-control-v2\",\n \"controlSession\": 1\n }\n}\n"},"state/control.capability":{"size":32},"state/outcome.json":null,"state/openvmm.log":{"text":""},"build/fake-openvmm-state.json":{"text":"[\"--machine\",\"microvm\",\"--microvm-sandbox-block\",\"distro:file:\\\\\\\\?\\\\{root_json}\\\\distro.erofs,ro\",\"--microvm-sandbox-block\",\"scratch:file:\\\\\\\\?\\\\{root_json}\\\\scratch.ext4\",\"--microvm-workload-identity\",\"65534:65534\",\"--mount\",\"/data,{root_json}\\\\share,rw\",\"--mount-deny\",\"{root_json}\\\\share\\\\hidden\",\"--mount-allow\",\"{root_json}\\\\share\\\\hidden\\\\shown\",\"--mount-write\",\"{root_json}\\\\share\\\\writable\",\"--microvm-lifecycle\",\"managed\",\"--single-process\",\"--hypervisor\",\"whp\",\"--memory\",\"256M\",\"--kernel\",\"{root_json}\\\\build\\\\vmlinux\",\"--initrd\",\"{root_json}\\\\build\\\\initramfs.cpio.gz\",\"--cmdline\",\"nvx_sandbox=1 nvx_layer=distro,0xd0003000,erofs:11111111-1111-1111-1111-111111111111 nvx_scratch=0xd0006000,ext4 nvx_entrypoint=/bin/sh nvx_hostname=nvx-sandbox\",\"--virtio-console\",\"none\",\"--microvm-control-console\",\"listen=//./pipe/openvmm-microvm-{hex32}\",\"--microvm-control-auth-stdin\",\"--microvm-report\",\"{root_json}\\\\state\\\\outcome.json\"]"}}},{"argv":["sandbox","stop","--state-dir","{root}\\state"],"check":["state","state/config.json","state/runtime.json","state/control.capability","state/outcome.json","state/openvmm.log"],"status":0,"stdout":"","stderr":"","files":{"state":{"entries":["config.json","openvmm.log","outcome.json","sandbox.lock"]},"state/config.json":{"text":"{\r\n \"cmdline\": \"\",\r\n \"distro_binding\": {\r\n \"format\": \"erofs\",\r\n \"identity\": \"11111111-1111-1111-1111-111111111111\",\r\n \"image\": {\r\n \"changed\": null,\r\n \"device\": {int},\r\n \"fileId\": \"{hex32}\",\r\n \"kind\": \"regular\",\r\n \"length\": 7,\r\n \"modified\": {\r\n \"nanoseconds\": {int},\r\n \"seconds\": {int}\r\n },\r\n \"scheme\": \"windows\",\r\n \"version\": 1\r\n },\r\n \"manifest\": null,\r\n \"policy\": {\r\n \"result\": \"accepted\",\r\n \"revision\": 1\r\n },\r\n \"version\": 1\r\n },\r\n \"export\": {\r\n \"binds\": [\r\n {\r\n \"child\": 0,\r\n \"readOnly\": false,\r\n \"source\": \"\",\r\n \"target\": \"/data\"\r\n }\r\n ],\r\n \"children\": [\r\n {\r\n \"allowed\": [\r\n \"{root_json}\\\\share\\\\hidden\\\\shown\"\r\n ],\r\n \"denied\": [\r\n \"{root_json}\\\\share\\\\hidden\"\r\n ],\r\n \"deniedIdentities\": [\r\n null\r\n ],\r\n \"root\": \"{root_json}\\\\share\",\r\n \"writable\": true,\r\n \"write\": [\r\n \"{root_json}\\\\share\\\\writable\"\r\n ]\r\n }\r\n ]\r\n },\r\n \"format\": 7,\r\n \"hostname\": \"nvx-sandbox\",\r\n \"hypervisor\": \"whp\",\r\n \"layers\": [\r\n {\r\n \"path\": \"{root_json}\\\\distro.erofs\",\r\n \"role\": \"distro\",\r\n \"uuid\": \"11111111-1111-1111-1111-111111111111\"\r\n }\r\n ],\r\n \"memory_max\": null,\r\n \"memory_mib\": 256,\r\n \"network\": null,\r\n \"pids_max\": null,\r\n \"scratch\": \"{root_json}\\\\scratch.ext4\",\r\n \"scratch_binding\": {\r\n \"device\": {int},\r\n \"fileId\": \"{hex32}\",\r\n \"kind\": \"regular\",\r\n \"length\": 8,\r\n \"scheme\": \"windows\",\r\n \"version\": 1\r\n },\r\n \"workload_gid\": 65534,\r\n \"workload_uid\": 65534\r\n}\r\n"},"state/runtime.json":null,"state/control.capability":null,"state/outcome.json":{"text":"{\n \"backend\": \"whp\",\n \"instance_id\": \"{hex32}\",\n \"network_policy\": {\n \"allow_rule_count\": 0,\n \"deny_rule_count\": 0,\n \"host_loopback\": \"none\",\n \"mode\": \"none\",\n \"status\": \"not-requested\",\n \"status_code\": 0\n },\n \"outcome\": {\n \"category\": \"success\",\n \"operation\": \"managed\",\n \"status_code\": 0\n },\n \"schema_version\": 1,\n \"teardown\": {\n \"control_channels_closed\": true,\n \"guest_workload_stopped\": true,\n \"network_released\": true,\n \"openvmm_process_terminated\": true,\n \"temporary_storage_removed\": true,\n \"virtiofs_released\": true,\n \"vm_stopped\": true\n }\n}\n"},"state/openvmm.log":{"text":""}}},{"argv":["sandbox","start","--state-dir","{root}\\state"],"check":["state","state/config.json","state/runtime.json","state/control.capability","state/outcome.json","state/openvmm.log"],"status":0,"stdout":"","stderr":"","files":{"state":{"entries":["config.json","control.capability","openvmm.log","runtime.json","sandbox.lock"]},"state/config.json":{"text":"{\r\n \"cmdline\": \"\",\r\n \"distro_binding\": {\r\n \"format\": \"erofs\",\r\n \"identity\": \"11111111-1111-1111-1111-111111111111\",\r\n \"image\": {\r\n \"changed\": null,\r\n \"device\": {int},\r\n \"fileId\": \"{hex32}\",\r\n \"kind\": \"regular\",\r\n \"length\": 7,\r\n \"modified\": {\r\n \"nanoseconds\": {int},\r\n \"seconds\": {int}\r\n },\r\n \"scheme\": \"windows\",\r\n \"version\": 1\r\n },\r\n \"manifest\": null,\r\n \"policy\": {\r\n \"result\": \"accepted\",\r\n \"revision\": 1\r\n },\r\n \"version\": 1\r\n },\r\n \"export\": {\r\n \"binds\": [\r\n {\r\n \"child\": 0,\r\n \"readOnly\": false,\r\n \"source\": \"\",\r\n \"target\": \"/data\"\r\n }\r\n ],\r\n \"children\": [\r\n {\r\n \"allowed\": [\r\n \"{root_json}\\\\share\\\\hidden\\\\shown\"\r\n ],\r\n \"denied\": [\r\n \"{root_json}\\\\share\\\\hidden\"\r\n ],\r\n \"deniedIdentities\": [\r\n null\r\n ],\r\n \"root\": \"{root_json}\\\\share\",\r\n \"writable\": true,\r\n \"write\": [\r\n \"{root_json}\\\\share\\\\writable\"\r\n ]\r\n }\r\n ]\r\n },\r\n \"format\": 7,\r\n \"hostname\": \"nvx-sandbox\",\r\n \"hypervisor\": \"whp\",\r\n \"layers\": [\r\n {\r\n \"path\": \"{root_json}\\\\distro.erofs\",\r\n \"role\": \"distro\",\r\n \"uuid\": \"11111111-1111-1111-1111-111111111111\"\r\n }\r\n ],\r\n \"memory_max\": null,\r\n \"memory_mib\": 256,\r\n \"network\": null,\r\n \"pids_max\": null,\r\n \"scratch\": \"{root_json}\\\\scratch.ext4\",\r\n \"scratch_binding\": {\r\n \"device\": {int},\r\n \"fileId\": \"{hex32}\",\r\n \"kind\": \"regular\",\r\n \"length\": 8,\r\n \"scheme\": \"windows\",\r\n \"version\": 1\r\n },\r\n \"workload_gid\": 65534,\r\n \"workload_uid\": 65534\r\n}\r\n"},"state/runtime.json":{"text":"{\n \"format\": 4,\n \"launch\": \"{hex32}\",\n \"process\": {\n \"pid\": {int},\n \"startTime\": {int},\n \"boot\": \"{hex32}\"\n },\n \"endpoint\": \"//./pipe/openvmm-microvm-{hex32}\",\n \"runtime\": {\n \"openvmm\": \"sha256:1e8c924cdaac227bf74b4a4a9bcdb9e8836a1355fd0408cc81dab5d9aa71eb4d\",\n \"kernel\": \"sha256:a0c936696eb7d5ee3192bf53b9d281cecbb40ca9db520de72cb95817ad92ac72\",\n \"initramfs\": \"sha256:2f77c2c97621e8bf69794e9d12815bb7c46338638f126bea8b18dfe02a684d62\",\n \"bootContract\": 3,\n \"controlContract\": \"nvx-microvm-v2-control-v2\",\n \"controlSession\": 1\n }\n}\n"},"state/control.capability":{"size":32},"state/outcome.json":null,"state/openvmm.log":{"text":""}}},{"argv":["sandbox","stop","--state-dir","{root}\\state"],"check":["state","state/config.json","state/runtime.json","state/control.capability","state/outcome.json","state/openvmm.log"],"status":0,"stdout":"","stderr":"","files":{"state":{"entries":["config.json","openvmm.log","outcome.json","sandbox.lock"]},"state/config.json":{"text":"{\r\n \"cmdline\": \"\",\r\n \"distro_binding\": {\r\n \"format\": \"erofs\",\r\n \"identity\": \"11111111-1111-1111-1111-111111111111\",\r\n \"image\": {\r\n \"changed\": null,\r\n \"device\": {int},\r\n \"fileId\": \"{hex32}\",\r\n \"kind\": \"regular\",\r\n \"length\": 7,\r\n \"modified\": {\r\n \"nanoseconds\": {int},\r\n \"seconds\": {int}\r\n },\r\n \"scheme\": \"windows\",\r\n \"version\": 1\r\n },\r\n \"manifest\": null,\r\n \"policy\": {\r\n \"result\": \"accepted\",\r\n \"revision\": 1\r\n },\r\n \"version\": 1\r\n },\r\n \"export\": {\r\n \"binds\": [\r\n {\r\n \"child\": 0,\r\n \"readOnly\": false,\r\n \"source\": \"\",\r\n \"target\": \"/data\"\r\n }\r\n ],\r\n \"children\": [\r\n {\r\n \"allowed\": [\r\n \"{root_json}\\\\share\\\\hidden\\\\shown\"\r\n ],\r\n \"denied\": [\r\n \"{root_json}\\\\share\\\\hidden\"\r\n ],\r\n \"deniedIdentities\": [\r\n null\r\n ],\r\n \"root\": \"{root_json}\\\\share\",\r\n \"writable\": true,\r\n \"write\": [\r\n \"{root_json}\\\\share\\\\writable\"\r\n ]\r\n }\r\n ]\r\n },\r\n \"format\": 7,\r\n \"hostname\": \"nvx-sandbox\",\r\n \"hypervisor\": \"whp\",\r\n \"layers\": [\r\n {\r\n \"path\": \"{root_json}\\\\distro.erofs\",\r\n \"role\": \"distro\",\r\n \"uuid\": \"11111111-1111-1111-1111-111111111111\"\r\n }\r\n ],\r\n \"memory_max\": null,\r\n \"memory_mib\": 256,\r\n \"network\": null,\r\n \"pids_max\": null,\r\n \"scratch\": \"{root_json}\\\\scratch.ext4\",\r\n \"scratch_binding\": {\r\n \"device\": {int},\r\n \"fileId\": \"{hex32}\",\r\n \"kind\": \"regular\",\r\n \"length\": 8,\r\n \"scheme\": \"windows\",\r\n \"version\": 1\r\n },\r\n \"workload_gid\": 65534,\r\n \"workload_uid\": 65534\r\n}\r\n"},"state/runtime.json":null,"state/control.capability":null,"state/outcome.json":{"text":"{\n \"backend\": \"whp\",\n \"instance_id\": \"{hex32}\",\n \"network_policy\": {\n \"allow_rule_count\": 0,\n \"deny_rule_count\": 0,\n \"host_loopback\": \"none\",\n \"mode\": \"none\",\n \"status\": \"not-requested\",\n \"status_code\": 0\n },\n \"outcome\": {\n \"category\": \"success\",\n \"operation\": \"managed\",\n \"status_code\": 0\n },\n \"schema_version\": 1,\n \"teardown\": {\n \"control_channels_closed\": true,\n \"guest_workload_stopped\": true,\n \"network_released\": true,\n \"openvmm_process_terminated\": true,\n \"temporary_storage_removed\": true,\n \"virtiofs_released\": true,\n \"vm_stopped\": true\n }\n}\n"},"state/openvmm.log":{"text":""}}},{"argv":["sandbox","deprovision","--state-dir","{root}\\state"],"check":["state"],"status":0,"stdout":"","stderr":"","files":{"state":null}}],"interop":true}, -{"name":"lifecycle: file share","steps":[{"argv":["sandbox","provision","--state-dir","{root}\\state","--layer","distro,{root}\\distro.erofs,11111111-1111-1111-1111-111111111111","--scratch","{root}\\scratch.ext4","--mount","/etc/single.txt,{root}\\single.txt,ro"],"check":["state","state/config.json","state/runtime.json","state/control.capability","state/outcome.json","state/openvmm.log"],"status":0,"stdout":"","stderr":"","files":{"state":{"entries":["config.json","sandbox.lock"]},"state/config.json":{"text":"{\r\n \"cmdline\": \"\",\r\n \"distro_binding\": {\r\n \"format\": \"erofs\",\r\n \"identity\": \"11111111-1111-1111-1111-111111111111\",\r\n \"image\": {\r\n \"changed\": null,\r\n \"device\": {int},\r\n \"fileId\": \"{hex32}\",\r\n \"kind\": \"regular\",\r\n \"length\": 7,\r\n \"modified\": {\r\n \"nanoseconds\": {int},\r\n \"seconds\": {int}\r\n },\r\n \"scheme\": \"windows\",\r\n \"version\": 1\r\n },\r\n \"manifest\": null,\r\n \"policy\": {\r\n \"result\": \"accepted\",\r\n \"revision\": 1\r\n },\r\n \"version\": 1\r\n },\r\n \"export\": {\r\n \"binds\": [\r\n {\r\n \"child\": 0,\r\n \"readOnly\": true,\r\n \"source\": \"\",\r\n \"target\": \"/etc/single.txt\"\r\n }\r\n ],\r\n \"children\": [\r\n {\r\n \"allowed\": [],\r\n \"denied\": [],\r\n \"deniedIdentities\": [],\r\n \"file\": true,\r\n \"root\": \"{root_json}\\\\single.txt\",\r\n \"writable\": false,\r\n \"write\": []\r\n }\r\n ]\r\n },\r\n \"format\": 7,\r\n \"hostname\": \"nvx-sandbox\",\r\n \"hypervisor\": \"whp\",\r\n \"layers\": [\r\n {\r\n \"path\": \"{root_json}\\\\distro.erofs\",\r\n \"role\": \"distro\",\r\n \"uuid\": \"11111111-1111-1111-1111-111111111111\"\r\n }\r\n ],\r\n \"memory_max\": null,\r\n \"memory_mib\": 256,\r\n \"network\": null,\r\n \"pids_max\": null,\r\n \"scratch\": \"{root_json}\\\\scratch.ext4\",\r\n \"scratch_binding\": {\r\n \"device\": {int},\r\n \"fileId\": \"{hex32}\",\r\n \"kind\": \"regular\",\r\n \"length\": 8,\r\n \"scheme\": \"windows\",\r\n \"version\": 1\r\n },\r\n \"workload_gid\": 65534,\r\n \"workload_uid\": 65534\r\n}\r\n"},"state/runtime.json":null,"state/control.capability":null,"state/outcome.json":null,"state/openvmm.log":null}},{"argv":["sandbox","start","--state-dir","{root}\\state"],"check":["state","state/config.json","state/runtime.json","state/control.capability","state/outcome.json","state/openvmm.log","build/fake-openvmm-state.json"],"status":0,"stdout":"","stderr":"","files":{"state":{"entries":["config.json","control.capability","openvmm.log","runtime.json","sandbox.lock"]},"state/config.json":{"text":"{\r\n \"cmdline\": \"\",\r\n \"distro_binding\": {\r\n \"format\": \"erofs\",\r\n \"identity\": \"11111111-1111-1111-1111-111111111111\",\r\n \"image\": {\r\n \"changed\": null,\r\n \"device\": {int},\r\n \"fileId\": \"{hex32}\",\r\n \"kind\": \"regular\",\r\n \"length\": 7,\r\n \"modified\": {\r\n \"nanoseconds\": {int},\r\n \"seconds\": {int}\r\n },\r\n \"scheme\": \"windows\",\r\n \"version\": 1\r\n },\r\n \"manifest\": null,\r\n \"policy\": {\r\n \"result\": \"accepted\",\r\n \"revision\": 1\r\n },\r\n \"version\": 1\r\n },\r\n \"export\": {\r\n \"binds\": [\r\n {\r\n \"child\": 0,\r\n \"readOnly\": true,\r\n \"source\": \"\",\r\n \"target\": \"/etc/single.txt\"\r\n }\r\n ],\r\n \"children\": [\r\n {\r\n \"allowed\": [],\r\n \"denied\": [],\r\n \"deniedIdentities\": [],\r\n \"file\": true,\r\n \"root\": \"{root_json}\\\\single.txt\",\r\n \"writable\": false,\r\n \"write\": []\r\n }\r\n ]\r\n },\r\n \"format\": 7,\r\n \"hostname\": \"nvx-sandbox\",\r\n \"hypervisor\": \"whp\",\r\n \"layers\": [\r\n {\r\n \"path\": \"{root_json}\\\\distro.erofs\",\r\n \"role\": \"distro\",\r\n \"uuid\": \"11111111-1111-1111-1111-111111111111\"\r\n }\r\n ],\r\n \"memory_max\": null,\r\n \"memory_mib\": 256,\r\n \"network\": null,\r\n \"pids_max\": null,\r\n \"scratch\": \"{root_json}\\\\scratch.ext4\",\r\n \"scratch_binding\": {\r\n \"device\": {int},\r\n \"fileId\": \"{hex32}\",\r\n \"kind\": \"regular\",\r\n \"length\": 8,\r\n \"scheme\": \"windows\",\r\n \"version\": 1\r\n },\r\n \"workload_gid\": 65534,\r\n \"workload_uid\": 65534\r\n}\r\n"},"state/runtime.json":{"text":"{\n \"format\": 4,\n \"launch\": \"{hex32}\",\n \"process\": {\n \"pid\": {int},\n \"startTime\": {int},\n \"boot\": \"{hex32}\"\n },\n \"endpoint\": \"//./pipe/openvmm-microvm-{hex32}\",\n \"runtime\": {\n \"openvmm\": \"sha256:1e8c924cdaac227bf74b4a4a9bcdb9e8836a1355fd0408cc81dab5d9aa71eb4d\",\n \"kernel\": \"sha256:a0c936696eb7d5ee3192bf53b9d281cecbb40ca9db520de72cb95817ad92ac72\",\n \"initramfs\": \"sha256:2f77c2c97621e8bf69794e9d12815bb7c46338638f126bea8b18dfe02a684d62\",\n \"bootContract\": 3,\n \"controlContract\": \"nvx-microvm-v2-control-v2\",\n \"controlSession\": 1\n }\n}\n"},"state/control.capability":{"size":32},"state/outcome.json":null,"state/openvmm.log":{"text":""},"build/fake-openvmm-state.json":{"text":"[\"--machine\",\"microvm\",\"--microvm-sandbox-block\",\"distro:file:\\\\\\\\?\\\\{root_json}\\\\distro.erofs,ro\",\"--microvm-sandbox-block\",\"scratch:file:\\\\\\\\?\\\\{root_json}\\\\scratch.ext4\",\"--microvm-workload-identity\",\"65534:65534\",\"--mount-aggregate\",\"/run/nvx/shares\",\"--mount-child\",\"0-a80a05e9cb129bc27b7ba103bf2f5ac0,{root_json}\\\\single.txt,ro,file\",\"--microvm-lifecycle\",\"managed\",\"--single-process\",\"--hypervisor\",\"whp\",\"--memory\",\"256M\",\"--kernel\",\"{root_json}\\\\build\\\\vmlinux\",\"--initrd\",\"{root_json}\\\\build\\\\initramfs.cpio.gz\",\"--cmdline\",\"nvx_sandbox=1 nvx_layer=distro,0xd0003000,erofs:11111111-1111-1111-1111-111111111111 nvx_scratch=0xd0006000,ext4 nvx_entrypoint=/bin/sh nvx_hostname=nvx-sandbox nvx_share=0-a80a05e9cb129bc27b7ba103bf2f5ac0,/etc/single.txt,ro,file\",\"--virtio-console\",\"none\",\"--microvm-control-console\",\"listen=//./pipe/openvmm-microvm-{hex32}\",\"--microvm-control-auth-stdin\",\"--microvm-report\",\"{root_json}\\\\state\\\\outcome.json\"]"}}},{"argv":["sandbox","stop","--state-dir","{root}\\state"],"check":["state","state/config.json","state/runtime.json","state/control.capability","state/outcome.json","state/openvmm.log"],"status":0,"stdout":"","stderr":"","files":{"state":{"entries":["config.json","openvmm.log","outcome.json","sandbox.lock"]},"state/config.json":{"text":"{\r\n \"cmdline\": \"\",\r\n \"distro_binding\": {\r\n \"format\": \"erofs\",\r\n \"identity\": \"11111111-1111-1111-1111-111111111111\",\r\n \"image\": {\r\n \"changed\": null,\r\n \"device\": {int},\r\n \"fileId\": \"{hex32}\",\r\n \"kind\": \"regular\",\r\n \"length\": 7,\r\n \"modified\": {\r\n \"nanoseconds\": {int},\r\n \"seconds\": {int}\r\n },\r\n \"scheme\": \"windows\",\r\n \"version\": 1\r\n },\r\n \"manifest\": null,\r\n \"policy\": {\r\n \"result\": \"accepted\",\r\n \"revision\": 1\r\n },\r\n \"version\": 1\r\n },\r\n \"export\": {\r\n \"binds\": [\r\n {\r\n \"child\": 0,\r\n \"readOnly\": true,\r\n \"source\": \"\",\r\n \"target\": \"/etc/single.txt\"\r\n }\r\n ],\r\n \"children\": [\r\n {\r\n \"allowed\": [],\r\n \"denied\": [],\r\n \"deniedIdentities\": [],\r\n \"file\": true,\r\n \"root\": \"{root_json}\\\\single.txt\",\r\n \"writable\": false,\r\n \"write\": []\r\n }\r\n ]\r\n },\r\n \"format\": 7,\r\n \"hostname\": \"nvx-sandbox\",\r\n \"hypervisor\": \"whp\",\r\n \"layers\": [\r\n {\r\n \"path\": \"{root_json}\\\\distro.erofs\",\r\n \"role\": \"distro\",\r\n \"uuid\": \"11111111-1111-1111-1111-111111111111\"\r\n }\r\n ],\r\n \"memory_max\": null,\r\n \"memory_mib\": 256,\r\n \"network\": null,\r\n \"pids_max\": null,\r\n \"scratch\": \"{root_json}\\\\scratch.ext4\",\r\n \"scratch_binding\": {\r\n \"device\": {int},\r\n \"fileId\": \"{hex32}\",\r\n \"kind\": \"regular\",\r\n \"length\": 8,\r\n \"scheme\": \"windows\",\r\n \"version\": 1\r\n },\r\n \"workload_gid\": 65534,\r\n \"workload_uid\": 65534\r\n}\r\n"},"state/runtime.json":null,"state/control.capability":null,"state/outcome.json":{"text":"{\n \"backend\": \"whp\",\n \"instance_id\": \"{hex32}\",\n \"network_policy\": {\n \"allow_rule_count\": 0,\n \"deny_rule_count\": 0,\n \"host_loopback\": \"none\",\n \"mode\": \"none\",\n \"status\": \"not-requested\",\n \"status_code\": 0\n },\n \"outcome\": {\n \"category\": \"success\",\n \"operation\": \"managed\",\n \"status_code\": 0\n },\n \"schema_version\": 1,\n \"teardown\": {\n \"control_channels_closed\": true,\n \"guest_workload_stopped\": true,\n \"network_released\": true,\n \"openvmm_process_terminated\": true,\n \"temporary_storage_removed\": true,\n \"virtiofs_released\": true,\n \"vm_stopped\": true\n }\n}\n"},"state/openvmm.log":{"text":""}}},{"argv":["sandbox","start","--state-dir","{root}\\state"],"check":["state","state/config.json","state/runtime.json","state/control.capability","state/outcome.json","state/openvmm.log"],"status":0,"stdout":"","stderr":"","files":{"state":{"entries":["config.json","control.capability","openvmm.log","runtime.json","sandbox.lock"]},"state/config.json":{"text":"{\r\n \"cmdline\": \"\",\r\n \"distro_binding\": {\r\n \"format\": \"erofs\",\r\n \"identity\": \"11111111-1111-1111-1111-111111111111\",\r\n \"image\": {\r\n \"changed\": null,\r\n \"device\": {int},\r\n \"fileId\": \"{hex32}\",\r\n \"kind\": \"regular\",\r\n \"length\": 7,\r\n \"modified\": {\r\n \"nanoseconds\": {int},\r\n \"seconds\": {int}\r\n },\r\n \"scheme\": \"windows\",\r\n \"version\": 1\r\n },\r\n \"manifest\": null,\r\n \"policy\": {\r\n \"result\": \"accepted\",\r\n \"revision\": 1\r\n },\r\n \"version\": 1\r\n },\r\n \"export\": {\r\n \"binds\": [\r\n {\r\n \"child\": 0,\r\n \"readOnly\": true,\r\n \"source\": \"\",\r\n \"target\": \"/etc/single.txt\"\r\n }\r\n ],\r\n \"children\": [\r\n {\r\n \"allowed\": [],\r\n \"denied\": [],\r\n \"deniedIdentities\": [],\r\n \"file\": true,\r\n \"root\": \"{root_json}\\\\single.txt\",\r\n \"writable\": false,\r\n \"write\": []\r\n }\r\n ]\r\n },\r\n \"format\": 7,\r\n \"hostname\": \"nvx-sandbox\",\r\n \"hypervisor\": \"whp\",\r\n \"layers\": [\r\n {\r\n \"path\": \"{root_json}\\\\distro.erofs\",\r\n \"role\": \"distro\",\r\n \"uuid\": \"11111111-1111-1111-1111-111111111111\"\r\n }\r\n ],\r\n \"memory_max\": null,\r\n \"memory_mib\": 256,\r\n \"network\": null,\r\n \"pids_max\": null,\r\n \"scratch\": \"{root_json}\\\\scratch.ext4\",\r\n \"scratch_binding\": {\r\n \"device\": {int},\r\n \"fileId\": \"{hex32}\",\r\n \"kind\": \"regular\",\r\n \"length\": 8,\r\n \"scheme\": \"windows\",\r\n \"version\": 1\r\n },\r\n \"workload_gid\": 65534,\r\n \"workload_uid\": 65534\r\n}\r\n"},"state/runtime.json":{"text":"{\n \"format\": 4,\n \"launch\": \"{hex32}\",\n \"process\": {\n \"pid\": {int},\n \"startTime\": {int},\n \"boot\": \"{hex32}\"\n },\n \"endpoint\": \"//./pipe/openvmm-microvm-{hex32}\",\n \"runtime\": {\n \"openvmm\": \"sha256:1e8c924cdaac227bf74b4a4a9bcdb9e8836a1355fd0408cc81dab5d9aa71eb4d\",\n \"kernel\": \"sha256:a0c936696eb7d5ee3192bf53b9d281cecbb40ca9db520de72cb95817ad92ac72\",\n \"initramfs\": \"sha256:2f77c2c97621e8bf69794e9d12815bb7c46338638f126bea8b18dfe02a684d62\",\n \"bootContract\": 3,\n \"controlContract\": \"nvx-microvm-v2-control-v2\",\n \"controlSession\": 1\n }\n}\n"},"state/control.capability":{"size":32},"state/outcome.json":null,"state/openvmm.log":{"text":""}}},{"argv":["sandbox","stop","--state-dir","{root}\\state"],"check":["state","state/config.json","state/runtime.json","state/control.capability","state/outcome.json","state/openvmm.log"],"status":0,"stdout":"","stderr":"","files":{"state":{"entries":["config.json","openvmm.log","outcome.json","sandbox.lock"]},"state/config.json":{"text":"{\r\n \"cmdline\": \"\",\r\n \"distro_binding\": {\r\n \"format\": \"erofs\",\r\n \"identity\": \"11111111-1111-1111-1111-111111111111\",\r\n \"image\": {\r\n \"changed\": null,\r\n \"device\": {int},\r\n \"fileId\": \"{hex32}\",\r\n \"kind\": \"regular\",\r\n \"length\": 7,\r\n \"modified\": {\r\n \"nanoseconds\": {int},\r\n \"seconds\": {int}\r\n },\r\n \"scheme\": \"windows\",\r\n \"version\": 1\r\n },\r\n \"manifest\": null,\r\n \"policy\": {\r\n \"result\": \"accepted\",\r\n \"revision\": 1\r\n },\r\n \"version\": 1\r\n },\r\n \"export\": {\r\n \"binds\": [\r\n {\r\n \"child\": 0,\r\n \"readOnly\": true,\r\n \"source\": \"\",\r\n \"target\": \"/etc/single.txt\"\r\n }\r\n ],\r\n \"children\": [\r\n {\r\n \"allowed\": [],\r\n \"denied\": [],\r\n \"deniedIdentities\": [],\r\n \"file\": true,\r\n \"root\": \"{root_json}\\\\single.txt\",\r\n \"writable\": false,\r\n \"write\": []\r\n }\r\n ]\r\n },\r\n \"format\": 7,\r\n \"hostname\": \"nvx-sandbox\",\r\n \"hypervisor\": \"whp\",\r\n \"layers\": [\r\n {\r\n \"path\": \"{root_json}\\\\distro.erofs\",\r\n \"role\": \"distro\",\r\n \"uuid\": \"11111111-1111-1111-1111-111111111111\"\r\n }\r\n ],\r\n \"memory_max\": null,\r\n \"memory_mib\": 256,\r\n \"network\": null,\r\n \"pids_max\": null,\r\n \"scratch\": \"{root_json}\\\\scratch.ext4\",\r\n \"scratch_binding\": {\r\n \"device\": {int},\r\n \"fileId\": \"{hex32}\",\r\n \"kind\": \"regular\",\r\n \"length\": 8,\r\n \"scheme\": \"windows\",\r\n \"version\": 1\r\n },\r\n \"workload_gid\": 65534,\r\n \"workload_uid\": 65534\r\n}\r\n"},"state/runtime.json":null,"state/control.capability":null,"state/outcome.json":{"text":"{\n \"backend\": \"whp\",\n \"instance_id\": \"{hex32}\",\n \"network_policy\": {\n \"allow_rule_count\": 0,\n \"deny_rule_count\": 0,\n \"host_loopback\": \"none\",\n \"mode\": \"none\",\n \"status\": \"not-requested\",\n \"status_code\": 0\n },\n \"outcome\": {\n \"category\": \"success\",\n \"operation\": \"managed\",\n \"status_code\": 0\n },\n \"schema_version\": 1,\n \"teardown\": {\n \"control_channels_closed\": true,\n \"guest_workload_stopped\": true,\n \"network_released\": true,\n \"openvmm_process_terminated\": true,\n \"temporary_storage_removed\": true,\n \"virtiofs_released\": true,\n \"vm_stopped\": true\n }\n}\n"},"state/openvmm.log":{"text":""}}},{"argv":["sandbox","deprovision","--state-dir","{root}\\state"],"check":["state"],"status":0,"stdout":"","stderr":"","files":{"state":null}}],"interop":true}, +{"name":"lifecycle: minimal","steps":[{"argv":["sandbox","provision","--state-dir","{root}\\state","--layer","distro,{root}\\distro.erofs,11111111-1111-1111-1111-111111111111","--scratch","{root}\\scratch.ext4"],"check":["state","state/config.json","state/runtime.json","state/control.capability","state/outcome.json","state/openvmm.log"],"status":0,"stdout":"","stderr":"","files":{"state":{"entries":["config.json","sandbox.lock"]},"state/config.json":{"text":"{\r\n \"cmdline\": \"\",\r\n \"distro_binding\": {\r\n \"format\": \"erofs\",\r\n \"identity\": \"11111111-1111-1111-1111-111111111111\",\r\n \"image\": {\r\n \"changed\": null,\r\n \"device\": {int},\r\n \"fileId\": \"{hex32}\",\r\n \"kind\": \"regular\",\r\n \"length\": 7,\r\n \"modified\": {\r\n \"nanoseconds\": {int},\r\n \"seconds\": {int}\r\n },\r\n \"scheme\": \"windows\",\r\n \"version\": 1\r\n },\r\n \"manifest\": null,\r\n \"policy\": {\r\n \"result\": \"accepted\",\r\n \"revision\": 1\r\n },\r\n \"version\": 1\r\n },\r\n \"format\": 1,\r\n \"hostname\": \"nvx-sandbox\",\r\n \"hypervisor\": \"whp\",\r\n \"layers\": [\r\n {\r\n \"path\": \"{root_json}\\\\distro.erofs\",\r\n \"role\": \"distro\",\r\n \"uuid\": \"11111111-1111-1111-1111-111111111111\"\r\n }\r\n ],\r\n \"memory_max\": null,\r\n \"memory_mib\": 256,\r\n \"mount\": null,\r\n \"network\": null,\r\n \"pids_max\": null,\r\n \"scratch\": \"{root_json}\\\\scratch.ext4\",\r\n \"scratch_binding\": {\r\n \"device\": {int},\r\n \"fileId\": \"{hex32}\",\r\n \"kind\": \"regular\",\r\n \"length\": 8,\r\n \"scheme\": \"windows\",\r\n \"version\": 1\r\n },\r\n \"workload_gid\": 65534,\r\n \"workload_uid\": 65534\r\n}\r\n"},"state/runtime.json":null,"state/control.capability":null,"state/outcome.json":null,"state/openvmm.log":null}},{"argv":["sandbox","start","--state-dir","{root}\\state"],"check":["state","state/config.json","state/runtime.json","state/control.capability","state/outcome.json","state/openvmm.log","build/fake-openvmm-state.json","build/fake-openvmm-state-maps.json"],"status":0,"stdout":"","stderr":"","files":{"state":{"entries":["config.json","control.capability","openvmm.log","runtime.json","sandbox.lock"]},"state/config.json":{"text":"{\r\n \"cmdline\": \"\",\r\n \"distro_binding\": {\r\n \"format\": \"erofs\",\r\n \"identity\": \"11111111-1111-1111-1111-111111111111\",\r\n \"image\": {\r\n \"changed\": null,\r\n \"device\": {int},\r\n \"fileId\": \"{hex32}\",\r\n \"kind\": \"regular\",\r\n \"length\": 7,\r\n \"modified\": {\r\n \"nanoseconds\": {int},\r\n \"seconds\": {int}\r\n },\r\n \"scheme\": \"windows\",\r\n \"version\": 1\r\n },\r\n \"manifest\": null,\r\n \"policy\": {\r\n \"result\": \"accepted\",\r\n \"revision\": 1\r\n },\r\n \"version\": 1\r\n },\r\n \"format\": 1,\r\n \"hostname\": \"nvx-sandbox\",\r\n \"hypervisor\": \"whp\",\r\n \"layers\": [\r\n {\r\n \"path\": \"{root_json}\\\\distro.erofs\",\r\n \"role\": \"distro\",\r\n \"uuid\": \"11111111-1111-1111-1111-111111111111\"\r\n }\r\n ],\r\n \"memory_max\": null,\r\n \"memory_mib\": 256,\r\n \"mount\": null,\r\n \"network\": null,\r\n \"pids_max\": null,\r\n \"scratch\": \"{root_json}\\\\scratch.ext4\",\r\n \"scratch_binding\": {\r\n \"device\": {int},\r\n \"fileId\": \"{hex32}\",\r\n \"kind\": \"regular\",\r\n \"length\": 8,\r\n \"scheme\": \"windows\",\r\n \"version\": 1\r\n },\r\n \"workload_gid\": 65534,\r\n \"workload_uid\": 65534\r\n}\r\n"},"state/runtime.json":{"text":"{\n \"format\": 4,\n \"launch\": \"{hex32}\",\n \"process\": {\n \"pid\": {int},\n \"startTime\": {int},\n \"boot\": \"{hex32}\"\n },\n \"endpoint\": \"//./pipe/openvmm-microvm-{hex32}\",\n \"runtime\": {\n \"openvmm\": \"sha256:1e8c924cdaac227bf74b4a4a9bcdb9e8836a1355fd0408cc81dab5d9aa71eb4d\",\n \"kernel\": \"sha256:a0c936696eb7d5ee3192bf53b9d281cecbb40ca9db520de72cb95817ad92ac72\",\n \"initramfs\": \"sha256:2f77c2c97621e8bf69794e9d12815bb7c46338638f126bea8b18dfe02a684d62\",\n \"bootContract\": 3,\n \"controlContract\": \"nvx-microvm-v2-control-v2\",\n \"controlSession\": 1\n }\n}\n"},"state/control.capability":{"size":32},"state/outcome.json":null,"state/openvmm.log":{"text":""},"build/fake-openvmm-state.json":{"text":"[\"--machine\",\"microvm\",\"--microvm-sandbox-block\",\"distro:file:\\\\\\\\?\\\\{root_json}\\\\distro.erofs,ro\",\"--microvm-sandbox-block\",\"scratch:file:\\\\\\\\?\\\\{root_json}\\\\scratch.ext4\",\"--microvm-workload-identity\",\"65534:65534\",\"--microvm-lifecycle\",\"managed\",\"--single-process\",\"--hypervisor\",\"whp\",\"--memory\",\"256M\",\"--kernel\",\"{root_json}\\\\build\\\\vmlinux\",\"--initrd\",\"{root_json}\\\\build\\\\initramfs.cpio.gz\",\"--cmdline\",\"nvx_sandbox=1 nvx_layer=distro,0xd0003000,erofs:11111111-1111-1111-1111-111111111111 nvx_scratch=0xd0006000,ext4 nvx_entrypoint=/bin/sh nvx_hostname=nvx-sandbox\",\"--virtio-console\",\"none\",\"--microvm-control-console\",\"listen=//./pipe/openvmm-microvm-{hex32}\",\"--microvm-control-auth-stdin\",\"--microvm-report\",\"{root_json}\\\\state\\\\outcome.json\"]"},"build/fake-openvmm-state-maps.json":null}},{"argv":["sandbox","exec","--state-dir","{root}\\state","--entrypoint","/bin/echo","--arg","hello","--arg","world"],"status":0,"stdout":"hello world\n","stderr":""},{"argv":["sandbox","exec","--state-dir","{root}\\state","--entrypoint","/bin/pwd","--cwd","/tmp"],"status":0,"stdout":"/tmp\n","stderr":""},{"argv":["sandbox","exec","--state-dir","{root}\\state","--entrypoint","/bin/sh","--arg=-c","--arg","echo out; echoerr err; exit 3","--outcome-report","{root}\\reports\\exec.json"],"check":["reports/exec.json"],"status":3,"stdout":"out\n","stderr":"err\n","files":{"reports/exec.json":{"text":"{\n \"operation_id\": \"{hex32}\",\n \"outcome\": {\n \"category\": \"exit\",\n \"operation\": \"exec\",\n \"status_code\": 3\n },\n \"schema_version\": 1\n}\n"}}},{"argv":["sandbox","exec","--state-dir","{root}\\state","--entrypoint","/usr/bin/env","--environment","A=1","--environment","B=two"],"status":0,"stdout":"A=1\nB=two\n","stderr":""},{"argv":["sandbox","exec","--state-dir","{root}\\state","--entrypoint","/usr/bin/printenv","--arg","PATH","--inherit-default-environment","--environment","A=1"],"status":0,"stdout":"/usr/sbin:/usr/bin:/sbin:/bin\n","stderr":""},{"argv":["sandbox","exec","--state-dir","{root}\\state","--entrypoint","/usr/bin/env","--environment-file","{root}\\env.json"],"write":{"env.json":"[\"X=1\", \"Y=two words\"]"},"status":0,"stdout":"X=1\nY=two words\n","stderr":""},{"argv":["sandbox","exec","--state-dir","{root}\\state","--entrypoint","/usr/bin/env","--environment-file","{root}\\empty.json"],"write":{"empty.json":"[]"},"status":0,"stdout":"","stderr":""},{"argv":["sandbox","exec","--state-dir","{root}\\state","--entrypoint","/bin/sh","--arg=-c","--arg","sleep 5000","--exec-timeout-ms","50","--outcome-report","{root}\\reports\\exec-timeout.json"],"check":["reports/exec-timeout.json"],"status":124,"stdout":"","stderr":"","files":{"reports/exec-timeout.json":{"text":"{\n \"operation_id\": \"{hex32}\",\n \"outcome\": {\n \"category\": \"timeout\",\n \"operation\": \"exec\",\n \"status_code\": 124\n },\n \"schema_version\": 1\n}\n"}}},{"argv":["sandbox","exec","--state-dir","{root}\\state","--entrypoint","/bin/sh","--arg=-c","--arg","signal 9"],"status":137,"stdout":"","stderr":""},{"argv":["sandbox","exec","--state-dir","{root}\\state","--entrypoint","/bin/missing"],"status":127,"stdout":"","stderr":"openvmm: /bin/missing: not found\n"},{"argv":["sandbox","exec","--state-dir","{root}\\state","--entrypoint","/bin/pwd","--cwd","/missing"],"status":1,"stdout":"","stderr":"error: managed guest rejected exec (status=2, category=cwd-failed)\r\n"},{"argv":["sandbox","exec","--state-dir","{root}\\state","--entrypoint","/bin/pwd","--cwd","relative"],"status":1,"stdout":"","stderr":"error: managed exec working directory must be an absolute path of at most 4096 bytes\r\n"},{"argv":["sandbox","exec","--state-dir","{root}\\state","--entrypoint","/bin/echo","--outcome-report","{root}\\reports\\exec.json"],"status":1,"stdout":"","stderr":"error: outcome report already exists: {root}\\reports\\exec.json\r\n"},{"argv":["sandbox","exec","--state-dir","{root}\\state","--entrypoint","/bin/echo","--outcome-report","{root}\\missing\\exec.json"],"status":1,"stdout":"","stderr":"error: outcome report parent is not a plain directory: {root}\\missing\r\n"},{"argv":["sandbox","stop","--state-dir","{root}\\state"],"check":["state","state/config.json","state/runtime.json","state/control.capability","state/outcome.json","state/openvmm.log"],"status":0,"stdout":"","stderr":"","files":{"state":{"entries":["config.json","openvmm.log","outcome.json","sandbox.lock"]},"state/config.json":{"text":"{\r\n \"cmdline\": \"\",\r\n \"distro_binding\": {\r\n \"format\": \"erofs\",\r\n \"identity\": \"11111111-1111-1111-1111-111111111111\",\r\n \"image\": {\r\n \"changed\": null,\r\n \"device\": {int},\r\n \"fileId\": \"{hex32}\",\r\n \"kind\": \"regular\",\r\n \"length\": 7,\r\n \"modified\": {\r\n \"nanoseconds\": {int},\r\n \"seconds\": {int}\r\n },\r\n \"scheme\": \"windows\",\r\n \"version\": 1\r\n },\r\n \"manifest\": null,\r\n \"policy\": {\r\n \"result\": \"accepted\",\r\n \"revision\": 1\r\n },\r\n \"version\": 1\r\n },\r\n \"format\": 1,\r\n \"hostname\": \"nvx-sandbox\",\r\n \"hypervisor\": \"whp\",\r\n \"layers\": [\r\n {\r\n \"path\": \"{root_json}\\\\distro.erofs\",\r\n \"role\": \"distro\",\r\n \"uuid\": \"11111111-1111-1111-1111-111111111111\"\r\n }\r\n ],\r\n \"memory_max\": null,\r\n \"memory_mib\": 256,\r\n \"mount\": null,\r\n \"network\": null,\r\n \"pids_max\": null,\r\n \"scratch\": \"{root_json}\\\\scratch.ext4\",\r\n \"scratch_binding\": {\r\n \"device\": {int},\r\n \"fileId\": \"{hex32}\",\r\n \"kind\": \"regular\",\r\n \"length\": 8,\r\n \"scheme\": \"windows\",\r\n \"version\": 1\r\n },\r\n \"workload_gid\": 65534,\r\n \"workload_uid\": 65534\r\n}\r\n"},"state/runtime.json":null,"state/control.capability":null,"state/outcome.json":{"text":"{\n \"backend\": \"whp\",\n \"instance_id\": \"{hex32}\",\n \"network_policy\": {\n \"allow_rule_count\": 0,\n \"deny_rule_count\": 0,\n \"host_loopback\": \"none\",\n \"mode\": \"none\",\n \"status\": \"not-requested\",\n \"status_code\": 0\n },\n \"outcome\": {\n \"category\": \"success\",\n \"operation\": \"managed\",\n \"status_code\": 0\n },\n \"schema_version\": 1,\n \"teardown\": {\n \"control_channels_closed\": true,\n \"guest_workload_stopped\": true,\n \"network_released\": true,\n \"openvmm_process_terminated\": true,\n \"temporary_storage_removed\": true,\n \"virtiofs_released\": true,\n \"vm_stopped\": true\n }\n}\n"},"state/openvmm.log":{"text":""}}},{"argv":["sandbox","start","--state-dir","{root}\\state"],"check":["state","state/config.json","state/runtime.json","state/control.capability","state/outcome.json","state/openvmm.log"],"status":0,"stdout":"","stderr":"","files":{"state":{"entries":["config.json","control.capability","openvmm.log","runtime.json","sandbox.lock"]},"state/config.json":{"text":"{\r\n \"cmdline\": \"\",\r\n \"distro_binding\": {\r\n \"format\": \"erofs\",\r\n \"identity\": \"11111111-1111-1111-1111-111111111111\",\r\n \"image\": {\r\n \"changed\": null,\r\n \"device\": {int},\r\n \"fileId\": \"{hex32}\",\r\n \"kind\": \"regular\",\r\n \"length\": 7,\r\n \"modified\": {\r\n \"nanoseconds\": {int},\r\n \"seconds\": {int}\r\n },\r\n \"scheme\": \"windows\",\r\n \"version\": 1\r\n },\r\n \"manifest\": null,\r\n \"policy\": {\r\n \"result\": \"accepted\",\r\n \"revision\": 1\r\n },\r\n \"version\": 1\r\n },\r\n \"format\": 1,\r\n \"hostname\": \"nvx-sandbox\",\r\n \"hypervisor\": \"whp\",\r\n \"layers\": [\r\n {\r\n \"path\": \"{root_json}\\\\distro.erofs\",\r\n \"role\": \"distro\",\r\n \"uuid\": \"11111111-1111-1111-1111-111111111111\"\r\n }\r\n ],\r\n \"memory_max\": null,\r\n \"memory_mib\": 256,\r\n \"mount\": null,\r\n \"network\": null,\r\n \"pids_max\": null,\r\n \"scratch\": \"{root_json}\\\\scratch.ext4\",\r\n \"scratch_binding\": {\r\n \"device\": {int},\r\n \"fileId\": \"{hex32}\",\r\n \"kind\": \"regular\",\r\n \"length\": 8,\r\n \"scheme\": \"windows\",\r\n \"version\": 1\r\n },\r\n \"workload_gid\": 65534,\r\n \"workload_uid\": 65534\r\n}\r\n"},"state/runtime.json":{"text":"{\n \"format\": 4,\n \"launch\": \"{hex32}\",\n \"process\": {\n \"pid\": {int},\n \"startTime\": {int},\n \"boot\": \"{hex32}\"\n },\n \"endpoint\": \"//./pipe/openvmm-microvm-{hex32}\",\n \"runtime\": {\n \"openvmm\": \"sha256:1e8c924cdaac227bf74b4a4a9bcdb9e8836a1355fd0408cc81dab5d9aa71eb4d\",\n \"kernel\": \"sha256:a0c936696eb7d5ee3192bf53b9d281cecbb40ca9db520de72cb95817ad92ac72\",\n \"initramfs\": \"sha256:2f77c2c97621e8bf69794e9d12815bb7c46338638f126bea8b18dfe02a684d62\",\n \"bootContract\": 3,\n \"controlContract\": \"nvx-microvm-v2-control-v2\",\n \"controlSession\": 1\n }\n}\n"},"state/control.capability":{"size":32},"state/outcome.json":null,"state/openvmm.log":{"text":""}}},{"argv":["sandbox","stop","--state-dir","{root}\\state"],"check":["state","state/config.json","state/runtime.json","state/control.capability","state/outcome.json","state/openvmm.log"],"status":0,"stdout":"","stderr":"","files":{"state":{"entries":["config.json","openvmm.log","outcome.json","sandbox.lock"]},"state/config.json":{"text":"{\r\n \"cmdline\": \"\",\r\n \"distro_binding\": {\r\n \"format\": \"erofs\",\r\n \"identity\": \"11111111-1111-1111-1111-111111111111\",\r\n \"image\": {\r\n \"changed\": null,\r\n \"device\": {int},\r\n \"fileId\": \"{hex32}\",\r\n \"kind\": \"regular\",\r\n \"length\": 7,\r\n \"modified\": {\r\n \"nanoseconds\": {int},\r\n \"seconds\": {int}\r\n },\r\n \"scheme\": \"windows\",\r\n \"version\": 1\r\n },\r\n \"manifest\": null,\r\n \"policy\": {\r\n \"result\": \"accepted\",\r\n \"revision\": 1\r\n },\r\n \"version\": 1\r\n },\r\n \"format\": 1,\r\n \"hostname\": \"nvx-sandbox\",\r\n \"hypervisor\": \"whp\",\r\n \"layers\": [\r\n {\r\n \"path\": \"{root_json}\\\\distro.erofs\",\r\n \"role\": \"distro\",\r\n \"uuid\": \"11111111-1111-1111-1111-111111111111\"\r\n }\r\n ],\r\n \"memory_max\": null,\r\n \"memory_mib\": 256,\r\n \"mount\": null,\r\n \"network\": null,\r\n \"pids_max\": null,\r\n \"scratch\": \"{root_json}\\\\scratch.ext4\",\r\n \"scratch_binding\": {\r\n \"device\": {int},\r\n \"fileId\": \"{hex32}\",\r\n \"kind\": \"regular\",\r\n \"length\": 8,\r\n \"scheme\": \"windows\",\r\n \"version\": 1\r\n },\r\n \"workload_gid\": 65534,\r\n \"workload_uid\": 65534\r\n}\r\n"},"state/runtime.json":null,"state/control.capability":null,"state/outcome.json":{"text":"{\n \"backend\": \"whp\",\n \"instance_id\": \"{hex32}\",\n \"network_policy\": {\n \"allow_rule_count\": 0,\n \"deny_rule_count\": 0,\n \"host_loopback\": \"none\",\n \"mode\": \"none\",\n \"status\": \"not-requested\",\n \"status_code\": 0\n },\n \"outcome\": {\n \"category\": \"success\",\n \"operation\": \"managed\",\n \"status_code\": 0\n },\n \"schema_version\": 1,\n \"teardown\": {\n \"control_channels_closed\": true,\n \"guest_workload_stopped\": true,\n \"network_released\": true,\n \"openvmm_process_terminated\": true,\n \"temporary_storage_removed\": true,\n \"virtiofs_released\": true,\n \"vm_stopped\": true\n }\n}\n"},"state/openvmm.log":{"text":""}}},{"argv":["sandbox","deprovision","--state-dir","{root}\\state"],"check":["state"],"status":0,"stdout":"","stderr":"","files":{"state":null}}],"interop":true}, +{"name":"lifecycle: one share","steps":[{"argv":["sandbox","provision","--state-dir","{root}\\state","--layer","distro,{root}\\distro.erofs,11111111-1111-1111-1111-111111111111","--scratch","{root}\\scratch.ext4","--mount","/data,{root}\\share"],"check":["state","state/config.json","state/runtime.json","state/control.capability","state/outcome.json","state/openvmm.log"],"status":0,"stdout":"","stderr":"","files":{"state":{"entries":["config.json","sandbox.lock"]},"state/config.json":{"text":"{\r\n \"cmdline\": \"\",\r\n \"distro_binding\": {\r\n \"format\": \"erofs\",\r\n \"identity\": \"11111111-1111-1111-1111-111111111111\",\r\n \"image\": {\r\n \"changed\": null,\r\n \"device\": {int},\r\n \"fileId\": \"{hex32}\",\r\n \"kind\": \"regular\",\r\n \"length\": 7,\r\n \"modified\": {\r\n \"nanoseconds\": {int},\r\n \"seconds\": {int}\r\n },\r\n \"scheme\": \"windows\",\r\n \"version\": 1\r\n },\r\n \"manifest\": null,\r\n \"policy\": {\r\n \"result\": \"accepted\",\r\n \"revision\": 1\r\n },\r\n \"version\": 1\r\n },\r\n \"export\": {\r\n \"binds\": [\r\n {\r\n \"child\": 0,\r\n \"readOnly\": true,\r\n \"source\": \"\",\r\n \"target\": \"/data\"\r\n }\r\n ],\r\n \"children\": [\r\n {\r\n \"allowed\": [],\r\n \"denied\": [],\r\n \"deniedIdentities\": [],\r\n \"root\": \"{root_json}\\\\share\",\r\n \"writable\": false,\r\n \"write\": []\r\n }\r\n ]\r\n },\r\n \"format\": 7,\r\n \"hostname\": \"nvx-sandbox\",\r\n \"hypervisor\": \"whp\",\r\n \"layers\": [\r\n {\r\n \"path\": \"{root_json}\\\\distro.erofs\",\r\n \"role\": \"distro\",\r\n \"uuid\": \"11111111-1111-1111-1111-111111111111\"\r\n }\r\n ],\r\n \"memory_max\": null,\r\n \"memory_mib\": 256,\r\n \"network\": null,\r\n \"pids_max\": null,\r\n \"scratch\": \"{root_json}\\\\scratch.ext4\",\r\n \"scratch_binding\": {\r\n \"device\": {int},\r\n \"fileId\": \"{hex32}\",\r\n \"kind\": \"regular\",\r\n \"length\": 8,\r\n \"scheme\": \"windows\",\r\n \"version\": 1\r\n },\r\n \"workload_gid\": 65534,\r\n \"workload_uid\": 65534\r\n}\r\n"},"state/runtime.json":null,"state/control.capability":null,"state/outcome.json":null,"state/openvmm.log":null}},{"argv":["sandbox","start","--state-dir","{root}\\state"],"check":["state","state/config.json","state/runtime.json","state/control.capability","state/outcome.json","state/openvmm.log","build/fake-openvmm-state.json","build/fake-openvmm-state-maps.json"],"status":0,"stdout":"","stderr":"","files":{"state":{"entries":["config.json","control.capability","openvmm.log","runtime.json","sandbox.lock"]},"state/config.json":{"text":"{\r\n \"cmdline\": \"\",\r\n \"distro_binding\": {\r\n \"format\": \"erofs\",\r\n \"identity\": \"11111111-1111-1111-1111-111111111111\",\r\n \"image\": {\r\n \"changed\": null,\r\n \"device\": {int},\r\n \"fileId\": \"{hex32}\",\r\n \"kind\": \"regular\",\r\n \"length\": 7,\r\n \"modified\": {\r\n \"nanoseconds\": {int},\r\n \"seconds\": {int}\r\n },\r\n \"scheme\": \"windows\",\r\n \"version\": 1\r\n },\r\n \"manifest\": null,\r\n \"policy\": {\r\n \"result\": \"accepted\",\r\n \"revision\": 1\r\n },\r\n \"version\": 1\r\n },\r\n \"export\": {\r\n \"binds\": [\r\n {\r\n \"child\": 0,\r\n \"readOnly\": true,\r\n \"source\": \"\",\r\n \"target\": \"/data\"\r\n }\r\n ],\r\n \"children\": [\r\n {\r\n \"allowed\": [],\r\n \"denied\": [],\r\n \"deniedIdentities\": [],\r\n \"root\": \"{root_json}\\\\share\",\r\n \"writable\": false,\r\n \"write\": []\r\n }\r\n ]\r\n },\r\n \"format\": 7,\r\n \"hostname\": \"nvx-sandbox\",\r\n \"hypervisor\": \"whp\",\r\n \"layers\": [\r\n {\r\n \"path\": \"{root_json}\\\\distro.erofs\",\r\n \"role\": \"distro\",\r\n \"uuid\": \"11111111-1111-1111-1111-111111111111\"\r\n }\r\n ],\r\n \"memory_max\": null,\r\n \"memory_mib\": 256,\r\n \"network\": null,\r\n \"pids_max\": null,\r\n \"scratch\": \"{root_json}\\\\scratch.ext4\",\r\n \"scratch_binding\": {\r\n \"device\": {int},\r\n \"fileId\": \"{hex32}\",\r\n \"kind\": \"regular\",\r\n \"length\": 8,\r\n \"scheme\": \"windows\",\r\n \"version\": 1\r\n },\r\n \"workload_gid\": 65534,\r\n \"workload_uid\": 65534\r\n}\r\n"},"state/runtime.json":{"text":"{\n \"format\": 4,\n \"launch\": \"{hex32}\",\n \"process\": {\n \"pid\": {int},\n \"startTime\": {int},\n \"boot\": \"{hex32}\"\n },\n \"endpoint\": \"//./pipe/openvmm-microvm-{hex32}\",\n \"runtime\": {\n \"openvmm\": \"sha256:1e8c924cdaac227bf74b4a4a9bcdb9e8836a1355fd0408cc81dab5d9aa71eb4d\",\n \"kernel\": \"sha256:a0c936696eb7d5ee3192bf53b9d281cecbb40ca9db520de72cb95817ad92ac72\",\n \"initramfs\": \"sha256:2f77c2c97621e8bf69794e9d12815bb7c46338638f126bea8b18dfe02a684d62\",\n \"bootContract\": 3,\n \"controlContract\": \"nvx-microvm-v2-control-v2\",\n \"controlSession\": 1\n }\n}\n"},"state/control.capability":{"size":32},"state/outcome.json":null,"state/openvmm.log":{"text":""},"build/fake-openvmm-state.json":{"text":"[\"--machine\",\"microvm\",\"--microvm-sandbox-block\",\"distro:file:\\\\\\\\?\\\\{root_json}\\\\distro.erofs,ro\",\"--microvm-sandbox-block\",\"scratch:file:\\\\\\\\?\\\\{root_json}\\\\scratch.ext4\",\"--microvm-workload-identity\",\"65534:65534\",\"--mount-aggregate\",\"/run/nvx/hostfs/root\",\"--mount-child\",\"0,{root_json}\\\\share,ro\",\"--microvm-lifecycle\",\"managed\",\"--single-process\",\"--hypervisor\",\"whp\",\"--memory\",\"256M\",\"--kernel\",\"{root_json}\\\\build\\\\vmlinux\",\"--initrd\",\"{root_json}\\\\build\\\\initramfs.cpio.gz\",\"--cmdline\",\"nvx_sandbox=1 nvx_layer=distro,0xd0003000,erofs:11111111-1111-1111-1111-111111111111 nvx_scratch=0xd0006000,ext4 nvx_entrypoint=/bin/sh nvx_hostname=nvx-sandbox nvx_maps=1\",\"--virtio-console\",\"none\",\"--microvm-control-console\",\"listen=//./pipe/openvmm-microvm-{hex32}\",\"--microvm-control-auth-stdin\",\"--microvm-report\",\"{root_json}\\\\state\\\\outcome.json\"]"},"build/fake-openvmm-state-maps.json":{"text":"[{\"source\":\"0\",\"target\":\"/data\",\"read_only\":true,\"directory\":true}]"}}},{"argv":["sandbox","exec","--state-dir","{root}\\state","--entrypoint","/bin/pwd","--cwd","/data"],"status":0,"stdout":"/data\n","stderr":""},{"argv":["sandbox","stop","--state-dir","{root}\\state"],"check":["state","state/config.json","state/runtime.json","state/control.capability","state/outcome.json","state/openvmm.log"],"status":0,"stdout":"","stderr":"","files":{"state":{"entries":["config.json","openvmm.log","outcome.json","sandbox.lock"]},"state/config.json":{"text":"{\r\n \"cmdline\": \"\",\r\n \"distro_binding\": {\r\n \"format\": \"erofs\",\r\n \"identity\": \"11111111-1111-1111-1111-111111111111\",\r\n \"image\": {\r\n \"changed\": null,\r\n \"device\": {int},\r\n \"fileId\": \"{hex32}\",\r\n \"kind\": \"regular\",\r\n \"length\": 7,\r\n \"modified\": {\r\n \"nanoseconds\": {int},\r\n \"seconds\": {int}\r\n },\r\n \"scheme\": \"windows\",\r\n \"version\": 1\r\n },\r\n \"manifest\": null,\r\n \"policy\": {\r\n \"result\": \"accepted\",\r\n \"revision\": 1\r\n },\r\n \"version\": 1\r\n },\r\n \"export\": {\r\n \"binds\": [\r\n {\r\n \"child\": 0,\r\n \"readOnly\": true,\r\n \"source\": \"\",\r\n \"target\": \"/data\"\r\n }\r\n ],\r\n \"children\": [\r\n {\r\n \"allowed\": [],\r\n \"denied\": [],\r\n \"deniedIdentities\": [],\r\n \"root\": \"{root_json}\\\\share\",\r\n \"writable\": false,\r\n \"write\": []\r\n }\r\n ]\r\n },\r\n \"format\": 7,\r\n \"hostname\": \"nvx-sandbox\",\r\n \"hypervisor\": \"whp\",\r\n \"layers\": [\r\n {\r\n \"path\": \"{root_json}\\\\distro.erofs\",\r\n \"role\": \"distro\",\r\n \"uuid\": \"11111111-1111-1111-1111-111111111111\"\r\n }\r\n ],\r\n \"memory_max\": null,\r\n \"memory_mib\": 256,\r\n \"network\": null,\r\n \"pids_max\": null,\r\n \"scratch\": \"{root_json}\\\\scratch.ext4\",\r\n \"scratch_binding\": {\r\n \"device\": {int},\r\n \"fileId\": \"{hex32}\",\r\n \"kind\": \"regular\",\r\n \"length\": 8,\r\n \"scheme\": \"windows\",\r\n \"version\": 1\r\n },\r\n \"workload_gid\": 65534,\r\n \"workload_uid\": 65534\r\n}\r\n"},"state/runtime.json":null,"state/control.capability":null,"state/outcome.json":{"text":"{\n \"backend\": \"whp\",\n \"instance_id\": \"{hex32}\",\n \"network_policy\": {\n \"allow_rule_count\": 0,\n \"deny_rule_count\": 0,\n \"host_loopback\": \"none\",\n \"mode\": \"none\",\n \"status\": \"not-requested\",\n \"status_code\": 0\n },\n \"outcome\": {\n \"category\": \"success\",\n \"operation\": \"managed\",\n \"status_code\": 0\n },\n \"schema_version\": 1,\n \"teardown\": {\n \"control_channels_closed\": true,\n \"guest_workload_stopped\": true,\n \"network_released\": true,\n \"openvmm_process_terminated\": true,\n \"temporary_storage_removed\": true,\n \"virtiofs_released\": true,\n \"vm_stopped\": true\n }\n}\n"},"state/openvmm.log":{"text":""}}},{"argv":["sandbox","start","--state-dir","{root}\\state"],"check":["state","state/config.json","state/runtime.json","state/control.capability","state/outcome.json","state/openvmm.log"],"status":0,"stdout":"","stderr":"","files":{"state":{"entries":["config.json","control.capability","openvmm.log","runtime.json","sandbox.lock"]},"state/config.json":{"text":"{\r\n \"cmdline\": \"\",\r\n \"distro_binding\": {\r\n \"format\": \"erofs\",\r\n \"identity\": \"11111111-1111-1111-1111-111111111111\",\r\n \"image\": {\r\n \"changed\": null,\r\n \"device\": {int},\r\n \"fileId\": \"{hex32}\",\r\n \"kind\": \"regular\",\r\n \"length\": 7,\r\n \"modified\": {\r\n \"nanoseconds\": {int},\r\n \"seconds\": {int}\r\n },\r\n \"scheme\": \"windows\",\r\n \"version\": 1\r\n },\r\n \"manifest\": null,\r\n \"policy\": {\r\n \"result\": \"accepted\",\r\n \"revision\": 1\r\n },\r\n \"version\": 1\r\n },\r\n \"export\": {\r\n \"binds\": [\r\n {\r\n \"child\": 0,\r\n \"readOnly\": true,\r\n \"source\": \"\",\r\n \"target\": \"/data\"\r\n }\r\n ],\r\n \"children\": [\r\n {\r\n \"allowed\": [],\r\n \"denied\": [],\r\n \"deniedIdentities\": [],\r\n \"root\": \"{root_json}\\\\share\",\r\n \"writable\": false,\r\n \"write\": []\r\n }\r\n ]\r\n },\r\n \"format\": 7,\r\n \"hostname\": \"nvx-sandbox\",\r\n \"hypervisor\": \"whp\",\r\n \"layers\": [\r\n {\r\n \"path\": \"{root_json}\\\\distro.erofs\",\r\n \"role\": \"distro\",\r\n \"uuid\": \"11111111-1111-1111-1111-111111111111\"\r\n }\r\n ],\r\n \"memory_max\": null,\r\n \"memory_mib\": 256,\r\n \"network\": null,\r\n \"pids_max\": null,\r\n \"scratch\": \"{root_json}\\\\scratch.ext4\",\r\n \"scratch_binding\": {\r\n \"device\": {int},\r\n \"fileId\": \"{hex32}\",\r\n \"kind\": \"regular\",\r\n \"length\": 8,\r\n \"scheme\": \"windows\",\r\n \"version\": 1\r\n },\r\n \"workload_gid\": 65534,\r\n \"workload_uid\": 65534\r\n}\r\n"},"state/runtime.json":{"text":"{\n \"format\": 4,\n \"launch\": \"{hex32}\",\n \"process\": {\n \"pid\": {int},\n \"startTime\": {int},\n \"boot\": \"{hex32}\"\n },\n \"endpoint\": \"//./pipe/openvmm-microvm-{hex32}\",\n \"runtime\": {\n \"openvmm\": \"sha256:1e8c924cdaac227bf74b4a4a9bcdb9e8836a1355fd0408cc81dab5d9aa71eb4d\",\n \"kernel\": \"sha256:a0c936696eb7d5ee3192bf53b9d281cecbb40ca9db520de72cb95817ad92ac72\",\n \"initramfs\": \"sha256:2f77c2c97621e8bf69794e9d12815bb7c46338638f126bea8b18dfe02a684d62\",\n \"bootContract\": 3,\n \"controlContract\": \"nvx-microvm-v2-control-v2\",\n \"controlSession\": 1\n }\n}\n"},"state/control.capability":{"size":32},"state/outcome.json":null,"state/openvmm.log":{"text":""}}},{"argv":["sandbox","stop","--state-dir","{root}\\state"],"check":["state","state/config.json","state/runtime.json","state/control.capability","state/outcome.json","state/openvmm.log"],"status":0,"stdout":"","stderr":"","files":{"state":{"entries":["config.json","openvmm.log","outcome.json","sandbox.lock"]},"state/config.json":{"text":"{\r\n \"cmdline\": \"\",\r\n \"distro_binding\": {\r\n \"format\": \"erofs\",\r\n \"identity\": \"11111111-1111-1111-1111-111111111111\",\r\n \"image\": {\r\n \"changed\": null,\r\n \"device\": {int},\r\n \"fileId\": \"{hex32}\",\r\n \"kind\": \"regular\",\r\n \"length\": 7,\r\n \"modified\": {\r\n \"nanoseconds\": {int},\r\n \"seconds\": {int}\r\n },\r\n \"scheme\": \"windows\",\r\n \"version\": 1\r\n },\r\n \"manifest\": null,\r\n \"policy\": {\r\n \"result\": \"accepted\",\r\n \"revision\": 1\r\n },\r\n \"version\": 1\r\n },\r\n \"export\": {\r\n \"binds\": [\r\n {\r\n \"child\": 0,\r\n \"readOnly\": true,\r\n \"source\": \"\",\r\n \"target\": \"/data\"\r\n }\r\n ],\r\n \"children\": [\r\n {\r\n \"allowed\": [],\r\n \"denied\": [],\r\n \"deniedIdentities\": [],\r\n \"root\": \"{root_json}\\\\share\",\r\n \"writable\": false,\r\n \"write\": []\r\n }\r\n ]\r\n },\r\n \"format\": 7,\r\n \"hostname\": \"nvx-sandbox\",\r\n \"hypervisor\": \"whp\",\r\n \"layers\": [\r\n {\r\n \"path\": \"{root_json}\\\\distro.erofs\",\r\n \"role\": \"distro\",\r\n \"uuid\": \"11111111-1111-1111-1111-111111111111\"\r\n }\r\n ],\r\n \"memory_max\": null,\r\n \"memory_mib\": 256,\r\n \"network\": null,\r\n \"pids_max\": null,\r\n \"scratch\": \"{root_json}\\\\scratch.ext4\",\r\n \"scratch_binding\": {\r\n \"device\": {int},\r\n \"fileId\": \"{hex32}\",\r\n \"kind\": \"regular\",\r\n \"length\": 8,\r\n \"scheme\": \"windows\",\r\n \"version\": 1\r\n },\r\n \"workload_gid\": 65534,\r\n \"workload_uid\": 65534\r\n}\r\n"},"state/runtime.json":null,"state/control.capability":null,"state/outcome.json":{"text":"{\n \"backend\": \"whp\",\n \"instance_id\": \"{hex32}\",\n \"network_policy\": {\n \"allow_rule_count\": 0,\n \"deny_rule_count\": 0,\n \"host_loopback\": \"none\",\n \"mode\": \"none\",\n \"status\": \"not-requested\",\n \"status_code\": 0\n },\n \"outcome\": {\n \"category\": \"success\",\n \"operation\": \"managed\",\n \"status_code\": 0\n },\n \"schema_version\": 1,\n \"teardown\": {\n \"control_channels_closed\": true,\n \"guest_workload_stopped\": true,\n \"network_released\": true,\n \"openvmm_process_terminated\": true,\n \"temporary_storage_removed\": true,\n \"virtiofs_released\": true,\n \"vm_stopped\": true\n }\n}\n"},"state/openvmm.log":{"text":""}}},{"argv":["sandbox","deprovision","--state-dir","{root}\\state"],"check":["state"],"status":0,"stdout":"","stderr":"","files":{"state":null}}],"interop":true}, +{"name":"lifecycle: several shares","steps":[{"argv":["sandbox","provision","--state-dir","{root}\\state","--layer","distro,{root}\\distro.erofs,11111111-1111-1111-1111-111111111111","--scratch","{root}\\scratch.ext4","--mount","/data,{root}\\share","--mount","/other,{root}\\share2,rw"],"check":["state","state/config.json","state/runtime.json","state/control.capability","state/outcome.json","state/openvmm.log"],"status":0,"stdout":"","stderr":"","files":{"state":{"entries":["config.json","sandbox.lock"]},"state/config.json":{"text":"{\r\n \"cmdline\": \"\",\r\n \"distro_binding\": {\r\n \"format\": \"erofs\",\r\n \"identity\": \"11111111-1111-1111-1111-111111111111\",\r\n \"image\": {\r\n \"changed\": null,\r\n \"device\": {int},\r\n \"fileId\": \"{hex32}\",\r\n \"kind\": \"regular\",\r\n \"length\": 7,\r\n \"modified\": {\r\n \"nanoseconds\": {int},\r\n \"seconds\": {int}\r\n },\r\n \"scheme\": \"windows\",\r\n \"version\": 1\r\n },\r\n \"manifest\": null,\r\n \"policy\": {\r\n \"result\": \"accepted\",\r\n \"revision\": 1\r\n },\r\n \"version\": 1\r\n },\r\n \"export\": {\r\n \"binds\": [\r\n {\r\n \"child\": 0,\r\n \"readOnly\": true,\r\n \"source\": \"\",\r\n \"target\": \"/data\"\r\n },\r\n {\r\n \"child\": 1,\r\n \"readOnly\": false,\r\n \"source\": \"\",\r\n \"target\": \"/other\"\r\n }\r\n ],\r\n \"children\": [\r\n {\r\n \"allowed\": [],\r\n \"denied\": [],\r\n \"deniedIdentities\": [],\r\n \"root\": \"{root_json}\\\\share\",\r\n \"writable\": false,\r\n \"write\": []\r\n },\r\n {\r\n \"allowed\": [],\r\n \"denied\": [],\r\n \"deniedIdentities\": [],\r\n \"root\": \"{root_json}\\\\share2\",\r\n \"writable\": true,\r\n \"write\": []\r\n }\r\n ]\r\n },\r\n \"format\": 7,\r\n \"hostname\": \"nvx-sandbox\",\r\n \"hypervisor\": \"whp\",\r\n \"layers\": [\r\n {\r\n \"path\": \"{root_json}\\\\distro.erofs\",\r\n \"role\": \"distro\",\r\n \"uuid\": \"11111111-1111-1111-1111-111111111111\"\r\n }\r\n ],\r\n \"memory_max\": null,\r\n \"memory_mib\": 256,\r\n \"network\": null,\r\n \"pids_max\": null,\r\n \"scratch\": \"{root_json}\\\\scratch.ext4\",\r\n \"scratch_binding\": {\r\n \"device\": {int},\r\n \"fileId\": \"{hex32}\",\r\n \"kind\": \"regular\",\r\n \"length\": 8,\r\n \"scheme\": \"windows\",\r\n \"version\": 1\r\n },\r\n \"workload_gid\": 65534,\r\n \"workload_uid\": 65534\r\n}\r\n"},"state/runtime.json":null,"state/control.capability":null,"state/outcome.json":null,"state/openvmm.log":null}},{"argv":["sandbox","start","--state-dir","{root}\\state"],"check":["state","state/config.json","state/runtime.json","state/control.capability","state/outcome.json","state/openvmm.log","build/fake-openvmm-state.json","build/fake-openvmm-state-maps.json"],"status":0,"stdout":"","stderr":"","files":{"state":{"entries":["config.json","control.capability","openvmm.log","runtime.json","sandbox.lock"]},"state/config.json":{"text":"{\r\n \"cmdline\": \"\",\r\n \"distro_binding\": {\r\n \"format\": \"erofs\",\r\n \"identity\": \"11111111-1111-1111-1111-111111111111\",\r\n \"image\": {\r\n \"changed\": null,\r\n \"device\": {int},\r\n \"fileId\": \"{hex32}\",\r\n \"kind\": \"regular\",\r\n \"length\": 7,\r\n \"modified\": {\r\n \"nanoseconds\": {int},\r\n \"seconds\": {int}\r\n },\r\n \"scheme\": \"windows\",\r\n \"version\": 1\r\n },\r\n \"manifest\": null,\r\n \"policy\": {\r\n \"result\": \"accepted\",\r\n \"revision\": 1\r\n },\r\n \"version\": 1\r\n },\r\n \"export\": {\r\n \"binds\": [\r\n {\r\n \"child\": 0,\r\n \"readOnly\": true,\r\n \"source\": \"\",\r\n \"target\": \"/data\"\r\n },\r\n {\r\n \"child\": 1,\r\n \"readOnly\": false,\r\n \"source\": \"\",\r\n \"target\": \"/other\"\r\n }\r\n ],\r\n \"children\": [\r\n {\r\n \"allowed\": [],\r\n \"denied\": [],\r\n \"deniedIdentities\": [],\r\n \"root\": \"{root_json}\\\\share\",\r\n \"writable\": false,\r\n \"write\": []\r\n },\r\n {\r\n \"allowed\": [],\r\n \"denied\": [],\r\n \"deniedIdentities\": [],\r\n \"root\": \"{root_json}\\\\share2\",\r\n \"writable\": true,\r\n \"write\": []\r\n }\r\n ]\r\n },\r\n \"format\": 7,\r\n \"hostname\": \"nvx-sandbox\",\r\n \"hypervisor\": \"whp\",\r\n \"layers\": [\r\n {\r\n \"path\": \"{root_json}\\\\distro.erofs\",\r\n \"role\": \"distro\",\r\n \"uuid\": \"11111111-1111-1111-1111-111111111111\"\r\n }\r\n ],\r\n \"memory_max\": null,\r\n \"memory_mib\": 256,\r\n \"network\": null,\r\n \"pids_max\": null,\r\n \"scratch\": \"{root_json}\\\\scratch.ext4\",\r\n \"scratch_binding\": {\r\n \"device\": {int},\r\n \"fileId\": \"{hex32}\",\r\n \"kind\": \"regular\",\r\n \"length\": 8,\r\n \"scheme\": \"windows\",\r\n \"version\": 1\r\n },\r\n \"workload_gid\": 65534,\r\n \"workload_uid\": 65534\r\n}\r\n"},"state/runtime.json":{"text":"{\n \"format\": 4,\n \"launch\": \"{hex32}\",\n \"process\": {\n \"pid\": {int},\n \"startTime\": {int},\n \"boot\": \"{hex32}\"\n },\n \"endpoint\": \"//./pipe/openvmm-microvm-{hex32}\",\n \"runtime\": {\n \"openvmm\": \"sha256:1e8c924cdaac227bf74b4a4a9bcdb9e8836a1355fd0408cc81dab5d9aa71eb4d\",\n \"kernel\": \"sha256:a0c936696eb7d5ee3192bf53b9d281cecbb40ca9db520de72cb95817ad92ac72\",\n \"initramfs\": \"sha256:2f77c2c97621e8bf69794e9d12815bb7c46338638f126bea8b18dfe02a684d62\",\n \"bootContract\": 3,\n \"controlContract\": \"nvx-microvm-v2-control-v2\",\n \"controlSession\": 1\n }\n}\n"},"state/control.capability":{"size":32},"state/outcome.json":null,"state/openvmm.log":{"text":""},"build/fake-openvmm-state.json":{"text":"[\"--machine\",\"microvm\",\"--microvm-sandbox-block\",\"distro:file:\\\\\\\\?\\\\{root_json}\\\\distro.erofs,ro\",\"--microvm-sandbox-block\",\"scratch:file:\\\\\\\\?\\\\{root_json}\\\\scratch.ext4\",\"--microvm-workload-identity\",\"65534:65534\",\"--mount-aggregate\",\"/run/nvx/hostfs/root\",\"--mount-child\",\"0,{root_json}\\\\share,ro\",\"--mount-child\",\"1,{root_json}\\\\share2,rw\",\"--microvm-lifecycle\",\"managed\",\"--single-process\",\"--hypervisor\",\"whp\",\"--memory\",\"256M\",\"--kernel\",\"{root_json}\\\\build\\\\vmlinux\",\"--initrd\",\"{root_json}\\\\build\\\\initramfs.cpio.gz\",\"--cmdline\",\"nvx_sandbox=1 nvx_layer=distro,0xd0003000,erofs:11111111-1111-1111-1111-111111111111 nvx_scratch=0xd0006000,ext4 nvx_entrypoint=/bin/sh nvx_hostname=nvx-sandbox nvx_maps=2\",\"--virtio-console\",\"none\",\"--microvm-control-console\",\"listen=//./pipe/openvmm-microvm-{hex32}\",\"--microvm-control-auth-stdin\",\"--microvm-report\",\"{root_json}\\\\state\\\\outcome.json\"]"},"build/fake-openvmm-state-maps.json":{"text":"[{\"source\":\"0\",\"target\":\"/data\",\"read_only\":true,\"directory\":true},{\"source\":\"1\",\"target\":\"/other\",\"read_only\":false,\"directory\":true}]"}}},{"argv":["sandbox","exec","--state-dir","{root}\\state","--entrypoint","/bin/pwd","--cwd","/other"],"status":0,"stdout":"/other\n","stderr":""},{"argv":["sandbox","stop","--state-dir","{root}\\state"],"check":["state","state/config.json","state/runtime.json","state/control.capability","state/outcome.json","state/openvmm.log"],"status":0,"stdout":"","stderr":"","files":{"state":{"entries":["config.json","openvmm.log","outcome.json","sandbox.lock"]},"state/config.json":{"text":"{\r\n \"cmdline\": \"\",\r\n \"distro_binding\": {\r\n \"format\": \"erofs\",\r\n \"identity\": \"11111111-1111-1111-1111-111111111111\",\r\n \"image\": {\r\n \"changed\": null,\r\n \"device\": {int},\r\n \"fileId\": \"{hex32}\",\r\n \"kind\": \"regular\",\r\n \"length\": 7,\r\n \"modified\": {\r\n \"nanoseconds\": {int},\r\n \"seconds\": {int}\r\n },\r\n \"scheme\": \"windows\",\r\n \"version\": 1\r\n },\r\n \"manifest\": null,\r\n \"policy\": {\r\n \"result\": \"accepted\",\r\n \"revision\": 1\r\n },\r\n \"version\": 1\r\n },\r\n \"export\": {\r\n \"binds\": [\r\n {\r\n \"child\": 0,\r\n \"readOnly\": true,\r\n \"source\": \"\",\r\n \"target\": \"/data\"\r\n },\r\n {\r\n \"child\": 1,\r\n \"readOnly\": false,\r\n \"source\": \"\",\r\n \"target\": \"/other\"\r\n }\r\n ],\r\n \"children\": [\r\n {\r\n \"allowed\": [],\r\n \"denied\": [],\r\n \"deniedIdentities\": [],\r\n \"root\": \"{root_json}\\\\share\",\r\n \"writable\": false,\r\n \"write\": []\r\n },\r\n {\r\n \"allowed\": [],\r\n \"denied\": [],\r\n \"deniedIdentities\": [],\r\n \"root\": \"{root_json}\\\\share2\",\r\n \"writable\": true,\r\n \"write\": []\r\n }\r\n ]\r\n },\r\n \"format\": 7,\r\n \"hostname\": \"nvx-sandbox\",\r\n \"hypervisor\": \"whp\",\r\n \"layers\": [\r\n {\r\n \"path\": \"{root_json}\\\\distro.erofs\",\r\n \"role\": \"distro\",\r\n \"uuid\": \"11111111-1111-1111-1111-111111111111\"\r\n }\r\n ],\r\n \"memory_max\": null,\r\n \"memory_mib\": 256,\r\n \"network\": null,\r\n \"pids_max\": null,\r\n \"scratch\": \"{root_json}\\\\scratch.ext4\",\r\n \"scratch_binding\": {\r\n \"device\": {int},\r\n \"fileId\": \"{hex32}\",\r\n \"kind\": \"regular\",\r\n \"length\": 8,\r\n \"scheme\": \"windows\",\r\n \"version\": 1\r\n },\r\n \"workload_gid\": 65534,\r\n \"workload_uid\": 65534\r\n}\r\n"},"state/runtime.json":null,"state/control.capability":null,"state/outcome.json":{"text":"{\n \"backend\": \"whp\",\n \"instance_id\": \"{hex32}\",\n \"network_policy\": {\n \"allow_rule_count\": 0,\n \"deny_rule_count\": 0,\n \"host_loopback\": \"none\",\n \"mode\": \"none\",\n \"status\": \"not-requested\",\n \"status_code\": 0\n },\n \"outcome\": {\n \"category\": \"success\",\n \"operation\": \"managed\",\n \"status_code\": 0\n },\n \"schema_version\": 1,\n \"teardown\": {\n \"control_channels_closed\": true,\n \"guest_workload_stopped\": true,\n \"network_released\": true,\n \"openvmm_process_terminated\": true,\n \"temporary_storage_removed\": true,\n \"virtiofs_released\": true,\n \"vm_stopped\": true\n }\n}\n"},"state/openvmm.log":{"text":""}}},{"argv":["sandbox","start","--state-dir","{root}\\state"],"check":["state","state/config.json","state/runtime.json","state/control.capability","state/outcome.json","state/openvmm.log"],"status":0,"stdout":"","stderr":"","files":{"state":{"entries":["config.json","control.capability","openvmm.log","runtime.json","sandbox.lock"]},"state/config.json":{"text":"{\r\n \"cmdline\": \"\",\r\n \"distro_binding\": {\r\n \"format\": \"erofs\",\r\n \"identity\": \"11111111-1111-1111-1111-111111111111\",\r\n \"image\": {\r\n \"changed\": null,\r\n \"device\": {int},\r\n \"fileId\": \"{hex32}\",\r\n \"kind\": \"regular\",\r\n \"length\": 7,\r\n \"modified\": {\r\n \"nanoseconds\": {int},\r\n \"seconds\": {int}\r\n },\r\n \"scheme\": \"windows\",\r\n \"version\": 1\r\n },\r\n \"manifest\": null,\r\n \"policy\": {\r\n \"result\": \"accepted\",\r\n \"revision\": 1\r\n },\r\n \"version\": 1\r\n },\r\n \"export\": {\r\n \"binds\": [\r\n {\r\n \"child\": 0,\r\n \"readOnly\": true,\r\n \"source\": \"\",\r\n \"target\": \"/data\"\r\n },\r\n {\r\n \"child\": 1,\r\n \"readOnly\": false,\r\n \"source\": \"\",\r\n \"target\": \"/other\"\r\n }\r\n ],\r\n \"children\": [\r\n {\r\n \"allowed\": [],\r\n \"denied\": [],\r\n \"deniedIdentities\": [],\r\n \"root\": \"{root_json}\\\\share\",\r\n \"writable\": false,\r\n \"write\": []\r\n },\r\n {\r\n \"allowed\": [],\r\n \"denied\": [],\r\n \"deniedIdentities\": [],\r\n \"root\": \"{root_json}\\\\share2\",\r\n \"writable\": true,\r\n \"write\": []\r\n }\r\n ]\r\n },\r\n \"format\": 7,\r\n \"hostname\": \"nvx-sandbox\",\r\n \"hypervisor\": \"whp\",\r\n \"layers\": [\r\n {\r\n \"path\": \"{root_json}\\\\distro.erofs\",\r\n \"role\": \"distro\",\r\n \"uuid\": \"11111111-1111-1111-1111-111111111111\"\r\n }\r\n ],\r\n \"memory_max\": null,\r\n \"memory_mib\": 256,\r\n \"network\": null,\r\n \"pids_max\": null,\r\n \"scratch\": \"{root_json}\\\\scratch.ext4\",\r\n \"scratch_binding\": {\r\n \"device\": {int},\r\n \"fileId\": \"{hex32}\",\r\n \"kind\": \"regular\",\r\n \"length\": 8,\r\n \"scheme\": \"windows\",\r\n \"version\": 1\r\n },\r\n \"workload_gid\": 65534,\r\n \"workload_uid\": 65534\r\n}\r\n"},"state/runtime.json":{"text":"{\n \"format\": 4,\n \"launch\": \"{hex32}\",\n \"process\": {\n \"pid\": {int},\n \"startTime\": {int},\n \"boot\": \"{hex32}\"\n },\n \"endpoint\": \"//./pipe/openvmm-microvm-{hex32}\",\n \"runtime\": {\n \"openvmm\": \"sha256:1e8c924cdaac227bf74b4a4a9bcdb9e8836a1355fd0408cc81dab5d9aa71eb4d\",\n \"kernel\": \"sha256:a0c936696eb7d5ee3192bf53b9d281cecbb40ca9db520de72cb95817ad92ac72\",\n \"initramfs\": \"sha256:2f77c2c97621e8bf69794e9d12815bb7c46338638f126bea8b18dfe02a684d62\",\n \"bootContract\": 3,\n \"controlContract\": \"nvx-microvm-v2-control-v2\",\n \"controlSession\": 1\n }\n}\n"},"state/control.capability":{"size":32},"state/outcome.json":null,"state/openvmm.log":{"text":""}}},{"argv":["sandbox","stop","--state-dir","{root}\\state"],"check":["state","state/config.json","state/runtime.json","state/control.capability","state/outcome.json","state/openvmm.log"],"status":0,"stdout":"","stderr":"","files":{"state":{"entries":["config.json","openvmm.log","outcome.json","sandbox.lock"]},"state/config.json":{"text":"{\r\n \"cmdline\": \"\",\r\n \"distro_binding\": {\r\n \"format\": \"erofs\",\r\n \"identity\": \"11111111-1111-1111-1111-111111111111\",\r\n \"image\": {\r\n \"changed\": null,\r\n \"device\": {int},\r\n \"fileId\": \"{hex32}\",\r\n \"kind\": \"regular\",\r\n \"length\": 7,\r\n \"modified\": {\r\n \"nanoseconds\": {int},\r\n \"seconds\": {int}\r\n },\r\n \"scheme\": \"windows\",\r\n \"version\": 1\r\n },\r\n \"manifest\": null,\r\n \"policy\": {\r\n \"result\": \"accepted\",\r\n \"revision\": 1\r\n },\r\n \"version\": 1\r\n },\r\n \"export\": {\r\n \"binds\": [\r\n {\r\n \"child\": 0,\r\n \"readOnly\": true,\r\n \"source\": \"\",\r\n \"target\": \"/data\"\r\n },\r\n {\r\n \"child\": 1,\r\n \"readOnly\": false,\r\n \"source\": \"\",\r\n \"target\": \"/other\"\r\n }\r\n ],\r\n \"children\": [\r\n {\r\n \"allowed\": [],\r\n \"denied\": [],\r\n \"deniedIdentities\": [],\r\n \"root\": \"{root_json}\\\\share\",\r\n \"writable\": false,\r\n \"write\": []\r\n },\r\n {\r\n \"allowed\": [],\r\n \"denied\": [],\r\n \"deniedIdentities\": [],\r\n \"root\": \"{root_json}\\\\share2\",\r\n \"writable\": true,\r\n \"write\": []\r\n }\r\n ]\r\n },\r\n \"format\": 7,\r\n \"hostname\": \"nvx-sandbox\",\r\n \"hypervisor\": \"whp\",\r\n \"layers\": [\r\n {\r\n \"path\": \"{root_json}\\\\distro.erofs\",\r\n \"role\": \"distro\",\r\n \"uuid\": \"11111111-1111-1111-1111-111111111111\"\r\n }\r\n ],\r\n \"memory_max\": null,\r\n \"memory_mib\": 256,\r\n \"network\": null,\r\n \"pids_max\": null,\r\n \"scratch\": \"{root_json}\\\\scratch.ext4\",\r\n \"scratch_binding\": {\r\n \"device\": {int},\r\n \"fileId\": \"{hex32}\",\r\n \"kind\": \"regular\",\r\n \"length\": 8,\r\n \"scheme\": \"windows\",\r\n \"version\": 1\r\n },\r\n \"workload_gid\": 65534,\r\n \"workload_uid\": 65534\r\n}\r\n"},"state/runtime.json":null,"state/control.capability":null,"state/outcome.json":{"text":"{\n \"backend\": \"whp\",\n \"instance_id\": \"{hex32}\",\n \"network_policy\": {\n \"allow_rule_count\": 0,\n \"deny_rule_count\": 0,\n \"host_loopback\": \"none\",\n \"mode\": \"none\",\n \"status\": \"not-requested\",\n \"status_code\": 0\n },\n \"outcome\": {\n \"category\": \"success\",\n \"operation\": \"managed\",\n \"status_code\": 0\n },\n \"schema_version\": 1,\n \"teardown\": {\n \"control_channels_closed\": true,\n \"guest_workload_stopped\": true,\n \"network_released\": true,\n \"openvmm_process_terminated\": true,\n \"temporary_storage_removed\": true,\n \"virtiofs_released\": true,\n \"vm_stopped\": true\n }\n}\n"},"state/openvmm.log":{"text":""}}},{"argv":["sandbox","deprovision","--state-dir","{root}\\state"],"check":["state"],"status":0,"stdout":"","stderr":"","files":{"state":null}}],"interop":true}, +{"name":"lifecycle: share policies","steps":[{"argv":["sandbox","provision","--state-dir","{root}\\state","--layer","distro,{root}\\distro.erofs,11111111-1111-1111-1111-111111111111","--scratch","{root}\\scratch.ext4","--mount","/data,{root}\\share,rw","--mount-deny","{root}\\share\\hidden","--mount-allow","{root}\\share\\hidden\\shown","--mount-write","{root}\\share\\writable"],"check":["state","state/config.json","state/runtime.json","state/control.capability","state/outcome.json","state/openvmm.log"],"status":0,"stdout":"","stderr":"","files":{"state":{"entries":["config.json","sandbox.lock"]},"state/config.json":{"text":"{\r\n \"cmdline\": \"\",\r\n \"distro_binding\": {\r\n \"format\": \"erofs\",\r\n \"identity\": \"11111111-1111-1111-1111-111111111111\",\r\n \"image\": {\r\n \"changed\": null,\r\n \"device\": {int},\r\n \"fileId\": \"{hex32}\",\r\n \"kind\": \"regular\",\r\n \"length\": 7,\r\n \"modified\": {\r\n \"nanoseconds\": {int},\r\n \"seconds\": {int}\r\n },\r\n \"scheme\": \"windows\",\r\n \"version\": 1\r\n },\r\n \"manifest\": null,\r\n \"policy\": {\r\n \"result\": \"accepted\",\r\n \"revision\": 1\r\n },\r\n \"version\": 1\r\n },\r\n \"export\": {\r\n \"binds\": [\r\n {\r\n \"child\": 0,\r\n \"readOnly\": false,\r\n \"source\": \"\",\r\n \"target\": \"/data\"\r\n }\r\n ],\r\n \"children\": [\r\n {\r\n \"allowed\": [\r\n \"{root_json}\\\\share\\\\hidden\\\\shown\"\r\n ],\r\n \"denied\": [\r\n \"{root_json}\\\\share\\\\hidden\"\r\n ],\r\n \"deniedIdentities\": [\r\n null\r\n ],\r\n \"root\": \"{root_json}\\\\share\",\r\n \"writable\": true,\r\n \"write\": [\r\n \"{root_json}\\\\share\\\\writable\"\r\n ]\r\n }\r\n ]\r\n },\r\n \"format\": 7,\r\n \"hostname\": \"nvx-sandbox\",\r\n \"hypervisor\": \"whp\",\r\n \"layers\": [\r\n {\r\n \"path\": \"{root_json}\\\\distro.erofs\",\r\n \"role\": \"distro\",\r\n \"uuid\": \"11111111-1111-1111-1111-111111111111\"\r\n }\r\n ],\r\n \"memory_max\": null,\r\n \"memory_mib\": 256,\r\n \"network\": null,\r\n \"pids_max\": null,\r\n \"scratch\": \"{root_json}\\\\scratch.ext4\",\r\n \"scratch_binding\": {\r\n \"device\": {int},\r\n \"fileId\": \"{hex32}\",\r\n \"kind\": \"regular\",\r\n \"length\": 8,\r\n \"scheme\": \"windows\",\r\n \"version\": 1\r\n },\r\n \"workload_gid\": 65534,\r\n \"workload_uid\": 65534\r\n}\r\n"},"state/runtime.json":null,"state/control.capability":null,"state/outcome.json":null,"state/openvmm.log":null}},{"argv":["sandbox","start","--state-dir","{root}\\state"],"check":["state","state/config.json","state/runtime.json","state/control.capability","state/outcome.json","state/openvmm.log","build/fake-openvmm-state.json","build/fake-openvmm-state-maps.json"],"status":0,"stdout":"","stderr":"","files":{"state":{"entries":["config.json","control.capability","openvmm.log","runtime.json","sandbox.lock"]},"state/config.json":{"text":"{\r\n \"cmdline\": \"\",\r\n \"distro_binding\": {\r\n \"format\": \"erofs\",\r\n \"identity\": \"11111111-1111-1111-1111-111111111111\",\r\n \"image\": {\r\n \"changed\": null,\r\n \"device\": {int},\r\n \"fileId\": \"{hex32}\",\r\n \"kind\": \"regular\",\r\n \"length\": 7,\r\n \"modified\": {\r\n \"nanoseconds\": {int},\r\n \"seconds\": {int}\r\n },\r\n \"scheme\": \"windows\",\r\n \"version\": 1\r\n },\r\n \"manifest\": null,\r\n \"policy\": {\r\n \"result\": \"accepted\",\r\n \"revision\": 1\r\n },\r\n \"version\": 1\r\n },\r\n \"export\": {\r\n \"binds\": [\r\n {\r\n \"child\": 0,\r\n \"readOnly\": false,\r\n \"source\": \"\",\r\n \"target\": \"/data\"\r\n }\r\n ],\r\n \"children\": [\r\n {\r\n \"allowed\": [\r\n \"{root_json}\\\\share\\\\hidden\\\\shown\"\r\n ],\r\n \"denied\": [\r\n \"{root_json}\\\\share\\\\hidden\"\r\n ],\r\n \"deniedIdentities\": [\r\n null\r\n ],\r\n \"root\": \"{root_json}\\\\share\",\r\n \"writable\": true,\r\n \"write\": [\r\n \"{root_json}\\\\share\\\\writable\"\r\n ]\r\n }\r\n ]\r\n },\r\n \"format\": 7,\r\n \"hostname\": \"nvx-sandbox\",\r\n \"hypervisor\": \"whp\",\r\n \"layers\": [\r\n {\r\n \"path\": \"{root_json}\\\\distro.erofs\",\r\n \"role\": \"distro\",\r\n \"uuid\": \"11111111-1111-1111-1111-111111111111\"\r\n }\r\n ],\r\n \"memory_max\": null,\r\n \"memory_mib\": 256,\r\n \"network\": null,\r\n \"pids_max\": null,\r\n \"scratch\": \"{root_json}\\\\scratch.ext4\",\r\n \"scratch_binding\": {\r\n \"device\": {int},\r\n \"fileId\": \"{hex32}\",\r\n \"kind\": \"regular\",\r\n \"length\": 8,\r\n \"scheme\": \"windows\",\r\n \"version\": 1\r\n },\r\n \"workload_gid\": 65534,\r\n \"workload_uid\": 65534\r\n}\r\n"},"state/runtime.json":{"text":"{\n \"format\": 4,\n \"launch\": \"{hex32}\",\n \"process\": {\n \"pid\": {int},\n \"startTime\": {int},\n \"boot\": \"{hex32}\"\n },\n \"endpoint\": \"//./pipe/openvmm-microvm-{hex32}\",\n \"runtime\": {\n \"openvmm\": \"sha256:1e8c924cdaac227bf74b4a4a9bcdb9e8836a1355fd0408cc81dab5d9aa71eb4d\",\n \"kernel\": \"sha256:a0c936696eb7d5ee3192bf53b9d281cecbb40ca9db520de72cb95817ad92ac72\",\n \"initramfs\": \"sha256:2f77c2c97621e8bf69794e9d12815bb7c46338638f126bea8b18dfe02a684d62\",\n \"bootContract\": 3,\n \"controlContract\": \"nvx-microvm-v2-control-v2\",\n \"controlSession\": 1\n }\n}\n"},"state/control.capability":{"size":32},"state/outcome.json":null,"state/openvmm.log":{"text":""},"build/fake-openvmm-state.json":{"text":"[\"--machine\",\"microvm\",\"--microvm-sandbox-block\",\"distro:file:\\\\\\\\?\\\\{root_json}\\\\distro.erofs,ro\",\"--microvm-sandbox-block\",\"scratch:file:\\\\\\\\?\\\\{root_json}\\\\scratch.ext4\",\"--microvm-workload-identity\",\"65534:65534\",\"--mount-aggregate\",\"/run/nvx/hostfs/root\",\"--mount-child\",\"0,{root_json}\\\\share,rw\",\"--mount-deny\",\"{root_json}\\\\share\\\\hidden\",\"--mount-allow\",\"{root_json}\\\\share\\\\hidden\\\\shown\",\"--mount-write\",\"{root_json}\\\\share\\\\writable\",\"--microvm-lifecycle\",\"managed\",\"--single-process\",\"--hypervisor\",\"whp\",\"--memory\",\"256M\",\"--kernel\",\"{root_json}\\\\build\\\\vmlinux\",\"--initrd\",\"{root_json}\\\\build\\\\initramfs.cpio.gz\",\"--cmdline\",\"nvx_sandbox=1 nvx_layer=distro,0xd0003000,erofs:11111111-1111-1111-1111-111111111111 nvx_scratch=0xd0006000,ext4 nvx_entrypoint=/bin/sh nvx_hostname=nvx-sandbox nvx_maps=1\",\"--virtio-console\",\"none\",\"--microvm-control-console\",\"listen=//./pipe/openvmm-microvm-{hex32}\",\"--microvm-control-auth-stdin\",\"--microvm-report\",\"{root_json}\\\\state\\\\outcome.json\"]"},"build/fake-openvmm-state-maps.json":{"text":"[{\"source\":\"0\",\"target\":\"/data\",\"read_only\":false,\"directory\":true}]"}}},{"argv":["sandbox","stop","--state-dir","{root}\\state"],"check":["state","state/config.json","state/runtime.json","state/control.capability","state/outcome.json","state/openvmm.log"],"status":0,"stdout":"","stderr":"","files":{"state":{"entries":["config.json","openvmm.log","outcome.json","sandbox.lock"]},"state/config.json":{"text":"{\r\n \"cmdline\": \"\",\r\n \"distro_binding\": {\r\n \"format\": \"erofs\",\r\n \"identity\": \"11111111-1111-1111-1111-111111111111\",\r\n \"image\": {\r\n \"changed\": null,\r\n \"device\": {int},\r\n \"fileId\": \"{hex32}\",\r\n \"kind\": \"regular\",\r\n \"length\": 7,\r\n \"modified\": {\r\n \"nanoseconds\": {int},\r\n \"seconds\": {int}\r\n },\r\n \"scheme\": \"windows\",\r\n \"version\": 1\r\n },\r\n \"manifest\": null,\r\n \"policy\": {\r\n \"result\": \"accepted\",\r\n \"revision\": 1\r\n },\r\n \"version\": 1\r\n },\r\n \"export\": {\r\n \"binds\": [\r\n {\r\n \"child\": 0,\r\n \"readOnly\": false,\r\n \"source\": \"\",\r\n \"target\": \"/data\"\r\n }\r\n ],\r\n \"children\": [\r\n {\r\n \"allowed\": [\r\n \"{root_json}\\\\share\\\\hidden\\\\shown\"\r\n ],\r\n \"denied\": [\r\n \"{root_json}\\\\share\\\\hidden\"\r\n ],\r\n \"deniedIdentities\": [\r\n null\r\n ],\r\n \"root\": \"{root_json}\\\\share\",\r\n \"writable\": true,\r\n \"write\": [\r\n \"{root_json}\\\\share\\\\writable\"\r\n ]\r\n }\r\n ]\r\n },\r\n \"format\": 7,\r\n \"hostname\": \"nvx-sandbox\",\r\n \"hypervisor\": \"whp\",\r\n \"layers\": [\r\n {\r\n \"path\": \"{root_json}\\\\distro.erofs\",\r\n \"role\": \"distro\",\r\n \"uuid\": \"11111111-1111-1111-1111-111111111111\"\r\n }\r\n ],\r\n \"memory_max\": null,\r\n \"memory_mib\": 256,\r\n \"network\": null,\r\n \"pids_max\": null,\r\n \"scratch\": \"{root_json}\\\\scratch.ext4\",\r\n \"scratch_binding\": {\r\n \"device\": {int},\r\n \"fileId\": \"{hex32}\",\r\n \"kind\": \"regular\",\r\n \"length\": 8,\r\n \"scheme\": \"windows\",\r\n \"version\": 1\r\n },\r\n \"workload_gid\": 65534,\r\n \"workload_uid\": 65534\r\n}\r\n"},"state/runtime.json":null,"state/control.capability":null,"state/outcome.json":{"text":"{\n \"backend\": \"whp\",\n \"instance_id\": \"{hex32}\",\n \"network_policy\": {\n \"allow_rule_count\": 0,\n \"deny_rule_count\": 0,\n \"host_loopback\": \"none\",\n \"mode\": \"none\",\n \"status\": \"not-requested\",\n \"status_code\": 0\n },\n \"outcome\": {\n \"category\": \"success\",\n \"operation\": \"managed\",\n \"status_code\": 0\n },\n \"schema_version\": 1,\n \"teardown\": {\n \"control_channels_closed\": true,\n \"guest_workload_stopped\": true,\n \"network_released\": true,\n \"openvmm_process_terminated\": true,\n \"temporary_storage_removed\": true,\n \"virtiofs_released\": true,\n \"vm_stopped\": true\n }\n}\n"},"state/openvmm.log":{"text":""}}},{"argv":["sandbox","start","--state-dir","{root}\\state"],"check":["state","state/config.json","state/runtime.json","state/control.capability","state/outcome.json","state/openvmm.log"],"status":0,"stdout":"","stderr":"","files":{"state":{"entries":["config.json","control.capability","openvmm.log","runtime.json","sandbox.lock"]},"state/config.json":{"text":"{\r\n \"cmdline\": \"\",\r\n \"distro_binding\": {\r\n \"format\": \"erofs\",\r\n \"identity\": \"11111111-1111-1111-1111-111111111111\",\r\n \"image\": {\r\n \"changed\": null,\r\n \"device\": {int},\r\n \"fileId\": \"{hex32}\",\r\n \"kind\": \"regular\",\r\n \"length\": 7,\r\n \"modified\": {\r\n \"nanoseconds\": {int},\r\n \"seconds\": {int}\r\n },\r\n \"scheme\": \"windows\",\r\n \"version\": 1\r\n },\r\n \"manifest\": null,\r\n \"policy\": {\r\n \"result\": \"accepted\",\r\n \"revision\": 1\r\n },\r\n \"version\": 1\r\n },\r\n \"export\": {\r\n \"binds\": [\r\n {\r\n \"child\": 0,\r\n \"readOnly\": false,\r\n \"source\": \"\",\r\n \"target\": \"/data\"\r\n }\r\n ],\r\n \"children\": [\r\n {\r\n \"allowed\": [\r\n \"{root_json}\\\\share\\\\hidden\\\\shown\"\r\n ],\r\n \"denied\": [\r\n \"{root_json}\\\\share\\\\hidden\"\r\n ],\r\n \"deniedIdentities\": [\r\n null\r\n ],\r\n \"root\": \"{root_json}\\\\share\",\r\n \"writable\": true,\r\n \"write\": [\r\n \"{root_json}\\\\share\\\\writable\"\r\n ]\r\n }\r\n ]\r\n },\r\n \"format\": 7,\r\n \"hostname\": \"nvx-sandbox\",\r\n \"hypervisor\": \"whp\",\r\n \"layers\": [\r\n {\r\n \"path\": \"{root_json}\\\\distro.erofs\",\r\n \"role\": \"distro\",\r\n \"uuid\": \"11111111-1111-1111-1111-111111111111\"\r\n }\r\n ],\r\n \"memory_max\": null,\r\n \"memory_mib\": 256,\r\n \"network\": null,\r\n \"pids_max\": null,\r\n \"scratch\": \"{root_json}\\\\scratch.ext4\",\r\n \"scratch_binding\": {\r\n \"device\": {int},\r\n \"fileId\": \"{hex32}\",\r\n \"kind\": \"regular\",\r\n \"length\": 8,\r\n \"scheme\": \"windows\",\r\n \"version\": 1\r\n },\r\n \"workload_gid\": 65534,\r\n \"workload_uid\": 65534\r\n}\r\n"},"state/runtime.json":{"text":"{\n \"format\": 4,\n \"launch\": \"{hex32}\",\n \"process\": {\n \"pid\": {int},\n \"startTime\": {int},\n \"boot\": \"{hex32}\"\n },\n \"endpoint\": \"//./pipe/openvmm-microvm-{hex32}\",\n \"runtime\": {\n \"openvmm\": \"sha256:1e8c924cdaac227bf74b4a4a9bcdb9e8836a1355fd0408cc81dab5d9aa71eb4d\",\n \"kernel\": \"sha256:a0c936696eb7d5ee3192bf53b9d281cecbb40ca9db520de72cb95817ad92ac72\",\n \"initramfs\": \"sha256:2f77c2c97621e8bf69794e9d12815bb7c46338638f126bea8b18dfe02a684d62\",\n \"bootContract\": 3,\n \"controlContract\": \"nvx-microvm-v2-control-v2\",\n \"controlSession\": 1\n }\n}\n"},"state/control.capability":{"size":32},"state/outcome.json":null,"state/openvmm.log":{"text":""}}},{"argv":["sandbox","stop","--state-dir","{root}\\state"],"check":["state","state/config.json","state/runtime.json","state/control.capability","state/outcome.json","state/openvmm.log"],"status":0,"stdout":"","stderr":"","files":{"state":{"entries":["config.json","openvmm.log","outcome.json","sandbox.lock"]},"state/config.json":{"text":"{\r\n \"cmdline\": \"\",\r\n \"distro_binding\": {\r\n \"format\": \"erofs\",\r\n \"identity\": \"11111111-1111-1111-1111-111111111111\",\r\n \"image\": {\r\n \"changed\": null,\r\n \"device\": {int},\r\n \"fileId\": \"{hex32}\",\r\n \"kind\": \"regular\",\r\n \"length\": 7,\r\n \"modified\": {\r\n \"nanoseconds\": {int},\r\n \"seconds\": {int}\r\n },\r\n \"scheme\": \"windows\",\r\n \"version\": 1\r\n },\r\n \"manifest\": null,\r\n \"policy\": {\r\n \"result\": \"accepted\",\r\n \"revision\": 1\r\n },\r\n \"version\": 1\r\n },\r\n \"export\": {\r\n \"binds\": [\r\n {\r\n \"child\": 0,\r\n \"readOnly\": false,\r\n \"source\": \"\",\r\n \"target\": \"/data\"\r\n }\r\n ],\r\n \"children\": [\r\n {\r\n \"allowed\": [\r\n \"{root_json}\\\\share\\\\hidden\\\\shown\"\r\n ],\r\n \"denied\": [\r\n \"{root_json}\\\\share\\\\hidden\"\r\n ],\r\n \"deniedIdentities\": [\r\n null\r\n ],\r\n \"root\": \"{root_json}\\\\share\",\r\n \"writable\": true,\r\n \"write\": [\r\n \"{root_json}\\\\share\\\\writable\"\r\n ]\r\n }\r\n ]\r\n },\r\n \"format\": 7,\r\n \"hostname\": \"nvx-sandbox\",\r\n \"hypervisor\": \"whp\",\r\n \"layers\": [\r\n {\r\n \"path\": \"{root_json}\\\\distro.erofs\",\r\n \"role\": \"distro\",\r\n \"uuid\": \"11111111-1111-1111-1111-111111111111\"\r\n }\r\n ],\r\n \"memory_max\": null,\r\n \"memory_mib\": 256,\r\n \"network\": null,\r\n \"pids_max\": null,\r\n \"scratch\": \"{root_json}\\\\scratch.ext4\",\r\n \"scratch_binding\": {\r\n \"device\": {int},\r\n \"fileId\": \"{hex32}\",\r\n \"kind\": \"regular\",\r\n \"length\": 8,\r\n \"scheme\": \"windows\",\r\n \"version\": 1\r\n },\r\n \"workload_gid\": 65534,\r\n \"workload_uid\": 65534\r\n}\r\n"},"state/runtime.json":null,"state/control.capability":null,"state/outcome.json":{"text":"{\n \"backend\": \"whp\",\n \"instance_id\": \"{hex32}\",\n \"network_policy\": {\n \"allow_rule_count\": 0,\n \"deny_rule_count\": 0,\n \"host_loopback\": \"none\",\n \"mode\": \"none\",\n \"status\": \"not-requested\",\n \"status_code\": 0\n },\n \"outcome\": {\n \"category\": \"success\",\n \"operation\": \"managed\",\n \"status_code\": 0\n },\n \"schema_version\": 1,\n \"teardown\": {\n \"control_channels_closed\": true,\n \"guest_workload_stopped\": true,\n \"network_released\": true,\n \"openvmm_process_terminated\": true,\n \"temporary_storage_removed\": true,\n \"virtiofs_released\": true,\n \"vm_stopped\": true\n }\n}\n"},"state/openvmm.log":{"text":""}}},{"argv":["sandbox","deprovision","--state-dir","{root}\\state"],"check":["state"],"status":0,"stdout":"","stderr":"","files":{"state":null}}],"interop":true}, +{"name":"lifecycle: file share","steps":[{"argv":["sandbox","provision","--state-dir","{root}\\state","--layer","distro,{root}\\distro.erofs,11111111-1111-1111-1111-111111111111","--scratch","{root}\\scratch.ext4","--mount","/etc/single.txt,{root}\\single.txt,ro"],"check":["state","state/config.json","state/runtime.json","state/control.capability","state/outcome.json","state/openvmm.log"],"status":0,"stdout":"","stderr":"","files":{"state":{"entries":["config.json","sandbox.lock"]},"state/config.json":{"text":"{\r\n \"cmdline\": \"\",\r\n \"distro_binding\": {\r\n \"format\": \"erofs\",\r\n \"identity\": \"11111111-1111-1111-1111-111111111111\",\r\n \"image\": {\r\n \"changed\": null,\r\n \"device\": {int},\r\n \"fileId\": \"{hex32}\",\r\n \"kind\": \"regular\",\r\n \"length\": 7,\r\n \"modified\": {\r\n \"nanoseconds\": {int},\r\n \"seconds\": {int}\r\n },\r\n \"scheme\": \"windows\",\r\n \"version\": 1\r\n },\r\n \"manifest\": null,\r\n \"policy\": {\r\n \"result\": \"accepted\",\r\n \"revision\": 1\r\n },\r\n \"version\": 1\r\n },\r\n \"export\": {\r\n \"binds\": [\r\n {\r\n \"child\": 0,\r\n \"readOnly\": true,\r\n \"source\": \"\",\r\n \"target\": \"/etc/single.txt\"\r\n }\r\n ],\r\n \"children\": [\r\n {\r\n \"allowed\": [],\r\n \"denied\": [],\r\n \"deniedIdentities\": [],\r\n \"file\": true,\r\n \"root\": \"{root_json}\\\\single.txt\",\r\n \"writable\": false,\r\n \"write\": []\r\n }\r\n ]\r\n },\r\n \"format\": 7,\r\n \"hostname\": \"nvx-sandbox\",\r\n \"hypervisor\": \"whp\",\r\n \"layers\": [\r\n {\r\n \"path\": \"{root_json}\\\\distro.erofs\",\r\n \"role\": \"distro\",\r\n \"uuid\": \"11111111-1111-1111-1111-111111111111\"\r\n }\r\n ],\r\n \"memory_max\": null,\r\n \"memory_mib\": 256,\r\n \"network\": null,\r\n \"pids_max\": null,\r\n \"scratch\": \"{root_json}\\\\scratch.ext4\",\r\n \"scratch_binding\": {\r\n \"device\": {int},\r\n \"fileId\": \"{hex32}\",\r\n \"kind\": \"regular\",\r\n \"length\": 8,\r\n \"scheme\": \"windows\",\r\n \"version\": 1\r\n },\r\n \"workload_gid\": 65534,\r\n \"workload_uid\": 65534\r\n}\r\n"},"state/runtime.json":null,"state/control.capability":null,"state/outcome.json":null,"state/openvmm.log":null}},{"argv":["sandbox","start","--state-dir","{root}\\state"],"check":["state","state/config.json","state/runtime.json","state/control.capability","state/outcome.json","state/openvmm.log","build/fake-openvmm-state.json","build/fake-openvmm-state-maps.json"],"status":0,"stdout":"","stderr":"","files":{"state":{"entries":["config.json","control.capability","openvmm.log","runtime.json","sandbox.lock"]},"state/config.json":{"text":"{\r\n \"cmdline\": \"\",\r\n \"distro_binding\": {\r\n \"format\": \"erofs\",\r\n \"identity\": \"11111111-1111-1111-1111-111111111111\",\r\n \"image\": {\r\n \"changed\": null,\r\n \"device\": {int},\r\n \"fileId\": \"{hex32}\",\r\n \"kind\": \"regular\",\r\n \"length\": 7,\r\n \"modified\": {\r\n \"nanoseconds\": {int},\r\n \"seconds\": {int}\r\n },\r\n \"scheme\": \"windows\",\r\n \"version\": 1\r\n },\r\n \"manifest\": null,\r\n \"policy\": {\r\n \"result\": \"accepted\",\r\n \"revision\": 1\r\n },\r\n \"version\": 1\r\n },\r\n \"export\": {\r\n \"binds\": [\r\n {\r\n \"child\": 0,\r\n \"readOnly\": true,\r\n \"source\": \"\",\r\n \"target\": \"/etc/single.txt\"\r\n }\r\n ],\r\n \"children\": [\r\n {\r\n \"allowed\": [],\r\n \"denied\": [],\r\n \"deniedIdentities\": [],\r\n \"file\": true,\r\n \"root\": \"{root_json}\\\\single.txt\",\r\n \"writable\": false,\r\n \"write\": []\r\n }\r\n ]\r\n },\r\n \"format\": 7,\r\n \"hostname\": \"nvx-sandbox\",\r\n \"hypervisor\": \"whp\",\r\n \"layers\": [\r\n {\r\n \"path\": \"{root_json}\\\\distro.erofs\",\r\n \"role\": \"distro\",\r\n \"uuid\": \"11111111-1111-1111-1111-111111111111\"\r\n }\r\n ],\r\n \"memory_max\": null,\r\n \"memory_mib\": 256,\r\n \"network\": null,\r\n \"pids_max\": null,\r\n \"scratch\": \"{root_json}\\\\scratch.ext4\",\r\n \"scratch_binding\": {\r\n \"device\": {int},\r\n \"fileId\": \"{hex32}\",\r\n \"kind\": \"regular\",\r\n \"length\": 8,\r\n \"scheme\": \"windows\",\r\n \"version\": 1\r\n },\r\n \"workload_gid\": 65534,\r\n \"workload_uid\": 65534\r\n}\r\n"},"state/runtime.json":{"text":"{\n \"format\": 4,\n \"launch\": \"{hex32}\",\n \"process\": {\n \"pid\": {int},\n \"startTime\": {int},\n \"boot\": \"{hex32}\"\n },\n \"endpoint\": \"//./pipe/openvmm-microvm-{hex32}\",\n \"runtime\": {\n \"openvmm\": \"sha256:1e8c924cdaac227bf74b4a4a9bcdb9e8836a1355fd0408cc81dab5d9aa71eb4d\",\n \"kernel\": \"sha256:a0c936696eb7d5ee3192bf53b9d281cecbb40ca9db520de72cb95817ad92ac72\",\n \"initramfs\": \"sha256:2f77c2c97621e8bf69794e9d12815bb7c46338638f126bea8b18dfe02a684d62\",\n \"bootContract\": 3,\n \"controlContract\": \"nvx-microvm-v2-control-v2\",\n \"controlSession\": 1\n }\n}\n"},"state/control.capability":{"size":32},"state/outcome.json":null,"state/openvmm.log":{"text":""},"build/fake-openvmm-state.json":{"text":"[\"--machine\",\"microvm\",\"--microvm-sandbox-block\",\"distro:file:\\\\\\\\?\\\\{root_json}\\\\distro.erofs,ro\",\"--microvm-sandbox-block\",\"scratch:file:\\\\\\\\?\\\\{root_json}\\\\scratch.ext4\",\"--microvm-workload-identity\",\"65534:65534\",\"--mount-aggregate\",\"/run/nvx/hostfs/root\",\"--mount-child\",\"0,{root_json}\\\\single.txt,ro,file\",\"--microvm-lifecycle\",\"managed\",\"--single-process\",\"--hypervisor\",\"whp\",\"--memory\",\"256M\",\"--kernel\",\"{root_json}\\\\build\\\\vmlinux\",\"--initrd\",\"{root_json}\\\\build\\\\initramfs.cpio.gz\",\"--cmdline\",\"nvx_sandbox=1 nvx_layer=distro,0xd0003000,erofs:11111111-1111-1111-1111-111111111111 nvx_scratch=0xd0006000,ext4 nvx_entrypoint=/bin/sh nvx_hostname=nvx-sandbox nvx_maps=1\",\"--virtio-console\",\"none\",\"--microvm-control-console\",\"listen=//./pipe/openvmm-microvm-{hex32}\",\"--microvm-control-auth-stdin\",\"--microvm-report\",\"{root_json}\\\\state\\\\outcome.json\"]"},"build/fake-openvmm-state-maps.json":{"text":"[{\"source\":\"0\",\"target\":\"/etc/single.txt\",\"read_only\":true,\"directory\":false}]"}}},{"argv":["sandbox","stop","--state-dir","{root}\\state"],"check":["state","state/config.json","state/runtime.json","state/control.capability","state/outcome.json","state/openvmm.log"],"status":0,"stdout":"","stderr":"","files":{"state":{"entries":["config.json","openvmm.log","outcome.json","sandbox.lock"]},"state/config.json":{"text":"{\r\n \"cmdline\": \"\",\r\n \"distro_binding\": {\r\n \"format\": \"erofs\",\r\n \"identity\": \"11111111-1111-1111-1111-111111111111\",\r\n \"image\": {\r\n \"changed\": null,\r\n \"device\": {int},\r\n \"fileId\": \"{hex32}\",\r\n \"kind\": \"regular\",\r\n \"length\": 7,\r\n \"modified\": {\r\n \"nanoseconds\": {int},\r\n \"seconds\": {int}\r\n },\r\n \"scheme\": \"windows\",\r\n \"version\": 1\r\n },\r\n \"manifest\": null,\r\n \"policy\": {\r\n \"result\": \"accepted\",\r\n \"revision\": 1\r\n },\r\n \"version\": 1\r\n },\r\n \"export\": {\r\n \"binds\": [\r\n {\r\n \"child\": 0,\r\n \"readOnly\": true,\r\n \"source\": \"\",\r\n \"target\": \"/etc/single.txt\"\r\n }\r\n ],\r\n \"children\": [\r\n {\r\n \"allowed\": [],\r\n \"denied\": [],\r\n \"deniedIdentities\": [],\r\n \"file\": true,\r\n \"root\": \"{root_json}\\\\single.txt\",\r\n \"writable\": false,\r\n \"write\": []\r\n }\r\n ]\r\n },\r\n \"format\": 7,\r\n \"hostname\": \"nvx-sandbox\",\r\n \"hypervisor\": \"whp\",\r\n \"layers\": [\r\n {\r\n \"path\": \"{root_json}\\\\distro.erofs\",\r\n \"role\": \"distro\",\r\n \"uuid\": \"11111111-1111-1111-1111-111111111111\"\r\n }\r\n ],\r\n \"memory_max\": null,\r\n \"memory_mib\": 256,\r\n \"network\": null,\r\n \"pids_max\": null,\r\n \"scratch\": \"{root_json}\\\\scratch.ext4\",\r\n \"scratch_binding\": {\r\n \"device\": {int},\r\n \"fileId\": \"{hex32}\",\r\n \"kind\": \"regular\",\r\n \"length\": 8,\r\n \"scheme\": \"windows\",\r\n \"version\": 1\r\n },\r\n \"workload_gid\": 65534,\r\n \"workload_uid\": 65534\r\n}\r\n"},"state/runtime.json":null,"state/control.capability":null,"state/outcome.json":{"text":"{\n \"backend\": \"whp\",\n \"instance_id\": \"{hex32}\",\n \"network_policy\": {\n \"allow_rule_count\": 0,\n \"deny_rule_count\": 0,\n \"host_loopback\": \"none\",\n \"mode\": \"none\",\n \"status\": \"not-requested\",\n \"status_code\": 0\n },\n \"outcome\": {\n \"category\": \"success\",\n \"operation\": \"managed\",\n \"status_code\": 0\n },\n \"schema_version\": 1,\n \"teardown\": {\n \"control_channels_closed\": true,\n \"guest_workload_stopped\": true,\n \"network_released\": true,\n \"openvmm_process_terminated\": true,\n \"temporary_storage_removed\": true,\n \"virtiofs_released\": true,\n \"vm_stopped\": true\n }\n}\n"},"state/openvmm.log":{"text":""}}},{"argv":["sandbox","start","--state-dir","{root}\\state"],"check":["state","state/config.json","state/runtime.json","state/control.capability","state/outcome.json","state/openvmm.log"],"status":0,"stdout":"","stderr":"","files":{"state":{"entries":["config.json","control.capability","openvmm.log","runtime.json","sandbox.lock"]},"state/config.json":{"text":"{\r\n \"cmdline\": \"\",\r\n \"distro_binding\": {\r\n \"format\": \"erofs\",\r\n \"identity\": \"11111111-1111-1111-1111-111111111111\",\r\n \"image\": {\r\n \"changed\": null,\r\n \"device\": {int},\r\n \"fileId\": \"{hex32}\",\r\n \"kind\": \"regular\",\r\n \"length\": 7,\r\n \"modified\": {\r\n \"nanoseconds\": {int},\r\n \"seconds\": {int}\r\n },\r\n \"scheme\": \"windows\",\r\n \"version\": 1\r\n },\r\n \"manifest\": null,\r\n \"policy\": {\r\n \"result\": \"accepted\",\r\n \"revision\": 1\r\n },\r\n \"version\": 1\r\n },\r\n \"export\": {\r\n \"binds\": [\r\n {\r\n \"child\": 0,\r\n \"readOnly\": true,\r\n \"source\": \"\",\r\n \"target\": \"/etc/single.txt\"\r\n }\r\n ],\r\n \"children\": [\r\n {\r\n \"allowed\": [],\r\n \"denied\": [],\r\n \"deniedIdentities\": [],\r\n \"file\": true,\r\n \"root\": \"{root_json}\\\\single.txt\",\r\n \"writable\": false,\r\n \"write\": []\r\n }\r\n ]\r\n },\r\n \"format\": 7,\r\n \"hostname\": \"nvx-sandbox\",\r\n \"hypervisor\": \"whp\",\r\n \"layers\": [\r\n {\r\n \"path\": \"{root_json}\\\\distro.erofs\",\r\n \"role\": \"distro\",\r\n \"uuid\": \"11111111-1111-1111-1111-111111111111\"\r\n }\r\n ],\r\n \"memory_max\": null,\r\n \"memory_mib\": 256,\r\n \"network\": null,\r\n \"pids_max\": null,\r\n \"scratch\": \"{root_json}\\\\scratch.ext4\",\r\n \"scratch_binding\": {\r\n \"device\": {int},\r\n \"fileId\": \"{hex32}\",\r\n \"kind\": \"regular\",\r\n \"length\": 8,\r\n \"scheme\": \"windows\",\r\n \"version\": 1\r\n },\r\n \"workload_gid\": 65534,\r\n \"workload_uid\": 65534\r\n}\r\n"},"state/runtime.json":{"text":"{\n \"format\": 4,\n \"launch\": \"{hex32}\",\n \"process\": {\n \"pid\": {int},\n \"startTime\": {int},\n \"boot\": \"{hex32}\"\n },\n \"endpoint\": \"//./pipe/openvmm-microvm-{hex32}\",\n \"runtime\": {\n \"openvmm\": \"sha256:1e8c924cdaac227bf74b4a4a9bcdb9e8836a1355fd0408cc81dab5d9aa71eb4d\",\n \"kernel\": \"sha256:a0c936696eb7d5ee3192bf53b9d281cecbb40ca9db520de72cb95817ad92ac72\",\n \"initramfs\": \"sha256:2f77c2c97621e8bf69794e9d12815bb7c46338638f126bea8b18dfe02a684d62\",\n \"bootContract\": 3,\n \"controlContract\": \"nvx-microvm-v2-control-v2\",\n \"controlSession\": 1\n }\n}\n"},"state/control.capability":{"size":32},"state/outcome.json":null,"state/openvmm.log":{"text":""}}},{"argv":["sandbox","stop","--state-dir","{root}\\state"],"check":["state","state/config.json","state/runtime.json","state/control.capability","state/outcome.json","state/openvmm.log"],"status":0,"stdout":"","stderr":"","files":{"state":{"entries":["config.json","openvmm.log","outcome.json","sandbox.lock"]},"state/config.json":{"text":"{\r\n \"cmdline\": \"\",\r\n \"distro_binding\": {\r\n \"format\": \"erofs\",\r\n \"identity\": \"11111111-1111-1111-1111-111111111111\",\r\n \"image\": {\r\n \"changed\": null,\r\n \"device\": {int},\r\n \"fileId\": \"{hex32}\",\r\n \"kind\": \"regular\",\r\n \"length\": 7,\r\n \"modified\": {\r\n \"nanoseconds\": {int},\r\n \"seconds\": {int}\r\n },\r\n \"scheme\": \"windows\",\r\n \"version\": 1\r\n },\r\n \"manifest\": null,\r\n \"policy\": {\r\n \"result\": \"accepted\",\r\n \"revision\": 1\r\n },\r\n \"version\": 1\r\n },\r\n \"export\": {\r\n \"binds\": [\r\n {\r\n \"child\": 0,\r\n \"readOnly\": true,\r\n \"source\": \"\",\r\n \"target\": \"/etc/single.txt\"\r\n }\r\n ],\r\n \"children\": [\r\n {\r\n \"allowed\": [],\r\n \"denied\": [],\r\n \"deniedIdentities\": [],\r\n \"file\": true,\r\n \"root\": \"{root_json}\\\\single.txt\",\r\n \"writable\": false,\r\n \"write\": []\r\n }\r\n ]\r\n },\r\n \"format\": 7,\r\n \"hostname\": \"nvx-sandbox\",\r\n \"hypervisor\": \"whp\",\r\n \"layers\": [\r\n {\r\n \"path\": \"{root_json}\\\\distro.erofs\",\r\n \"role\": \"distro\",\r\n \"uuid\": \"11111111-1111-1111-1111-111111111111\"\r\n }\r\n ],\r\n \"memory_max\": null,\r\n \"memory_mib\": 256,\r\n \"network\": null,\r\n \"pids_max\": null,\r\n \"scratch\": \"{root_json}\\\\scratch.ext4\",\r\n \"scratch_binding\": {\r\n \"device\": {int},\r\n \"fileId\": \"{hex32}\",\r\n \"kind\": \"regular\",\r\n \"length\": 8,\r\n \"scheme\": \"windows\",\r\n \"version\": 1\r\n },\r\n \"workload_gid\": 65534,\r\n \"workload_uid\": 65534\r\n}\r\n"},"state/runtime.json":null,"state/control.capability":null,"state/outcome.json":{"text":"{\n \"backend\": \"whp\",\n \"instance_id\": \"{hex32}\",\n \"network_policy\": {\n \"allow_rule_count\": 0,\n \"deny_rule_count\": 0,\n \"host_loopback\": \"none\",\n \"mode\": \"none\",\n \"status\": \"not-requested\",\n \"status_code\": 0\n },\n \"outcome\": {\n \"category\": \"success\",\n \"operation\": \"managed\",\n \"status_code\": 0\n },\n \"schema_version\": 1,\n \"teardown\": {\n \"control_channels_closed\": true,\n \"guest_workload_stopped\": true,\n \"network_released\": true,\n \"openvmm_process_terminated\": true,\n \"temporary_storage_removed\": true,\n \"virtiofs_released\": true,\n \"vm_stopped\": true\n }\n}\n"},"state/openvmm.log":{"text":""}}},{"argv":["sandbox","deprovision","--state-dir","{root}\\state"],"check":["state"],"status":0,"stdout":"","stderr":"","files":{"state":null}}],"interop":true}, {"name":"lifecycle: network and launch options","steps":[{"argv":["sandbox","provision","--state-dir","{root}\\state","--layer","distro,{root}\\distro.erofs,11111111-1111-1111-1111-111111111111","--scratch","{root}\\scratch.ext4","--entrypoint","/bin/server","--arg=--serve","--hostname","worker","--workload-user","1000:1000","--memory-max","268435456","--pids-max","64","--memory-mib","384","--hypervisor","auto","--cmdline","quiet","--net","10.0.0.2/24","--network-profile","portable","--network-egress","allow","--network-ingress","deny","--network-egress-policy-file","{root}\\policy.json","--host-loopback","allow","--host-loopback-forward","tcp:18080:8080","--host-loopback-forward","udp:19090:9090"],"write":{"policy.json":"{\"allow\": [{\"cidr\": \"192.0.2.0/24\", \"protocol\": \"tcp\", \"port\": 443}], \"deny\": [{\"cidr\": \"192.0.2.128/25\"}]}"},"check":["state","state/config.json","state/runtime.json","state/control.capability","state/outcome.json","state/openvmm.log"],"status":0,"stdout":"","stderr":"","files":{"state":{"entries":["config.json","sandbox.lock"]},"state/config.json":{"text":"{\r\n \"cmdline\": \"quiet\",\r\n \"distro_binding\": {\r\n \"format\": \"erofs\",\r\n \"identity\": \"11111111-1111-1111-1111-111111111111\",\r\n \"image\": {\r\n \"changed\": null,\r\n \"device\": {int},\r\n \"fileId\": \"{hex32}\",\r\n \"kind\": \"regular\",\r\n \"length\": 7,\r\n \"modified\": {\r\n \"nanoseconds\": {int},\r\n \"seconds\": {int}\r\n },\r\n \"scheme\": \"windows\",\r\n \"version\": 1\r\n },\r\n \"manifest\": null,\r\n \"policy\": {\r\n \"result\": \"accepted\",\r\n \"revision\": 1\r\n },\r\n \"version\": 1\r\n },\r\n \"format\": 1,\r\n \"hostname\": \"worker\",\r\n \"hypervisor\": \"whp\",\r\n \"layers\": [\r\n {\r\n \"path\": \"{root_json}\\\\distro.erofs\",\r\n \"role\": \"distro\",\r\n \"uuid\": \"11111111-1111-1111-1111-111111111111\"\r\n }\r\n ],\r\n \"memory_max\": 268435456,\r\n \"memory_mib\": 384,\r\n \"mount\": null,\r\n \"network\": {\r\n \"allow\": {\r\n \"name\": \"--network-egress-allow\",\r\n \"rules\": [\r\n {\r\n \"ports\": [\r\n {\r\n \"endPort\": null,\r\n \"port\": 443,\r\n \"protocol\": \"tcp\"\r\n }\r\n ],\r\n \"to\": [\r\n {\r\n \"cidr\": \"192.0.2.0/24\",\r\n \"except\": []\r\n }\r\n ]\r\n }\r\n ]\r\n },\r\n \"deny\": {\r\n \"name\": \"--network-egress-deny\",\r\n \"rules\": [\r\n {\r\n \"ports\": [],\r\n \"to\": [\r\n {\r\n \"cidr\": \"192.0.2.128/25\",\r\n \"except\": []\r\n }\r\n ]\r\n }\r\n ]\r\n },\r\n \"egress\": \"allow\",\r\n \"guestNetwork\": \"10.0.0.2/24\",\r\n \"hostLoopback\": \"allow\",\r\n \"hostLoopbackForwards\": [\r\n {\r\n \"guestPort\": 8080,\r\n \"hostPort\": 18080,\r\n \"protocol\": \"tcp\"\r\n },\r\n {\r\n \"guestPort\": 9090,\r\n \"hostPort\": 19090,\r\n \"protocol\": \"udp\"\r\n }\r\n ],\r\n \"ingress\": \"deny\",\r\n \"proxy\": null\r\n },\r\n \"pids_max\": 64,\r\n \"scratch\": \"{root_json}\\\\scratch.ext4\",\r\n \"scratch_binding\": {\r\n \"device\": {int},\r\n \"fileId\": \"{hex32}\",\r\n \"kind\": \"regular\",\r\n \"length\": 8,\r\n \"scheme\": \"windows\",\r\n \"version\": 1\r\n },\r\n \"workload_gid\": 1000,\r\n \"workload_uid\": 1000\r\n}\r\n"},"state/runtime.json":null,"state/control.capability":null,"state/outcome.json":null,"state/openvmm.log":null}},{"argv":["sandbox","start","--state-dir","{root}\\state"],"check":["state","state/config.json","state/runtime.json","state/control.capability","state/outcome.json","state/openvmm.log","build/fake-openvmm-state.json"],"status":0,"stdout":"","stderr":"","files":{"state":{"entries":["config.json","control.capability","openvmm.log","runtime.json","sandbox.lock"]},"state/config.json":{"text":"{\r\n \"cmdline\": \"quiet\",\r\n \"distro_binding\": {\r\n \"format\": \"erofs\",\r\n \"identity\": \"11111111-1111-1111-1111-111111111111\",\r\n \"image\": {\r\n \"changed\": null,\r\n \"device\": {int},\r\n \"fileId\": \"{hex32}\",\r\n \"kind\": \"regular\",\r\n \"length\": 7,\r\n \"modified\": {\r\n \"nanoseconds\": {int},\r\n \"seconds\": {int}\r\n },\r\n \"scheme\": \"windows\",\r\n \"version\": 1\r\n },\r\n \"manifest\": null,\r\n \"policy\": {\r\n \"result\": \"accepted\",\r\n \"revision\": 1\r\n },\r\n \"version\": 1\r\n },\r\n \"format\": 1,\r\n \"hostname\": \"worker\",\r\n \"hypervisor\": \"whp\",\r\n \"layers\": [\r\n {\r\n \"path\": \"{root_json}\\\\distro.erofs\",\r\n \"role\": \"distro\",\r\n \"uuid\": \"11111111-1111-1111-1111-111111111111\"\r\n }\r\n ],\r\n \"memory_max\": 268435456,\r\n \"memory_mib\": 384,\r\n \"mount\": null,\r\n \"network\": {\r\n \"allow\": {\r\n \"name\": \"--network-egress-allow\",\r\n \"rules\": [\r\n {\r\n \"ports\": [\r\n {\r\n \"endPort\": null,\r\n \"port\": 443,\r\n \"protocol\": \"tcp\"\r\n }\r\n ],\r\n \"to\": [\r\n {\r\n \"cidr\": \"192.0.2.0/24\",\r\n \"except\": []\r\n }\r\n ]\r\n }\r\n ]\r\n },\r\n \"deny\": {\r\n \"name\": \"--network-egress-deny\",\r\n \"rules\": [\r\n {\r\n \"ports\": [],\r\n \"to\": [\r\n {\r\n \"cidr\": \"192.0.2.128/25\",\r\n \"except\": []\r\n }\r\n ]\r\n }\r\n ]\r\n },\r\n \"egress\": \"allow\",\r\n \"guestNetwork\": \"10.0.0.2/24\",\r\n \"hostLoopback\": \"allow\",\r\n \"hostLoopbackForwards\": [\r\n {\r\n \"guestPort\": 8080,\r\n \"hostPort\": 18080,\r\n \"protocol\": \"tcp\"\r\n },\r\n {\r\n \"guestPort\": 9090,\r\n \"hostPort\": 19090,\r\n \"protocol\": \"udp\"\r\n }\r\n ],\r\n \"ingress\": \"deny\",\r\n \"proxy\": null\r\n },\r\n \"pids_max\": 64,\r\n \"scratch\": \"{root_json}\\\\scratch.ext4\",\r\n \"scratch_binding\": {\r\n \"device\": {int},\r\n \"fileId\": \"{hex32}\",\r\n \"kind\": \"regular\",\r\n \"length\": 8,\r\n \"scheme\": \"windows\",\r\n \"version\": 1\r\n },\r\n \"workload_gid\": 1000,\r\n \"workload_uid\": 1000\r\n}\r\n"},"state/runtime.json":{"text":"{\n \"format\": 4,\n \"launch\": \"{hex32}\",\n \"process\": {\n \"pid\": {int},\n \"startTime\": {int},\n \"boot\": \"{hex32}\"\n },\n \"endpoint\": \"//./pipe/openvmm-microvm-{hex32}\",\n \"runtime\": {\n \"openvmm\": \"sha256:1e8c924cdaac227bf74b4a4a9bcdb9e8836a1355fd0408cc81dab5d9aa71eb4d\",\n \"kernel\": \"sha256:a0c936696eb7d5ee3192bf53b9d281cecbb40ca9db520de72cb95817ad92ac72\",\n \"initramfs\": \"sha256:2f77c2c97621e8bf69794e9d12815bb7c46338638f126bea8b18dfe02a684d62\",\n \"bootContract\": 3,\n \"controlContract\": \"nvx-microvm-v2-control-v2\",\n \"controlSession\": 1\n }\n}\n"},"state/control.capability":{"size":32},"state/outcome.json":null,"state/openvmm.log":{"text":""},"build/fake-openvmm-state.json":{"text":"[\"--machine\",\"microvm\",\"--microvm-sandbox-block\",\"distro:file:\\\\\\\\?\\\\{root_json}\\\\distro.erofs,ro\",\"--microvm-sandbox-block\",\"scratch:file:\\\\\\\\?\\\\{root_json}\\\\scratch.ext4\",\"--microvm-workload-identity\",\"1000:1000\",\"--net\",\"10.0.0.2/24\",\"--network-profile\",\"portable\",\"--network-egress\",\"allow\",\"--network-ingress\",\"deny\",\"--host-loopback\",\"allow\",\"--network-egress-allow\",\"192.0.2.0/24:tcp:443\",\"--network-egress-deny\",\"192.0.2.128/25\",\"--host-loopback-forward\",\"tcp:18080:8080\",\"--host-loopback-forward\",\"udp:19090:9090\",\"--microvm-lifecycle\",\"managed\",\"--single-process\",\"--hypervisor\",\"whp\",\"--memory\",\"384M\",\"--kernel\",\"{root_json}\\\\build\\\\vmlinux\",\"--initrd\",\"{root_json}\\\\build\\\\initramfs.cpio.gz\",\"--cmdline\",\"quiet nvx_sandbox=1 nvx_layer=distro,0xd0003000,erofs:11111111-1111-1111-1111-111111111111 nvx_scratch=0xd0006000,ext4 nvx_entrypoint=/bin/sh nvx_hostname=worker nvx_memory_max=268435456 nvx_pids_max=65\",\"--virtio-console\",\"none\",\"--microvm-control-console\",\"listen=//./pipe/openvmm-microvm-{hex32}\",\"--microvm-control-auth-stdin\",\"--microvm-report\",\"{root_json}\\\\state\\\\outcome.json\"]"}}},{"argv":["sandbox","stop","--state-dir","{root}\\state"],"check":["state","state/config.json","state/runtime.json","state/control.capability","state/outcome.json","state/openvmm.log"],"status":0,"stdout":"","stderr":"","files":{"state":{"entries":["config.json","openvmm.log","outcome.json","sandbox.lock"]},"state/config.json":{"text":"{\r\n \"cmdline\": \"quiet\",\r\n \"distro_binding\": {\r\n \"format\": \"erofs\",\r\n \"identity\": \"11111111-1111-1111-1111-111111111111\",\r\n \"image\": {\r\n \"changed\": null,\r\n \"device\": {int},\r\n \"fileId\": \"{hex32}\",\r\n \"kind\": \"regular\",\r\n \"length\": 7,\r\n \"modified\": {\r\n \"nanoseconds\": {int},\r\n \"seconds\": {int}\r\n },\r\n \"scheme\": \"windows\",\r\n \"version\": 1\r\n },\r\n \"manifest\": null,\r\n \"policy\": {\r\n \"result\": \"accepted\",\r\n \"revision\": 1\r\n },\r\n \"version\": 1\r\n },\r\n \"format\": 1,\r\n \"hostname\": \"worker\",\r\n \"hypervisor\": \"whp\",\r\n \"layers\": [\r\n {\r\n \"path\": \"{root_json}\\\\distro.erofs\",\r\n \"role\": \"distro\",\r\n \"uuid\": \"11111111-1111-1111-1111-111111111111\"\r\n }\r\n ],\r\n \"memory_max\": 268435456,\r\n \"memory_mib\": 384,\r\n \"mount\": null,\r\n \"network\": {\r\n \"allow\": {\r\n \"name\": \"--network-egress-allow\",\r\n \"rules\": [\r\n {\r\n \"ports\": [\r\n {\r\n \"endPort\": null,\r\n \"port\": 443,\r\n \"protocol\": \"tcp\"\r\n }\r\n ],\r\n \"to\": [\r\n {\r\n \"cidr\": \"192.0.2.0/24\",\r\n \"except\": []\r\n }\r\n ]\r\n }\r\n ]\r\n },\r\n \"deny\": {\r\n \"name\": \"--network-egress-deny\",\r\n \"rules\": [\r\n {\r\n \"ports\": [],\r\n \"to\": [\r\n {\r\n \"cidr\": \"192.0.2.128/25\",\r\n \"except\": []\r\n }\r\n ]\r\n }\r\n ]\r\n },\r\n \"egress\": \"allow\",\r\n \"guestNetwork\": \"10.0.0.2/24\",\r\n \"hostLoopback\": \"allow\",\r\n \"hostLoopbackForwards\": [\r\n {\r\n \"guestPort\": 8080,\r\n \"hostPort\": 18080,\r\n \"protocol\": \"tcp\"\r\n },\r\n {\r\n \"guestPort\": 9090,\r\n \"hostPort\": 19090,\r\n \"protocol\": \"udp\"\r\n }\r\n ],\r\n \"ingress\": \"deny\",\r\n \"proxy\": null\r\n },\r\n \"pids_max\": 64,\r\n \"scratch\": \"{root_json}\\\\scratch.ext4\",\r\n \"scratch_binding\": {\r\n \"device\": {int},\r\n \"fileId\": \"{hex32}\",\r\n \"kind\": \"regular\",\r\n \"length\": 8,\r\n \"scheme\": \"windows\",\r\n \"version\": 1\r\n },\r\n \"workload_gid\": 1000,\r\n \"workload_uid\": 1000\r\n}\r\n"},"state/runtime.json":null,"state/control.capability":null,"state/outcome.json":{"text":"{\n \"backend\": \"whp\",\n \"instance_id\": \"{hex32}\",\n \"network_policy\": {\n \"allow_rule_count\": 1,\n \"deny_rule_count\": 1,\n \"host_loopback\": \"allow\",\n \"mode\": \"rules\",\n \"status\": \"applied\",\n \"status_code\": 0\n },\n \"outcome\": {\n \"category\": \"success\",\n \"operation\": \"managed\",\n \"status_code\": 0\n },\n \"schema_version\": 1,\n \"teardown\": {\n \"control_channels_closed\": true,\n \"guest_workload_stopped\": true,\n \"network_released\": true,\n \"openvmm_process_terminated\": true,\n \"temporary_storage_removed\": true,\n \"virtiofs_released\": true,\n \"vm_stopped\": true\n }\n}\n"},"state/openvmm.log":{"text":""}}},{"argv":["sandbox","start","--state-dir","{root}\\state"],"check":["state","state/config.json","state/runtime.json","state/control.capability","state/outcome.json","state/openvmm.log"],"status":0,"stdout":"","stderr":"","files":{"state":{"entries":["config.json","control.capability","openvmm.log","runtime.json","sandbox.lock"]},"state/config.json":{"text":"{\r\n \"cmdline\": \"quiet\",\r\n \"distro_binding\": {\r\n \"format\": \"erofs\",\r\n \"identity\": \"11111111-1111-1111-1111-111111111111\",\r\n \"image\": {\r\n \"changed\": null,\r\n \"device\": {int},\r\n \"fileId\": \"{hex32}\",\r\n \"kind\": \"regular\",\r\n \"length\": 7,\r\n \"modified\": {\r\n \"nanoseconds\": {int},\r\n \"seconds\": {int}\r\n },\r\n \"scheme\": \"windows\",\r\n \"version\": 1\r\n },\r\n \"manifest\": null,\r\n \"policy\": {\r\n \"result\": \"accepted\",\r\n \"revision\": 1\r\n },\r\n \"version\": 1\r\n },\r\n \"format\": 1,\r\n \"hostname\": \"worker\",\r\n \"hypervisor\": \"whp\",\r\n \"layers\": [\r\n {\r\n \"path\": \"{root_json}\\\\distro.erofs\",\r\n \"role\": \"distro\",\r\n \"uuid\": \"11111111-1111-1111-1111-111111111111\"\r\n }\r\n ],\r\n \"memory_max\": 268435456,\r\n \"memory_mib\": 384,\r\n \"mount\": null,\r\n \"network\": {\r\n \"allow\": {\r\n \"name\": \"--network-egress-allow\",\r\n \"rules\": [\r\n {\r\n \"ports\": [\r\n {\r\n \"endPort\": null,\r\n \"port\": 443,\r\n \"protocol\": \"tcp\"\r\n }\r\n ],\r\n \"to\": [\r\n {\r\n \"cidr\": \"192.0.2.0/24\",\r\n \"except\": []\r\n }\r\n ]\r\n }\r\n ]\r\n },\r\n \"deny\": {\r\n \"name\": \"--network-egress-deny\",\r\n \"rules\": [\r\n {\r\n \"ports\": [],\r\n \"to\": [\r\n {\r\n \"cidr\": \"192.0.2.128/25\",\r\n \"except\": []\r\n }\r\n ]\r\n }\r\n ]\r\n },\r\n \"egress\": \"allow\",\r\n \"guestNetwork\": \"10.0.0.2/24\",\r\n \"hostLoopback\": \"allow\",\r\n \"hostLoopbackForwards\": [\r\n {\r\n \"guestPort\": 8080,\r\n \"hostPort\": 18080,\r\n \"protocol\": \"tcp\"\r\n },\r\n {\r\n \"guestPort\": 9090,\r\n \"hostPort\": 19090,\r\n \"protocol\": \"udp\"\r\n }\r\n ],\r\n \"ingress\": \"deny\",\r\n \"proxy\": null\r\n },\r\n \"pids_max\": 64,\r\n \"scratch\": \"{root_json}\\\\scratch.ext4\",\r\n \"scratch_binding\": {\r\n \"device\": {int},\r\n \"fileId\": \"{hex32}\",\r\n \"kind\": \"regular\",\r\n \"length\": 8,\r\n \"scheme\": \"windows\",\r\n \"version\": 1\r\n },\r\n \"workload_gid\": 1000,\r\n \"workload_uid\": 1000\r\n}\r\n"},"state/runtime.json":{"text":"{\n \"format\": 4,\n \"launch\": \"{hex32}\",\n \"process\": {\n \"pid\": {int},\n \"startTime\": {int},\n \"boot\": \"{hex32}\"\n },\n \"endpoint\": \"//./pipe/openvmm-microvm-{hex32}\",\n \"runtime\": {\n \"openvmm\": \"sha256:1e8c924cdaac227bf74b4a4a9bcdb9e8836a1355fd0408cc81dab5d9aa71eb4d\",\n \"kernel\": \"sha256:a0c936696eb7d5ee3192bf53b9d281cecbb40ca9db520de72cb95817ad92ac72\",\n \"initramfs\": \"sha256:2f77c2c97621e8bf69794e9d12815bb7c46338638f126bea8b18dfe02a684d62\",\n \"bootContract\": 3,\n \"controlContract\": \"nvx-microvm-v2-control-v2\",\n \"controlSession\": 1\n }\n}\n"},"state/control.capability":{"size":32},"state/outcome.json":null,"state/openvmm.log":{"text":""}}},{"argv":["sandbox","stop","--state-dir","{root}\\state"],"check":["state","state/config.json","state/runtime.json","state/control.capability","state/outcome.json","state/openvmm.log"],"status":0,"stdout":"","stderr":"","files":{"state":{"entries":["config.json","openvmm.log","outcome.json","sandbox.lock"]},"state/config.json":{"text":"{\r\n \"cmdline\": \"quiet\",\r\n \"distro_binding\": {\r\n \"format\": \"erofs\",\r\n \"identity\": \"11111111-1111-1111-1111-111111111111\",\r\n \"image\": {\r\n \"changed\": null,\r\n \"device\": {int},\r\n \"fileId\": \"{hex32}\",\r\n \"kind\": \"regular\",\r\n \"length\": 7,\r\n \"modified\": {\r\n \"nanoseconds\": {int},\r\n \"seconds\": {int}\r\n },\r\n \"scheme\": \"windows\",\r\n \"version\": 1\r\n },\r\n \"manifest\": null,\r\n \"policy\": {\r\n \"result\": \"accepted\",\r\n \"revision\": 1\r\n },\r\n \"version\": 1\r\n },\r\n \"format\": 1,\r\n \"hostname\": \"worker\",\r\n \"hypervisor\": \"whp\",\r\n \"layers\": [\r\n {\r\n \"path\": \"{root_json}\\\\distro.erofs\",\r\n \"role\": \"distro\",\r\n \"uuid\": \"11111111-1111-1111-1111-111111111111\"\r\n }\r\n ],\r\n \"memory_max\": 268435456,\r\n \"memory_mib\": 384,\r\n \"mount\": null,\r\n \"network\": {\r\n \"allow\": {\r\n \"name\": \"--network-egress-allow\",\r\n \"rules\": [\r\n {\r\n \"ports\": [\r\n {\r\n \"endPort\": null,\r\n \"port\": 443,\r\n \"protocol\": \"tcp\"\r\n }\r\n ],\r\n \"to\": [\r\n {\r\n \"cidr\": \"192.0.2.0/24\",\r\n \"except\": []\r\n }\r\n ]\r\n }\r\n ]\r\n },\r\n \"deny\": {\r\n \"name\": \"--network-egress-deny\",\r\n \"rules\": [\r\n {\r\n \"ports\": [],\r\n \"to\": [\r\n {\r\n \"cidr\": \"192.0.2.128/25\",\r\n \"except\": []\r\n }\r\n ]\r\n }\r\n ]\r\n },\r\n \"egress\": \"allow\",\r\n \"guestNetwork\": \"10.0.0.2/24\",\r\n \"hostLoopback\": \"allow\",\r\n \"hostLoopbackForwards\": [\r\n {\r\n \"guestPort\": 8080,\r\n \"hostPort\": 18080,\r\n \"protocol\": \"tcp\"\r\n },\r\n {\r\n \"guestPort\": 9090,\r\n \"hostPort\": 19090,\r\n \"protocol\": \"udp\"\r\n }\r\n ],\r\n \"ingress\": \"deny\",\r\n \"proxy\": null\r\n },\r\n \"pids_max\": 64,\r\n \"scratch\": \"{root_json}\\\\scratch.ext4\",\r\n \"scratch_binding\": {\r\n \"device\": {int},\r\n \"fileId\": \"{hex32}\",\r\n \"kind\": \"regular\",\r\n \"length\": 8,\r\n \"scheme\": \"windows\",\r\n \"version\": 1\r\n },\r\n \"workload_gid\": 1000,\r\n \"workload_uid\": 1000\r\n}\r\n"},"state/runtime.json":null,"state/control.capability":null,"state/outcome.json":{"text":"{\n \"backend\": \"whp\",\n \"instance_id\": \"{hex32}\",\n \"network_policy\": {\n \"allow_rule_count\": 1,\n \"deny_rule_count\": 1,\n \"host_loopback\": \"allow\",\n \"mode\": \"rules\",\n \"status\": \"applied\",\n \"status_code\": 0\n },\n \"outcome\": {\n \"category\": \"success\",\n \"operation\": \"managed\",\n \"status_code\": 0\n },\n \"schema_version\": 1,\n \"teardown\": {\n \"control_channels_closed\": true,\n \"guest_workload_stopped\": true,\n \"network_released\": true,\n \"openvmm_process_terminated\": true,\n \"temporary_storage_removed\": true,\n \"virtiofs_released\": true,\n \"vm_stopped\": true\n }\n}\n"},"state/openvmm.log":{"text":""}}},{"argv":["sandbox","deprovision","--state-dir","{root}\\state"],"check":["state"],"status":0,"stdout":"","stderr":"","files":{"state":null}}],"interop":true}, {"name":"lifecycle: proxy-only network","steps":[{"argv":["sandbox","provision","--state-dir","{root}\\state","--layer","distro,{root}\\distro.erofs,11111111-1111-1111-1111-111111111111","--scratch","{root}\\scratch.ext4","--net","10.0.0.2/24","--network-profile","portable","--network-egress","deny","--host-loopback","deny","--network-proxy","10.0.0.1:3128"],"check":["state/config.json"],"status":0,"stdout":"","stderr":"","files":{"state/config.json":{"text":"{\r\n \"cmdline\": \"\",\r\n \"distro_binding\": {\r\n \"format\": \"erofs\",\r\n \"identity\": \"11111111-1111-1111-1111-111111111111\",\r\n \"image\": {\r\n \"changed\": null,\r\n \"device\": {int},\r\n \"fileId\": \"{hex32}\",\r\n \"kind\": \"regular\",\r\n \"length\": 7,\r\n \"modified\": {\r\n \"nanoseconds\": {int},\r\n \"seconds\": {int}\r\n },\r\n \"scheme\": \"windows\",\r\n \"version\": 1\r\n },\r\n \"manifest\": null,\r\n \"policy\": {\r\n \"result\": \"accepted\",\r\n \"revision\": 1\r\n },\r\n \"version\": 1\r\n },\r\n \"format\": 1,\r\n \"hostname\": \"nvx-sandbox\",\r\n \"hypervisor\": \"whp\",\r\n \"layers\": [\r\n {\r\n \"path\": \"{root_json}\\\\distro.erofs\",\r\n \"role\": \"distro\",\r\n \"uuid\": \"11111111-1111-1111-1111-111111111111\"\r\n }\r\n ],\r\n \"memory_max\": null,\r\n \"memory_mib\": 256,\r\n \"mount\": null,\r\n \"network\": {\r\n \"allow\": {\r\n \"name\": \"--network-egress-allow\",\r\n \"rules\": []\r\n },\r\n \"deny\": {\r\n \"name\": \"--network-egress-deny\",\r\n \"rules\": []\r\n },\r\n \"egress\": \"deny\",\r\n \"guestNetwork\": \"10.0.0.2/24\",\r\n \"hostLoopback\": \"deny\",\r\n \"hostLoopbackForwards\": [],\r\n \"ingress\": \"deny\",\r\n \"proxy\": {\r\n \"port\": 3128,\r\n \"scheme\": null\r\n }\r\n },\r\n \"pids_max\": null,\r\n \"scratch\": \"{root_json}\\\\scratch.ext4\",\r\n \"scratch_binding\": {\r\n \"device\": {int},\r\n \"fileId\": \"{hex32}\",\r\n \"kind\": \"regular\",\r\n \"length\": 8,\r\n \"scheme\": \"windows\",\r\n \"version\": 1\r\n },\r\n \"workload_gid\": 65534,\r\n \"workload_uid\": 65534\r\n}\r\n"}}},{"argv":["sandbox","start","--state-dir","{root}\\state"],"check":["build/fake-openvmm-state.json"],"status":0,"stdout":"","stderr":"","files":{"build/fake-openvmm-state.json":{"text":"[\"--machine\",\"microvm\",\"--microvm-sandbox-block\",\"distro:file:\\\\\\\\?\\\\{root_json}\\\\distro.erofs,ro\",\"--microvm-sandbox-block\",\"scratch:file:\\\\\\\\?\\\\{root_json}\\\\scratch.ext4\",\"--microvm-workload-identity\",\"65534:65534\",\"--net\",\"10.0.0.2/24\",\"--network-profile\",\"portable\",\"--network-egress\",\"deny\",\"--network-ingress\",\"deny\",\"--host-loopback\",\"deny\",\"--network-proxy\",\"10.0.0.1:3128\",\"--microvm-lifecycle\",\"managed\",\"--single-process\",\"--hypervisor\",\"whp\",\"--memory\",\"256M\",\"--kernel\",\"{root_json}\\\\build\\\\vmlinux\",\"--initrd\",\"{root_json}\\\\build\\\\initramfs.cpio.gz\",\"--cmdline\",\"nvx_sandbox=1 nvx_layer=distro,0xd0003000,erofs:11111111-1111-1111-1111-111111111111 nvx_scratch=0xd0006000,ext4 nvx_entrypoint=/bin/sh nvx_hostname=nvx-sandbox\",\"--virtio-console\",\"none\",\"--microvm-control-console\",\"listen=//./pipe/openvmm-microvm-{hex32}\",\"--microvm-control-auth-stdin\",\"--microvm-report\",\"{root_json}\\\\state\\\\outcome.json\"]"}}},{"argv":["sandbox","stop","--state-dir","{root}\\state"],"status":0,"stdout":"","stderr":""},{"argv":["sandbox","deprovision","--state-dir","{root}\\state"],"check":["state"],"status":0,"stdout":"","stderr":"","files":{"state":null}}]}, {"name":"state: operations without a sandbox","steps":[{"argv":["sandbox","start","--state-dir","{root}\\state"],"status":1,"stdout":"","stderr":"error: sandbox state path is not a plain directory: {root}\\state\r\n"},{"argv":["sandbox","exec","--state-dir","{root}\\state"],"status":1,"stdout":"","stderr":"error: sandbox state path is not a plain directory: {root}\\state\r\n"},{"argv":["sandbox","stop","--state-dir","{root}\\state"],"status":1,"stdout":"","stderr":"error: sandbox state path is not a plain directory: {root}\\state\r\n"},{"argv":["sandbox","deprovision","--state-dir","{root}\\state"],"status":1,"stdout":"","stderr":"error: sandbox state path is not a plain directory: {root}\\state\r\n"}]}, diff --git a/scripts/test_nvx_tools.py b/scripts/test_nvx_tools.py index 2c291650c..a3de327ae 100644 --- a/scripts/test_nvx_tools.py +++ b/scripts/test_nvx_tools.py @@ -17807,6 +17807,7 @@ def setUp(self): "parse_share_child", "bind_live_share", "mount_live_shares", + "mount_host_export", ) def _aggregate(self, *children: str, mode: str = "rw") -> str: @@ -17821,7 +17822,23 @@ def _aggregate(self, *children: str, mode: str = "rw") -> str: ] return " ".join(tokens) - def _run(self, cmdline: str) -> tuple[subprocess.CompletedProcess[str], str]: + def _export( + self, *extra: str, directory: str | None = None, mode: str = "rw" + ) -> str: + """Returns the bootstrap of a managed sandbox's host export at + `directory`, by default its place, followed by the tokens `extra`.""" + tokens = [ + f"virtfs_dir={directory or self.runtime + '/hostfs/root'}", + "virtfs_tag=microvm", + f"virtfs_mode={mode}", + "virtfs_aggregate=1", + *extra, + ] + return " ".join(tokens) + + def _run( + self, cmdline: str, function: str = "mount_live_shares" + ) -> tuple[subprocess.CompletedProcess[str], str]: mount_log = self.root / "mount.log" mount_log.unlink(missing_ok=True) functions = "".join( @@ -17830,10 +17847,11 @@ def _run(self, cmdline: str) -> tuple[subprocess.CompletedProcess[str], str]: script = ( "set -eu\n" "rootfs=$1\ncmdline=$2\nmount_log=$3\nruntime=$4\nshare_mountpoints=\n" + "hostfs=$runtime/hostfs\n" 'fatal() { echo "FATAL: $*" >&2; exit 125; }\n' 'mount() { printf "%s\\n" "$*" >>"$mount_log"; }\n' f"{functions}" - "mount_live_shares\n" + f"{function}\n" "echo \"mountpoints=$(printf '%s' \"$share_mountpoints\" | tr '\\n' ' ')\"\n" ) result = subprocess.run( @@ -17902,7 +17920,16 @@ def _run_teardown( return result, lines def test_agent_mounts_share_after_lifecycle_checks_for_both_lifecycles(self): - mount_call = self.source.index("\nmount_live_shares\n") + # A one-shot sandbox binds its shares from their tokens, and a managed + # sandbox mounts only the export from which its agent maps them. + mount_call = self.source.index( + '\ncase "$workload_lifecycle" in\n' + " managed) mount_host_export ;;\n" + " *) mount_live_shares ;;\n" + "esac\n" + ) + self.assertEqual(self.source.count("\n *) mount_live_shares ;;\n"), 1) + self.assertEqual(self.source.count("mount_host_export ;;"), 1) self.assertLess( self.source.index('fatal "configured workload home is unavailable"'), mount_call, @@ -18079,6 +18106,86 @@ def test_agent_mounts_share_inside_container_rootfs(self): result.stdout, ) + def test_managed_agent_mounts_no_export_without_bootstrap_tokens(self): + result, log = self._run("console=hvc0 nvx_sandbox=1", "mount_host_export") + self.assertEqual(result.returncode, 0, result.stderr) + self.assertIn("mountpoints=\n", result.stdout) + self.assertEqual(log, "") + self.assertFalse((self.root / "run" / "hostfs").exists()) + + def test_managed_agent_mounts_the_export_where_only_root_can_enter(self): + runtime = self.root / "run" + runtime.mkdir() + hostfs = runtime / "hostfs" + for mode in ("rw", "ro"): + with self.subTest(mode=mode): + shutil.rmtree(hostfs, ignore_errors=True) + result, log = self._run( + self._export("nvx_maps=2", mode=mode), "mount_host_export" + ) + self.assertEqual(result.returncode, 0, result.stderr) + self.assertEqual( + log.splitlines(), + [ + f"-t virtiofs -o {mode},nosuid,nodev microvm " + f"{self.runtime}/hostfs/root" + ], + ) + self.assertIn( + f"NVX-SANDBOX-EXPORT: mode={mode} tag=microvm\n", result.stdout + ) + # Teardown unmounts the export like a share. + self.assertIn( + f"mountpoints={self.runtime}/hostfs/root\n", result.stdout + ) + self.assertTrue((hostfs / "root").is_dir()) + if os.name == "posix": + self.assertEqual(hostfs.stat().st_mode & 0o777, 0o700) + # The agent maps into the container rootfs; the shell binds nothing. + self.assertEqual(list(self.rootfs.iterdir()), []) + + def test_managed_agent_refuses_share_tokens_and_other_exports(self): + (self.root / "run").mkdir() + export = f"{self.runtime}/hostfs/root" + for cmdline, message in ( + ( + self._export("nvx_share=0,/workspace,rw"), + "not from nvx_share= tokens", + ), + ("nvx_share=0,/workspace,rw", "not from nvx_share= tokens"), + ( + self._export(directory=f"{self.runtime}/shares"), + f"the host export must be mounted at {export}", + ), + (self._export(directory="/workspace"), "must be mounted at"), + ( + self._export().replace(" virtfs_aggregate=1", ""), + "host export bootstrap is incomplete", + ), + ("virtfs_aggregate=1", "host export bootstrap is incomplete"), + (self._export(f"virtfs_dir={export}"), "bootstrap is incomplete"), + (self._export("virtfs_tag="), "bootstrap is incomplete"), + ( + self._export().replace("virtfs_tag=microvm", "virtfs_tag=a.b"), + "host export tag is invalid", + ), + (self._export(mode="rx"), "host export mode is unsupported: rx"), + ): + with self.subTest(cmdline=cmdline): + result, log = self._run(cmdline, "mount_host_export") + self.assertEqual(result.returncode, 125, result.stdout) + self.assertIn(message, result.stderr) + # Every token is checked before anything is created or mounted. + self.assertEqual(log, "") + self.assertFalse((self.root / "run" / "hostfs").exists()) + + def test_managed_agent_refuses_an_export_directory_that_exists(self): + (self.root / "run" / "hostfs").mkdir(parents=True) + result, log = self._run(self._export(), "mount_host_export") + self.assertEqual(result.returncode, 125, result.stdout) + self.assertIn("failed to create the host export directory", result.stderr) + self.assertEqual(log, "") + def test_agent_binds_every_child_of_an_aggregate(self): rootfs = self.rootfs.as_posix() result, log = self._run(