diff --git a/doc/usage.md b/doc/usage.md index c0e223c97..275e23a42 100644 --- a/doc/usage.md +++ b/doc/usage.md @@ -84,7 +84,7 @@ the command. The usage errors that `nvx.py` itself reports, as `argparse` does, carry no code, and neither does an interruption by SIGINT or, outside Windows, SIGTERM, which prints `Interrupted` and exits with status 130. The [`nvx-rs` README](../nvx-rs/README.md#error-codes) gives the `ErrorKind` of -each code for callers of the `nvx` library. +each code, which callers of the `nvx` library see in its place. | Code | Status | Meaning | | --- | --- | --- | @@ -106,9 +106,6 @@ each code for callers of the `nvx` library. | `foreign-files` | 1 | `deprovision` found files that NVX does not own in the state directory, which the message names, and kept them with the directory. | | `outcome-report-exists` | 1 | A file exists at the `--outcome-report` path. | | `scratch-claimed` | 1 | Another sandbox claims the scratch image. | -| `sandbox-leased` | 1 | The sandbox holds a lease of a template's generation, which allows no other lease, and one launch of its clone, until a release ends it once its VM has exited. | -| `template-ineligible` | 1 | The restore window of a template's generation, which the time contract of its capture sets, excludes the host's time, so no clone may restore it now. | -| `template-tombstoned` | 1 | A tombstone quarantines the template's generation, which takes no new clones. | | `exited` | 1 | OpenVMM exited, as when a start fails, whose message names the category and status of OpenVMM's outcome report when it has one. | | `still-running` | 1 | A stop could not confirm the VM process's exit, so the caller keeps its verified process. | | `exec-refused` | 1 | The guest agent refused the workload, as for a working directory that it cannot use. | diff --git a/nvx-rs/README.md b/nvx-rs/README.md index a6506e192..9d1db5cb0 100644 --- a/nvx-rs/README.md +++ b/nvx-rs/README.md @@ -42,7 +42,7 @@ nvx-rs/ │ ├── uuid.rs UUIDs in their canonical text and in GPT's layout; no dependencies, shared │ │ by the host and the guest │ ├── hypervisor.rs -│ ├── error.rs nvx::Error, its ErrorKind, and its stable ErrorCode +│ ├── error.rs nvx::Error, its ErrorKind, and the stable codes that the CLI prints │ ├── host/ feature `host` (default): the runtime that every launch shares, VM │ │ directories and configurations, artifacts, network and egress policy files, │ │ filesystem, NVXS connection, session, process, platform, templates' @@ -2342,9 +2342,11 @@ fn main() -> Result<(), Box> { ## Errors -Every fallible operation returns `nvx::Error`: a message that callers can show -as is, an `ErrorCode`, which determines the error's `ErrorKind`, and an -optional cause. +Every fallible operation returns `nvx::Error`, which only `nvx` makes: a +message that callers can show as is, an `ErrorKind`, and an optional cause. +Callers tell errors apart by their kinds, and by stable fragments of their +messages, such as the names of options, fields, files, and processes, since the +wording of a message may change. | `ErrorKind` | Meaning | | --- | --- | @@ -2361,20 +2363,20 @@ optional cause. ### Error codes -An `ErrorCode` is finer than an `ErrorKind`: callers tell errors apart by their -codes, and by stable fragments of their messages, such as the names of options, -fields, files, and processes, since the wording of a message may change. The -[CLI](#the-nvx-rs-cli) prints the code of each error that it reports. - -`ErrorCode::as_str` spells a code in lowercase ASCII words joined by hyphens. A -failure that a caller can act on has a code of its own, which names the subject -of the failure and then its condition, such as `sandbox-not-running`. Any other -failure has the code of its kind, which is spelled as the kind, such as `io`, -and which an `ErrorKind` converts into. A code keeps its spelling, its kind, and -its meaning, and is never reused for another failure: a failure that callers -come to act on gets a new code, so a caller treats a code that it does not know -as a failure of the operation. The `argument-*` codes are those of the CLI's -usage errors, which no library error has. +The [CLI](#the-nvx-rs-cli) prints a stable code with each error that it +reports, finer than the error's `ErrorKind`, by which callers of the CLI tell +errors apart. The codes are private to `nvx`: callers of the library see the +kind of each code, which the table gives. + +A code is spelled in lowercase ASCII words joined by hyphens. A failure that a +caller can act on has a code of its own, which names the subject of the failure +and then its condition, such as `sandbox-not-running`. Any other failure has +the code of its kind, which is spelled as the kind, such as `io`. A code keeps +its spelling, its kind, and its meaning, and is never reused for another +failure: a failure that callers come to act on gets a new code, so a caller +treats a code that it does not know as a failure of the operation. The +`argument-*` codes are those of the CLI's usage errors, which no library error +has. | Code | `ErrorKind` | Meaning | | --- | --- | --- | @@ -2405,9 +2407,6 @@ usage errors, which no library error has. | `scratch-claimed` | `TimedOut` | Another sandbox claims the scratch image | | `exec-refused` | `Protocol` | The guest agent refused the workload, as for a working directory that it cannot use | | `endpoint-closed` | `Protocol` | OpenVMM closed the control endpoint, as it does when the VM shuts down | -| `template-ineligible` | `Unavailable` | The restore window of a template's generation, which the time contract of its capture sets, excludes the host's time, so no clone may restore it now: its capture is too old, or the host's clock is behind the capture's | -| `template-tombstoned` | `Unavailable` | A tombstone quarantines the template's generation, which takes no new clones, while the clones that lease it keep their leases | -| `sandbox-leased` | `Other` | The sandbox holds a lease of a template's generation, which allows no other lease, and one launch of its clone, until a release ends it once its VM has exited | ## Guest binaries diff --git a/nvx-rs/public-api/linux.txt b/nvx-rs/public-api/linux.txt index 1b2f72310..45ba2cbfb 100644 --- a/nvx-rs/public-api/linux.txt +++ b/nvx-rs/public-api/linux.txt @@ -1,53 +1,8 @@ mod nvx struct nvx::Error -method nvx::Error::code -method nvx::Error::exited method nvx::Error::into_parts -method nvx::Error::io method nvx::Error::kind method nvx::Error::message -method nvx::Error::new -method nvx::Error::not_found -method nvx::Error::other -method nvx::Error::protocol -method nvx::Error::timed_out -method nvx::Error::unavailable -method nvx::Error::unsupported -method nvx::Error::with_source -enum nvx::ErrorCode -const nvx::ErrorCode::ALL -variant nvx::ErrorCode::ArgumentInvalid -variant nvx::ErrorCode::ArgumentMissing -variant nvx::ErrorCode::ArgumentUnrecognized -variant nvx::ErrorCode::ArtifactMissing -variant nvx::ErrorCode::EndpointClosed -variant nvx::ErrorCode::ExecRefused -variant nvx::ErrorCode::Exited -variant nvx::ErrorCode::ForeignFiles -variant nvx::ErrorCode::FormatUnsupported -variant nvx::ErrorCode::Io -variant nvx::ErrorCode::NotFound -variant nvx::ErrorCode::Other -variant nvx::ErrorCode::OutcomeReportExists -variant nvx::ErrorCode::Protocol -variant nvx::ErrorCode::RuntimeMismatch -variant nvx::ErrorCode::SandboxBusy -variant nvx::ErrorCode::SandboxExited -variant nvx::ErrorCode::SandboxLeased -variant nvx::ErrorCode::SandboxNotProvisioned -variant nvx::ErrorCode::SandboxNotRunning -variant nvx::ErrorCode::SandboxProvisioned -variant nvx::ErrorCode::SandboxRunning -variant nvx::ErrorCode::ScratchClaimed -variant nvx::ErrorCode::StillRunning -variant nvx::ErrorCode::TemplateIneligible -variant nvx::ErrorCode::TemplateTombstoned -variant nvx::ErrorCode::TimedOut -variant nvx::ErrorCode::Unavailable -variant nvx::ErrorCode::Unsupported -variant nvx::ErrorCode::VmmIndeterminate -method nvx::ErrorCode::as_str -method nvx::ErrorCode::kind enum nvx::ErrorKind variant nvx::ErrorKind::Exited variant nvx::ErrorKind::Io diff --git a/nvx-rs/public-api/windows.txt b/nvx-rs/public-api/windows.txt index 93a33df47..1b9b6199a 100644 --- a/nvx-rs/public-api/windows.txt +++ b/nvx-rs/public-api/windows.txt @@ -1,53 +1,8 @@ mod nvx struct nvx::Error -method nvx::Error::code -method nvx::Error::exited method nvx::Error::into_parts -method nvx::Error::io method nvx::Error::kind method nvx::Error::message -method nvx::Error::new -method nvx::Error::not_found -method nvx::Error::other -method nvx::Error::protocol -method nvx::Error::timed_out -method nvx::Error::unavailable -method nvx::Error::unsupported -method nvx::Error::with_source -enum nvx::ErrorCode -const nvx::ErrorCode::ALL -variant nvx::ErrorCode::ArgumentInvalid -variant nvx::ErrorCode::ArgumentMissing -variant nvx::ErrorCode::ArgumentUnrecognized -variant nvx::ErrorCode::ArtifactMissing -variant nvx::ErrorCode::EndpointClosed -variant nvx::ErrorCode::ExecRefused -variant nvx::ErrorCode::Exited -variant nvx::ErrorCode::ForeignFiles -variant nvx::ErrorCode::FormatUnsupported -variant nvx::ErrorCode::Io -variant nvx::ErrorCode::NotFound -variant nvx::ErrorCode::Other -variant nvx::ErrorCode::OutcomeReportExists -variant nvx::ErrorCode::Protocol -variant nvx::ErrorCode::RuntimeMismatch -variant nvx::ErrorCode::SandboxBusy -variant nvx::ErrorCode::SandboxExited -variant nvx::ErrorCode::SandboxLeased -variant nvx::ErrorCode::SandboxNotProvisioned -variant nvx::ErrorCode::SandboxNotRunning -variant nvx::ErrorCode::SandboxProvisioned -variant nvx::ErrorCode::SandboxRunning -variant nvx::ErrorCode::ScratchClaimed -variant nvx::ErrorCode::StillRunning -variant nvx::ErrorCode::TemplateIneligible -variant nvx::ErrorCode::TemplateTombstoned -variant nvx::ErrorCode::TimedOut -variant nvx::ErrorCode::Unavailable -variant nvx::ErrorCode::Unsupported -variant nvx::ErrorCode::VmmIndeterminate -method nvx::ErrorCode::as_str -method nvx::ErrorCode::kind enum nvx::ErrorKind variant nvx::ErrorKind::Exited variant nvx::ErrorKind::Io diff --git a/nvx-rs/src/error.rs b/nvx-rs/src/error.rs index a0d5e7500..fa8877dfb 100644 --- a/nvx-rs/src/error.rs +++ b/nvx-rs/src/error.rs @@ -5,7 +5,7 @@ use std::fmt; /// Result type of NVX operations. pub type Result = std::result::Result; -/// Classification of an [`Error`], which its [`ErrorCode`] determines. +/// Classification of an [`Error`]. #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] #[non_exhaustive] pub enum ErrorKind { @@ -63,7 +63,9 @@ impl fmt::Display for ErrorKind { } } -/// Stable, machine-readable code of an [`Error`], finer than its [`ErrorKind`]. +/// Stable, machine-readable code of an [`Error`], finer than its [`ErrorKind`], which the `nvx-rs` +/// CLI prints with each error that it reports. Codes are private to the crate: callers of the +/// library tell errors apart by their kinds. /// /// Each code belongs to one kind, which [`kind`](Self::kind) returns. A failure that a caller can /// act on has a code of its own, such as `sandbox-not-running`; any other failure has its kind's @@ -73,14 +75,16 @@ impl fmt::Display for ErrorKind { /// a kind, or the subject of the failure followed by its condition, such as `artifact-missing`. /// Codes are stable: a code keeps its spelling, its kind, and its meaning, and is never reused for /// another failure, so a new failure that a caller can act on gets a new code. Messages are not -/// stable, so callers tell errors apart by their codes, and by stable fragments of their messages, -/// such as the names of options and fields. +/// stable, so the CLI's callers tell errors apart by their codes, and by stable fragments of their +/// messages, such as the names of options and fields. /// -/// The `nvx-rs` CLI prints the code of every error that it reports, including the `argument-*` -/// codes of its usage errors, which no library error has. +/// The CLI's usage errors have the `argument-*` codes, which no library error has. #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] -#[non_exhaustive] -pub enum ErrorCode { +#[cfg_attr( + not(feature = "cli"), + allow(dead_code, reason = "the CLI makes most of the finer codes") +)] +pub(crate) enum ErrorCode { /// `unavailable`: a runtime dependency is missing or unusable, other than as a finer code /// says, such as install metadata, the hypervisor, a release, or a host that NVX does not /// support. @@ -155,55 +159,11 @@ pub enum ErrorCode { ExecRefused, /// `endpoint-closed`: OpenVMM closed the control endpoint, as it does when the VM shuts down. EndpointClosed, - /// `template-ineligible`: the restore window of a template's generation, which the time - /// contract of its capture sets, excludes the host's time, so no clone may restore it now: its - /// capture is too old, or the host's clock is behind the capture's. - TemplateIneligible, - /// `template-tombstoned`: a tombstone quarantines the template's generation, which takes no - /// new clones, while the clones that lease it keep their leases. - TemplateTombstoned, - /// `sandbox-leased`: the sandbox holds a lease of a template's generation, which allows no - /// other lease, and one launch of its clone, until a release ends it once its VM has exited. - SandboxLeased, } impl ErrorCode { - /// Every code of this release. - pub const ALL: &'static [ErrorCode] = &[ - Self::Unavailable, - Self::Unsupported, - Self::Exited, - Self::StillRunning, - Self::Io, - Self::NotFound, - Self::Protocol, - Self::TimedOut, - Self::Other, - Self::ArgumentUnrecognized, - Self::ArgumentMissing, - Self::ArgumentInvalid, - Self::ArtifactMissing, - Self::SandboxNotProvisioned, - Self::SandboxProvisioned, - Self::SandboxNotRunning, - Self::SandboxRunning, - Self::SandboxExited, - Self::SandboxBusy, - Self::RuntimeMismatch, - Self::VmmIndeterminate, - Self::FormatUnsupported, - Self::ForeignFiles, - Self::OutcomeReportExists, - Self::ScratchClaimed, - Self::ExecRefused, - Self::EndpointClosed, - Self::TemplateIneligible, - Self::TemplateTombstoned, - Self::SandboxLeased, - ]; - /// Returns the stable spelling of this code. - pub const fn as_str(self) -> &'static str { + pub(crate) const fn as_str(self) -> &'static str { match self { Self::Unavailable => ErrorKind::Unavailable.as_str(), Self::Unsupported => ErrorKind::Unsupported.as_str(), @@ -232,19 +192,13 @@ impl ErrorCode { Self::ScratchClaimed => "scratch-claimed", Self::ExecRefused => "exec-refused", Self::EndpointClosed => "endpoint-closed", - Self::TemplateIneligible => "template-ineligible", - Self::TemplateTombstoned => "template-tombstoned", - Self::SandboxLeased => "sandbox-leased", } } /// Returns the kind of the errors that have this code. - pub const fn kind(self) -> ErrorKind { + pub(crate) const fn kind(self) -> ErrorKind { match self { - Self::Unavailable - | Self::ArtifactMissing - | Self::TemplateIneligible - | Self::TemplateTombstoned => ErrorKind::Unavailable, + Self::Unavailable | Self::ArtifactMissing => ErrorKind::Unavailable, Self::Unsupported | Self::ArgumentUnrecognized | Self::ArgumentMissing @@ -262,8 +216,7 @@ impl ErrorCode { | Self::SandboxRunning | Self::VmmIndeterminate | Self::ForeignFiles - | Self::OutcomeReportExists - | Self::SandboxLeased => ErrorKind::Other, + | Self::OutcomeReportExists => ErrorKind::Other, } } } @@ -292,14 +245,13 @@ impl From for ErrorCode { } } -/// Error of an NVX operation: its [`ErrorCode`], which determines its [`ErrorKind`], a -/// description, and an optional cause. +/// Error of an NVX operation: its [`ErrorKind`], a description, and an optional cause. /// /// The description is a complete sentence fragment that callers can show as is, so callers map -/// errors onto their own classifications by [`kind`](Self::kind) or [`code`](Self::code) alone. +/// errors onto their own classifications by [`kind`](Self::kind) alone. #[derive(Debug)] pub struct Error { - /// Stable code that callers use when telling the failure apart. + /// Stable code, which determines the error's kind, and which the CLI prints. code: ErrorCode, /// Complete, user-facing description without a trailing period. message: String, @@ -309,7 +261,7 @@ pub struct Error { impl Error { /// Creates an error with the given code, or the code of the given kind, and description. - pub fn new(code: impl Into, message: impl Into) -> Self { + pub(crate) fn new(code: impl Into, message: impl Into) -> Self { Self { code: code.into(), message: message.into(), @@ -318,48 +270,49 @@ impl Error { } /// Creates an [`ErrorKind::Unavailable`] error. - pub fn unavailable(message: impl Into) -> Self { + pub(crate) fn unavailable(message: impl Into) -> Self { Self::new(ErrorKind::Unavailable, message) } /// Creates an [`ErrorKind::Unsupported`] error. - pub fn unsupported(message: impl Into) -> Self { + #[cfg(any(feature = "host", all(feature = "guest", target_os = "linux")))] + pub(crate) fn unsupported(message: impl Into) -> Self { Self::new(ErrorKind::Unsupported, message) } /// Creates an [`ErrorKind::Exited`] error. - pub fn exited(message: impl Into) -> Self { + #[cfg(feature = "host")] + pub(crate) fn exited(message: impl Into) -> Self { Self::new(ErrorKind::Exited, message) } /// Creates an [`ErrorKind::Io`] error. - pub fn io(message: impl Into) -> Self { + #[cfg(any(feature = "host", all(feature = "guest", target_os = "linux")))] + pub(crate) fn io(message: impl Into) -> Self { Self::new(ErrorKind::Io, message) } - /// Creates an [`ErrorKind::NotFound`] error. - pub fn not_found(message: impl Into) -> Self { - Self::new(ErrorKind::NotFound, message) - } - /// Creates an [`ErrorKind::Protocol`] error. - pub fn protocol(message: impl Into) -> Self { + #[cfg(feature = "host")] + pub(crate) fn protocol(message: impl Into) -> Self { Self::new(ErrorKind::Protocol, message) } /// Creates an [`ErrorKind::TimedOut`] error. - pub fn timed_out(message: impl Into) -> Self { + #[cfg(feature = "host")] + pub(crate) fn timed_out(message: impl Into) -> Self { Self::new(ErrorKind::TimedOut, message) } /// Creates an [`ErrorKind::Other`] error. - pub fn other(message: impl Into) -> Self { + #[cfg(feature = "host")] + pub(crate) fn other(message: impl Into) -> Self { Self::new(ErrorKind::Other, message) } /// Attaches an underlying cause to this error. #[must_use] - pub fn with_source( + pub(crate) fn with_source( mut self, source: impl Into>, ) -> Self { @@ -367,13 +320,17 @@ impl Error { self } - /// Returns the classification of this error, which its code determines. + /// Returns the classification of this error. pub fn kind(&self) -> ErrorKind { self.code.kind() } - /// Returns the stable code of this error. - pub fn code(&self) -> ErrorCode { + /// Returns the stable code of this error, which the CLI prints. + #[cfg_attr( + not(feature = "cli"), + allow(dead_code, reason = "the CLI prints the codes") + )] + pub(crate) fn code(&self) -> ErrorCode { self.code } @@ -383,8 +340,7 @@ impl Error { } /// Splits the error into its kind, description, and cause, so that a caller can rebuild it - /// as an error of its own without adding a level to the chain of causes. A caller that keeps - /// the code reads it with [`code`](Self::code) first. + /// as an error of its own without adding a level to the chain of causes. pub fn into_parts( self, ) -> ( diff --git a/nvx-rs/src/error/tests.rs b/nvx-rs/src/error/tests.rs index a893e72b7..adc381133 100644 --- a/nvx-rs/src/error/tests.rs +++ b/nvx-rs/src/error/tests.rs @@ -1,9 +1,40 @@ use super::*; +/// Every code, in the order of the README's table of codes. +const CODES: [ErrorCode; 27] = [ + ErrorCode::Unavailable, + ErrorCode::Unsupported, + ErrorCode::Exited, + ErrorCode::StillRunning, + ErrorCode::Io, + ErrorCode::NotFound, + ErrorCode::Protocol, + ErrorCode::TimedOut, + ErrorCode::Other, + ErrorCode::ArgumentUnrecognized, + ErrorCode::ArgumentMissing, + ErrorCode::ArgumentInvalid, + ErrorCode::ArtifactMissing, + ErrorCode::SandboxNotProvisioned, + ErrorCode::SandboxProvisioned, + ErrorCode::SandboxNotRunning, + ErrorCode::SandboxRunning, + ErrorCode::SandboxExited, + ErrorCode::SandboxBusy, + ErrorCode::RuntimeMismatch, + ErrorCode::VmmIndeterminate, + ErrorCode::FormatUnsupported, + ErrorCode::ForeignFiles, + ErrorCode::OutcomeReportExists, + ErrorCode::ScratchClaimed, + ErrorCode::ExecRefused, + ErrorCode::EndpointClosed, +]; + #[test] fn errors_keep_their_kind_message_and_cause() { let cause = std::io::Error::other("disk full"); - let error = Error::io("cannot write /state/runtime.json").with_source(cause); + let error = Error::new(ErrorKind::Io, "cannot write /state/runtime.json").with_source(cause); assert_eq!(error.kind(), ErrorKind::Io); assert_eq!(error.code(), ErrorCode::Io); assert_eq!(error.to_string(), "cannot write /state/runtime.json"); @@ -39,7 +70,7 @@ fn codes_determine_kinds() { Error::new(ErrorKind::RuntimeMismatch, "elsewhere").code(), ErrorCode::RuntimeMismatch ); - assert_eq!(Error::unsupported("no").code(), ErrorCode::Unsupported); + assert_eq!(Error::unavailable("no").code(), ErrorCode::Unavailable); assert_eq!( ErrorCode::SandboxNotRunning.to_string(), "sandbox-not-running" @@ -69,7 +100,7 @@ fn every_kind_has_a_code_of_its_own_spelling() { #[test] fn codes_are_unique_lowercase_words_joined_by_hyphens() { let mut seen = std::collections::HashSet::new(); - for code in ErrorCode::ALL { + for code in CODES { let spelling = code.as_str(); assert!(seen.insert(spelling), "{spelling} repeats"); assert!( @@ -79,17 +110,17 @@ fn codes_are_unique_lowercase_words_joined_by_hyphens() { "{spelling}" ); // A finer code is never spelled as a kind, whose code it would shadow. - if ErrorCode::from(code.kind()) != *code { + if ErrorCode::from(code.kind()) != code { assert_ne!(spelling, code.kind().as_str()); } } - assert_eq!(seen.len(), ErrorCode::ALL.len()); + assert_eq!(seen.len(), CODES.len()); } #[test] fn the_readme_documents_every_code_with_its_kind() { // The table of the README's "Error codes" section lists each code and its kind, in the - // order of `ErrorCode::ALL`. + // order of `CODES`. let readme = include_str!("../../README.md"); let documented: Vec<(String, String)> = readme .lines() @@ -103,7 +134,7 @@ fn the_readme_documents_every_code_with_its_kind() { Some((code.to_owned(), kind.to_owned())) }) .collect(); - let expected: Vec<(String, String)> = ErrorCode::ALL + let expected: Vec<(String, String)> = CODES .iter() .map(|code| (code.as_str().to_owned(), format!("{:?}", code.kind()))) .collect(); diff --git a/nvx-rs/src/host/cli/mod.rs b/nvx-rs/src/host/cli/mod.rs index 01d9adf3d..301a603b4 100644 --- a/nvx-rs/src/host/cli/mod.rs +++ b/nvx-rs/src/host/cli/mod.rs @@ -31,7 +31,7 @@ //! is `0`. //! //! Errors print `error[CODE]: MESSAGE` to standard error and exit with status 1, as `nvx.py` -//! reports a `ScriptError`, with the stable [`ErrorCode`] of the failure. Usage errors print the +//! reports a `ScriptError`, with the stable `ErrorCode` of the failure. Usage errors print the //! one-line usage of the parser and `PROG: error[CODE]: MESSAGE`, where `PROG` is the parser's //! name, such as `nvx-rs run`, with one of the `argument-*` codes, and exit with status 2, as //! `argparse` does. Help prints the usage and every option of the parser, and exits with status 0. diff --git a/nvx-rs/src/host/snapshot/key.rs b/nvx-rs/src/host/snapshot/key.rs index bfc3d5406..e69402ed0 100644 --- a/nvx-rs/src/host/snapshot/key.rs +++ b/nvx-rs/src/host/snapshot/key.rs @@ -662,9 +662,8 @@ impl SnapshotKey { /// The bytes must be the key's one encoding, of version [`VERSION`](Self::VERSION), with no /// value of another form than a key derived from a manifest has, and no byte left over. /// - /// Fails with [`ErrorCode::FormatUnsupported`](crate::ErrorCode::FormatUnsupported) for a key - /// of another version, and with [`ErrorKind::Io`](crate::ErrorKind::Io) for bytes that are - /// not such a key. + /// Fails with [`ErrorKind::Io`](crate::ErrorKind::Io) for a key of another version, and for + /// bytes that are not such a key. pub fn from_bytes(bytes: &[u8]) -> Result { if bytes.len() > Self::MAX_LEN { return Err(Error::io(format!( diff --git a/nvx-rs/src/host/snapshot/manifest.rs b/nvx-rs/src/host/snapshot/manifest.rs index f8bcf392a..cb75fab9f 100644 --- a/nvx-rs/src/host/snapshot/manifest.rs +++ b/nvx-rs/src/host/snapshot/manifest.rs @@ -670,12 +670,10 @@ impl SnapshotManifest { /// Parses and checks the bytes of a template's manifest. /// - /// Fails with [`ErrorCode::FormatUnsupported`] for a - /// manifest of another version of the snapshot format, saved-state schema, machine ABI, boot - /// layout, or time ABI than this build reads, and with - /// [`ErrorKind::Io`](crate::ErrorKind::Io) for more than [`MAX_MANIFEST_LEN`] bytes, bytes - /// that are not such a manifest, and a manifest that is not a template's, as - /// [`SnapshotManifest`] describes. + /// Fails with [`ErrorKind::Io`](crate::ErrorKind::Io) for a manifest of another version of the + /// snapshot format, saved-state schema, machine ABI, boot layout, or time ABI than this build + /// reads, for more than [`MAX_MANIFEST_LEN`] bytes, bytes that are not such a manifest, and a + /// manifest that is not a template's, as [`SnapshotManifest`] describes. pub fn parse(bytes: &[u8]) -> Result { Self::parse_described(bytes, "the snapshot manifest") } diff --git a/nvx-rs/src/lib.rs b/nvx-rs/src/lib.rs index 468d1a576..645c407ac 100644 --- a/nvx-rs/src/lib.rs +++ b/nvx-rs/src/lib.rs @@ -155,7 +155,9 @@ pub mod testing; #[cfg(test)] mod tests; -pub use error::{Error, ErrorCode, ErrorKind, Result}; +#[cfg(feature = "host")] +pub(crate) use error::ErrorCode; +pub use error::{Error, ErrorKind, Result}; #[cfg(feature = "host")] pub use host::filesystem::guest_path; pub use hypervisor::Hypervisor; diff --git a/nvx-rs/tests/cli/openvmm.rs b/nvx-rs/tests/cli/openvmm.rs index c38db9c97..249f8d283 100644 --- a/nvx-rs/tests/cli/openvmm.rs +++ b/nvx-rs/tests/cli/openvmm.rs @@ -353,7 +353,11 @@ impl Options { /// Projects an old cold-run fixture onto the checked public VM contract, independently of /// the CLI's parser, planner, and private token renderer. Restore and sandbox fixtures stay /// old. - pub(crate) fn cold_run_expected(&self, root: &Root, mode: &str) -> nvx::Result { + pub(crate) fn cold_run_expected( + &self, + root: &Root, + mode: &str, + ) -> Result> { use nvx::activation::{MachineIdMode, View}; use nvx::host::config::{Boot, ConsoleAttachment, NetworkConfig, RootConfig, VmConfig}; use nvx::host::filesystem::Owner; @@ -433,9 +437,10 @@ impl Options { for value in old.values(option) { let path = PathBuf::from(value); if shares.is_empty() || (aggregate && !path.is_absolute()) { - return Err(nvx::Error::unsupported( - "boot share policies need a mapped path and absolute aggregate paths", - )); + return Err( + "boot share policies need a mapped path and absolute aggregate paths" + .into(), + ); } policies[index].push(if path.is_absolute() { path @@ -482,9 +487,7 @@ impl Options { .into_iter() .any(|option| !old.values(option).is_empty()) { - return Err(nvx::Error::unsupported( - "network policy options require --net", - )); + return Err("network policy options require --net".into()); } let network = if let Some(net) = old.values("--net").first() { let access = |option, default| match old.values(option).first().map(String::as_str) { diff --git a/scripts/test_nvx_tools.py b/scripts/test_nvx_tools.py index 581add13a..3b054e637 100644 --- a/scripts/test_nvx_tools.py +++ b/scripts/test_nvx_tools.py @@ -2354,7 +2354,7 @@ def test_reported_errors_are_the_last_that_nvx_rs_printed(self): self.assertIsNone(nvx_rs.reported_error(stderr)) def test_usage_documents_every_error_code_of_nvx_rs(self): - # nvx-rs/README.md lists every code of nvx::ErrorCode, which a test of + # nvx-rs/README.md lists every code that nvx-rs prints, which a test of # nvx-rs checks, and doc/usage.md lists the same codes with the status # with which nvx-rs exits: 2 for usage errors and 1 for any other. def table(path: Path) -> list[tuple[str, str]]: