Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 30 additions & 8 deletions nvx-rs/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -45,12 +45,12 @@ nvx-rs/
│ ├── error.rs nvx::Error, its ErrorKind, and its stable ErrorCode
│ ├── exec/ the execution engine: the streams, credit, and outcome of an execution's two
│ │ sides, without I/O, threads, or features, for any framing and host
│ ├── host/ feature `host` (default): artifacts, launch, network and egress policy files,
│ │ filesystem, NVXS connection, session, process, platform, VM instances,
│ │ sandbox stores, templates' manifests, compatibility keys, store, and leases,
│ │ outcome reports, file seals, and the sandbox launch profile of
│ │ `nvx-rs sandbox`, its distro and scratch bindings, and its prepared launches;
│ │ with feature `cli`, the `nvx-rs` CLI
│ ├── host/ feature `host` (default): the runtime that every launch shares, artifacts,
│ │ launch, network and egress policy files, filesystem, NVXS connection, session,
│ │ process, platform, VM instances, sandbox stores, templates' manifests,
│ │ compatibility keys, store, and leases, outcome reports, file seals, and the
│ │ sandbox launch profile of `nvx-rs sandbox`, its distro and scratch bindings,
│ │ and its prepared launches; with feature `cli`, the `nvx-rs` CLI
│ ├── testing/ feature `testing`: the fake OpenVMM
│ ├── guest/ feature `guest`: the programs that run in Linux guests, the guest's NVXS
│ │ connection, the libraries through which a guest init or agent opens the
Expand Down Expand Up @@ -120,6 +120,7 @@ changes only when the module's purpose does.
| [`nvx::uuid`](#nvxuuid) | UUIDs, such as those of GPT disks and filesystems, in their canonical text and in GPT's layout |
| [`nvx::Hypervisor`](#nvxhypervisor) | KVM, MSHV, or WHP, with its serde form behind the `serde` feature |
| [`nvx::exec`](#nvxexec) | The execution engine: the streams, credit, and outcome of an execution's two sides, without I/O, for any framing |
| [`nvx::host::runtime`](#nvxhostruntime) | `Runtime`: what every launch shares, the runtime's files and their identity, the hypervisor and its probe, and the launch options |
| [`nvx::host::artifacts`](#nvxhostartifacts) | Locating the OpenVMM executable and the guest artifacts that a VM runs, and their runtime identity |
| [`nvx::host::launch`](#nvxhostlaunch) | `LaunchSpec` and `VmmLaunch`: the OpenVMM command line of a managed microVM, its checks, and the inputs that it shares with an adapter's launch |
| [`nvx::host::network`](#nvxhostnetwork) | The one lowering of a network posture into OpenVMM options, for the CLI and external orchestrators |
Expand Down Expand Up @@ -379,6 +380,26 @@ The adapter chooses one byte window per stream, or frames charged against one
pool that stdout and stderr share, and the maximum chunk, in `Limits`; a `Key`'s
generation tells stale messages from foreign ones.

### `nvx::host::runtime`

`Runtime`: what every launch shares, the paths of the OpenVMM executable, guest
kernel, and guest initramfs, their `RuntimeIdentity`, the hypervisor, an
optional CPU profile, whether OpenVMM breaks away from the caller's Windows job
object, and the `LaunchOptions`. Those are what OpenVMM does when the guest
powers off, a `GuestPowerAction`, by default `Exit`, which ends the VM, or
`Halt` or `Reset`, and how long OpenVMM waits for the host to authenticate on
the control console. The boot console is not among them: each VM attaches its
own.

`RuntimeIdentity` labels the three files with the `ArtifactIdentity` tokens that
their install or staging metadata gives, such as `sha256:` and a digest, which
NVX compares and never computes, and adds the versions of the contracts that the
crate speaks; `differences` names the `IdentityPart`s in which two identities
differ. The sandbox store records it with each VM, and re-exports its types.

`probe_hypervisor` checks that the host has the hypervisor: its device on Linux,
and the Windows Hypervisor Platform on Windows.

### `nvx::host::artifacts`

`Artifacts` (also `nvx::Artifacts`): the OpenVMM executable, guest kernel, and
Expand Down Expand Up @@ -2563,12 +2584,13 @@ optional cause.
| `ErrorKind` | Meaning |
| --- | --- |
| `Unavailable` | A missing or unusable artifact, hypervisor, or release, a guest image without a required control feature, or an unsupported host |
| `Unsupported` | A well-formed request that NVX cannot represent or enforce, such as a policy beyond a limit of OpenVMM or the guest agent |
| `Unsupported` | A request that NVX refuses: a value that it does not accept, such as a malformed or out-of-range one, options that it cannot combine, or a request that it cannot represent or enforce, such as a policy beyond a limit of OpenVMM or the guest agent |
| `Exited` | The VM's OpenVMM process exited |
| `Io` | A host I/O failure, or state that NVX recorded on the host and cannot read |
| `NotFound` | State that an operation names and that does not exist on the host, such as the store of a sandbox that was never created or that a removal deleted |
| `Protocol` | A control session that failed, or a request that the guest agent refused |
| `TimedOut` | A deadline that passed |
| `RuntimeMismatch` | A VM that runs under another runtime identity than the artifacts', which NVX does not drive: only a stop, which terminates it, applies |
| `Other` | Any other failure |

Messages call an instance `sandbox NAME`, after the name that `Instance::create`
Expand Down Expand Up @@ -2612,7 +2634,7 @@ usage errors, which no library error has.
| `sandbox-running` | `Other` | The operation needs a stopped sandbox, but its VM, or a launch of it, may still run |
| `sandbox-exited` | `Exited` | The sandbox's VM exited without a stop: the transition that finds it clears its runtime record, and a start launches it again |
| `sandbox-busy` | `TimedOut` | Another lifecycle transition of the sandbox held its lock until the deadline passed |
| `runtime-mismatch` | `Other` | The sandbox's VM runs under another runtime identity than the artifacts', whose differing parts the message names, so only a stop, which terminates it, applies |
| `runtime-mismatch` | `RuntimeMismatch` | The sandbox's VM runs under another runtime identity than the artifacts', whose differing parts the message names, so only a stop, which terminates it, applies |
| `vmm-indeterminate` | `Other` | Whether the OpenVMM process of the sandbox runs cannot be determined, so its records remain for a later attempt |
| `format-unsupported` | `Io` | A record or report has a format or schema version that this build does not read, such as the state of a sandbox that another build provisioned or started |
| `foreign-files` | `Other` | A directory of NVX's state, such as a sandbox's state directory or a template store, holds files that NVX does not own, which the message names and NVX keeps |
Expand Down
44 changes: 43 additions & 1 deletion nvx-rs/public-api/linux.txt
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@ variant nvx::ErrorKind::Io
variant nvx::ErrorKind::NotFound
variant nvx::ErrorKind::Other
variant nvx::ErrorKind::Protocol
variant nvx::ErrorKind::RuntimeMismatch
variant nvx::ErrorKind::TimedOut
variant nvx::ErrorKind::Unavailable
variant nvx::ErrorKind::Unsupported
Expand Down Expand Up @@ -2015,7 +2016,6 @@ method nvx::host::platform::Transport::write_all
type nvx::host::platform::TransportHandle
fn nvx::host::platform::create_private_dir
fn nvx::host::platform::file_identity
fn nvx::host::platform::probe_hypervisor
fn nvx::host::platform::process_start_time
mod nvx::host::process
struct nvx::host::process::BootId
Expand Down Expand Up @@ -2044,6 +2044,48 @@ field nvx::host::report::Report::category
field nvx::host::report::Report::status_code
field nvx::host::report::Report::teardown_complete
fn nvx::host::report::read
mod nvx::host::runtime
struct nvx::host::runtime::ArtifactIdentity
method nvx::host::runtime::ArtifactIdentity::as_str
method nvx::host::runtime::ArtifactIdentity::new
method nvx::host::runtime::ArtifactIdentity::sha256
enum nvx::host::runtime::GuestPowerAction
variant nvx::host::runtime::GuestPowerAction::Exit
variant nvx::host::runtime::GuestPowerAction::Halt
variant nvx::host::runtime::GuestPowerAction::Reset
enum nvx::host::runtime::IdentityPart
const nvx::host::runtime::IdentityPart::ALL
variant nvx::host::runtime::IdentityPart::BootContract
variant nvx::host::runtime::IdentityPart::ControlContract
variant nvx::host::runtime::IdentityPart::ControlSession
variant nvx::host::runtime::IdentityPart::Initramfs
variant nvx::host::runtime::IdentityPart::Kernel
variant nvx::host::runtime::IdentityPart::OpenVmm
method nvx::host::runtime::IdentityPart::name
struct nvx::host::runtime::LaunchOptions
field nvx::host::runtime::LaunchOptions::control_auth_timeout
field nvx::host::runtime::LaunchOptions::guest_shutdown
const nvx::host::runtime::MAX_IDENTITY_LEN
struct nvx::host::runtime::Runtime
field nvx::host::runtime::Runtime::cpu_profile
field nvx::host::runtime::Runtime::hypervisor
field nvx::host::runtime::Runtime::identity
field nvx::host::runtime::Runtime::initramfs
field nvx::host::runtime::Runtime::kernel
field nvx::host::runtime::Runtime::openvmm
field nvx::host::runtime::Runtime::options
field nvx::host::runtime::Runtime::windows_breakaway
struct nvx::host::runtime::RuntimeIdentity
field nvx::host::runtime::RuntimeIdentity::boot_contract
method nvx::host::runtime::RuntimeIdentity::check
field nvx::host::runtime::RuntimeIdentity::control_contract
field nvx::host::runtime::RuntimeIdentity::control_session
method nvx::host::runtime::RuntimeIdentity::differences
field nvx::host::runtime::RuntimeIdentity::initramfs
field nvx::host::runtime::RuntimeIdentity::kernel
method nvx::host::runtime::RuntimeIdentity::new
field nvx::host::runtime::RuntimeIdentity::openvmm
fn nvx::host::runtime::probe_hypervisor
mod nvx::host::sandbox
enum nvx::host::sandbox::BlockRole
variant nvx::host::sandbox::BlockRole::Distro
Expand Down
44 changes: 43 additions & 1 deletion nvx-rs/public-api/windows.txt
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@ variant nvx::ErrorKind::Io
variant nvx::ErrorKind::NotFound
variant nvx::ErrorKind::Other
variant nvx::ErrorKind::Protocol
variant nvx::ErrorKind::RuntimeMismatch
variant nvx::ErrorKind::TimedOut
variant nvx::ErrorKind::Unavailable
variant nvx::ErrorKind::Unsupported
Expand Down Expand Up @@ -953,7 +954,6 @@ method nvx::host::platform::Transport::write_all
type nvx::host::platform::TransportHandle
fn nvx::host::platform::create_private_dir
fn nvx::host::platform::file_identity
fn nvx::host::platform::probe_hypervisor
fn nvx::host::platform::process_start_time
mod nvx::host::process
struct nvx::host::process::BootId
Expand Down Expand Up @@ -982,6 +982,48 @@ field nvx::host::report::Report::category
field nvx::host::report::Report::status_code
field nvx::host::report::Report::teardown_complete
fn nvx::host::report::read
mod nvx::host::runtime
struct nvx::host::runtime::ArtifactIdentity
method nvx::host::runtime::ArtifactIdentity::as_str
method nvx::host::runtime::ArtifactIdentity::new
method nvx::host::runtime::ArtifactIdentity::sha256
enum nvx::host::runtime::GuestPowerAction
variant nvx::host::runtime::GuestPowerAction::Exit
variant nvx::host::runtime::GuestPowerAction::Halt
variant nvx::host::runtime::GuestPowerAction::Reset
enum nvx::host::runtime::IdentityPart
const nvx::host::runtime::IdentityPart::ALL
variant nvx::host::runtime::IdentityPart::BootContract
variant nvx::host::runtime::IdentityPart::ControlContract
variant nvx::host::runtime::IdentityPart::ControlSession
variant nvx::host::runtime::IdentityPart::Initramfs
variant nvx::host::runtime::IdentityPart::Kernel
variant nvx::host::runtime::IdentityPart::OpenVmm
method nvx::host::runtime::IdentityPart::name
struct nvx::host::runtime::LaunchOptions
field nvx::host::runtime::LaunchOptions::control_auth_timeout
field nvx::host::runtime::LaunchOptions::guest_shutdown
const nvx::host::runtime::MAX_IDENTITY_LEN
struct nvx::host::runtime::Runtime
field nvx::host::runtime::Runtime::cpu_profile
field nvx::host::runtime::Runtime::hypervisor
field nvx::host::runtime::Runtime::identity
field nvx::host::runtime::Runtime::initramfs
field nvx::host::runtime::Runtime::kernel
field nvx::host::runtime::Runtime::openvmm
field nvx::host::runtime::Runtime::options
field nvx::host::runtime::Runtime::windows_breakaway
struct nvx::host::runtime::RuntimeIdentity
field nvx::host::runtime::RuntimeIdentity::boot_contract
method nvx::host::runtime::RuntimeIdentity::check
field nvx::host::runtime::RuntimeIdentity::control_contract
field nvx::host::runtime::RuntimeIdentity::control_session
method nvx::host::runtime::RuntimeIdentity::differences
field nvx::host::runtime::RuntimeIdentity::initramfs
field nvx::host::runtime::RuntimeIdentity::kernel
method nvx::host::runtime::RuntimeIdentity::new
field nvx::host::runtime::RuntimeIdentity::openvmm
fn nvx::host::runtime::probe_hypervisor
mod nvx::host::sandbox
enum nvx::host::sandbox::BlockRole
variant nvx::host::sandbox::BlockRole::Distro
Expand Down
8 changes: 4 additions & 4 deletions nvx-rs/src/contract.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,10 @@
//! compatibility of NVX releases with them.
//!
//! The store records the boot contract, control contract, and control session versions of the
//! build that started a VM in the VM's runtime identity, `nvx::host::store::RuntimeIdentity`, and a
//! build drives only the VMs whose runtime identity is its own. So each version changes whenever a
//! guest that a build of the earlier version started could not be driven as one that a build of
//! the later version starts:
//! build that started a VM in the VM's runtime identity, `nvx::host::runtime::RuntimeIdentity`,
//! and a build drives only the VMs whose runtime identity is its own. So each version changes
//! whenever a guest that a build of the earlier version started could not be driven as one that a
//! build of the later version starts:
//!
//! - [`MICROVM_ABI_VERSION`] is the microVM ABI of the pinned OpenVMM: the machine, its devices,
//! and their addresses, through which OpenVMM boots the guest and saves its state. It changes
Expand Down
16 changes: 11 additions & 5 deletions nvx-rs/src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,9 @@ pub enum ErrorKind {
/// guest image without the control contract or features that this crate needs, or a host
/// that NVX does not support.
Unavailable,
/// The request is well formed, but NVX cannot represent or enforce it, for example because it
/// exceeds a limit of OpenVMM or the guest agent.
/// NVX refuses the request: a value that it does not accept, such as a malformed or
/// out-of-range one, options that it cannot combine, or a request that it cannot represent or
/// enforce, for example because it exceeds a limit of OpenVMM or the guest agent.
Unsupported,
/// The OpenVMM process of a VM exited.
Exited,
Expand All @@ -29,6 +30,9 @@ pub enum ErrorKind {
Protocol,
/// A deadline passed.
TimedOut,
/// A VM runs under another runtime identity than the artifacts', so NVX does not drive it:
/// only a stop, which terminates it, applies.
RuntimeMismatch,
/// Any other failure.
Other,
}
Expand All @@ -44,6 +48,7 @@ impl ErrorKind {
Self::NotFound => "not-found",
Self::Protocol => "protocol",
Self::TimedOut => "timed-out",
Self::RuntimeMismatch => "runtime-mismatch",
Self::Other => "other",
}
}
Expand Down Expand Up @@ -160,7 +165,7 @@ pub enum ErrorCode {
}

impl ErrorCode {
/// Every code of this release, the codes of the kinds first.
/// Every code of this release.
pub const ALL: &'static [ErrorCode] = &[
Self::Unavailable,
Self::Unsupported,
Expand Down Expand Up @@ -216,7 +221,7 @@ impl ErrorCode {
Self::SandboxRunning => "sandbox-running",
Self::SandboxExited => "sandbox-exited",
Self::SandboxBusy => "sandbox-busy",
Self::RuntimeMismatch => "runtime-mismatch",
Self::RuntimeMismatch => ErrorKind::RuntimeMismatch.as_str(),
Self::VmmIndeterminate => "vmm-indeterminate",
Self::FormatUnsupported => "format-unsupported",
Self::ForeignFiles => "foreign-files",
Expand Down Expand Up @@ -247,11 +252,11 @@ impl ErrorCode {
Self::NotFound | Self::SandboxNotProvisioned => ErrorKind::NotFound,
Self::Protocol | Self::ExecRefused | Self::EndpointClosed => ErrorKind::Protocol,
Self::TimedOut | Self::SandboxBusy | Self::ScratchClaimed => ErrorKind::TimedOut,
Self::RuntimeMismatch => ErrorKind::RuntimeMismatch,
Self::Other
| Self::SandboxProvisioned
| Self::SandboxNotRunning
| Self::SandboxRunning
| Self::RuntimeMismatch
| Self::VmmIndeterminate
| Self::ForeignFiles
| Self::OutcomeReportExists
Expand All @@ -277,6 +282,7 @@ impl From<ErrorKind> for ErrorCode {
ErrorKind::NotFound => Self::NotFound,
ErrorKind::Protocol => Self::Protocol,
ErrorKind::TimedOut => Self::TimedOut,
ErrorKind::RuntimeMismatch => Self::RuntimeMismatch,
ErrorKind::Other => Self::Other,
}
}
Expand Down
12 changes: 12 additions & 0 deletions nvx-rs/src/error/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,10 +24,21 @@ fn codes_determine_kinds() {
assert_eq!(error.code(), ErrorCode::SandboxExited);
assert_eq!(error.kind(), ErrorKind::Exited);
assert_eq!(error.into_parts().0, ErrorKind::Exited);
let mismatch = Error::new(ErrorCode::RuntimeMismatch, "another runtime");
assert_eq!(mismatch.code(), ErrorCode::RuntimeMismatch);
assert_eq!(mismatch.kind(), ErrorKind::RuntimeMismatch);
let (kind, message, source) = mismatch.into_parts();
assert_eq!(kind, ErrorKind::RuntimeMismatch);
assert_eq!(message, "another runtime");
assert!(source.is_none());
assert_eq!(
Error::new(ErrorKind::TimedOut, "late").code(),
ErrorCode::TimedOut
);
assert_eq!(
Error::new(ErrorKind::RuntimeMismatch, "elsewhere").code(),
ErrorCode::RuntimeMismatch
);
assert_eq!(Error::unsupported("no").code(), ErrorCode::Unsupported);
assert_eq!(
ErrorCode::SandboxNotRunning.to_string(),
Expand All @@ -45,6 +56,7 @@ fn every_kind_has_a_code_of_its_own_spelling() {
ErrorKind::NotFound,
ErrorKind::Protocol,
ErrorKind::TimedOut,
ErrorKind::RuntimeMismatch,
ErrorKind::Other,
] {
let code = ErrorCode::from(kind);
Expand Down
2 changes: 1 addition & 1 deletion nvx-rs/src/host/artifacts/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -146,7 +146,7 @@ impl Artifacts {
///
/// Fails with [`ErrorKind::Unavailable`](crate::ErrorKind::Unavailable) otherwise, with the
/// code [`ErrorCode::ArtifactMissing`] for a missing file. It does not check the hypervisor;
/// [`probe_hypervisor`](super::platform::probe_hypervisor) does.
/// [`probe_hypervisor`](super::runtime::probe_hypervisor) does.
pub fn probe(&self) -> Result<()> {
if !platform::SUPPORTED {
return Err(Error::unavailable(
Expand Down
5 changes: 5 additions & 0 deletions nvx-rs/src/host/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@
//!
//! - [`artifacts`] locates the OpenVMM executable and the guest kernel and initramfs, and every
//! artifact of the guests that `nvx.py` runs, in a repository checkout or a release.
//! - [`runtime`] holds what every launch shares: the paths of those three files and their
//! [`RuntimeIdentity`](runtime::RuntimeIdentity), the hypervisor, which
//! [`probe_hypervisor`](runtime::probe_hypervisor) checks, and the
//! [`LaunchOptions`](runtime::LaunchOptions).
//! - [`launch`] builds OpenVMM's command line from a [`LaunchSpec`](launch::LaunchSpec): the
//! managed lifecycle, the workload identity, the kernel command line, and the network and
//! filesystem options.
Expand Down Expand Up @@ -73,6 +77,7 @@ pub(crate) mod paths;
pub mod platform;
pub mod process;
pub mod report;
pub mod runtime;
pub mod sandbox;
pub mod seal;
pub mod session;
Expand Down
Loading
Loading