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
1 change: 1 addition & 0 deletions .gitattributes
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ scripts/setup/tool-versions.conf text eol=lf
.github/workflows/*.lock.yml linguist-generated=true
# Generated from Python by scripts/nvx_rs_fixtures.py.
nvx-rs/src/host/python/unicode.rs linguist-generated=true
nvx-rs/tests/fixtures/cli.json linguist-generated=true
nvx-rs/tests/fixtures/egress-policy.json linguist-generated=true
nvx-rs/tests/fixtures/python.json linguist-generated=true
nvx-rs/tests/fixtures/sandbox.json linguist-generated=true
Expand Down
23 changes: 12 additions & 11 deletions aci_edge_sandboxes/tests/openvmm_fake.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ use std::thread;
use std::time::{Duration, Instant, SystemTime};

use aci_edge_sandboxes::nvx::Hypervisor;
use aci_edge_sandboxes::nvx::host::platform;
use aci_edge_sandboxes::openvmm::OpenVmmConfig;
use aci_edge_sandboxes::{
Access, AciEdgeSandbox, EgressPolicy, ErrorCode, ExecFailure, ExecOutcome, ExecOutput,
Expand Down Expand Up @@ -981,20 +982,20 @@ fn crashed_vms_fall_back_to_provisioned() {
});
let sandbox_id = nvx.provision(&ProvisionRequest::new()).unwrap().sandbox_id;
nvx.start(&sandbox_id).unwrap();
// Wait until the VM is gone, as the backend tells it: an exec that the crash interrupts fails
// as a broken control session instead, with `BackendError`.
let runtime = state_json(&fixture, &sandbox_id, "runtime.json");
let pid = u32::try_from(runtime["pid"].as_u64().unwrap()).unwrap();
let start_time = runtime["startTime"].as_u64().unwrap();
let deadline = Instant::now() + Duration::from_secs(30);
loop {
match nvx.exec(&sandbox_id, &ExecRequest::command_line("echo alive")) {
Err(error) => {
assert_eq!(error.code(), ErrorCode::NotStarted, "{error}");
break;
}
Ok(execution) => {
let _ = execution.wait();
}
}
while platform::process_start_time(pid).unwrap() == Some(start_time) {
assert!(Instant::now() < deadline, "the crash was never observed");
thread::sleep(Duration::from_millis(100));
thread::sleep(Duration::from_millis(50));
}
let error = nvx
.exec(&sandbox_id, &ExecRequest::command_line("echo alive"))
.unwrap_err();
assert_eq!(error.code(), ErrorCode::NotStarted, "{error}");
assert_eq!(
nvx.stop(&sandbox_id).unwrap_err().code(),
ErrorCode::AlreadyStopped
Expand Down
10 changes: 6 additions & 4 deletions doc/project-structure.md
Original file line number Diff line number Diff line change
Expand Up @@ -101,11 +101,11 @@ nvx/
| | |-- protocol/ Control-console codec shared by the host and the guest
| | |-- contract.rs Control-contract versions and release compatibility
| | |-- net/ CIDR parsing and subtraction, and hostname and guest-network forms
| | |-- host/ Artifacts, launch, network and egress-policy lowering, sessions, VM instances, and the sandbox launch profile
| | |-- host/ Artifacts, launch, network and egress-policy lowering, sessions, VM instances, the sandbox launch profile, and the `nvx-rs` CLI (feature `cli`)
| | |-- testing/ Fake OpenVMM (feature `testing`)
| | |-- guest/ Programs that run in Linux guests (feature `guest`)
| | `-- bin/ nvx-fake-openvmm test double and the guest binaries
| |-- tests/ Fake-OpenVMM instance lifecycle and guest-binary tests, and the golden fixtures that Python recorded
| | `-- bin/ nvx-rs CLI, nvx-fake-openvmm test double, and the guest binaries
| |-- tests/ Fake-OpenVMM instance lifecycle, CLI, and guest-binary tests, and the golden fixtures that Python recorded
| |-- build.rs Stages the bundled artifacts (feature `bundled`)
| `-- artifacts.json Release package pinned for the bundled artifacts
|-- openvmm/ OpenVMM Git submodule
Expand Down Expand Up @@ -275,7 +275,9 @@ bundled-release staging, OpenVMM's command line, the lowering of network and
filesystem policies, the compiler of `nvx.py`'s egress policy files, process
and platform primitives for Linux and Windows
hosts, the supervision of VM instances, the sandbox launch profile of
`nvx.py sandbox`, and a fake OpenVMM for tests. Its
`nvx.py sandbox`, the `nvx-rs` command-line interface that ports
`nvx.py sandbox`, egress policy compilation, and artifact lookup, and a fake
OpenVMM for tests. Its
`guest` feature builds the nine static executables that every guest image
installs at `/sbin/nvx-*`. It is a
standalone crate with its own `Cargo.lock`, like `aci_edge_sandboxes`, and
Expand Down
10 changes: 10 additions & 0 deletions nvx-rs/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,9 @@ host = [
bundled = ["host", "dep:sha2"]
# Test doubles: the fake OpenVMM of `testing::fake_openvmm` and its `nvx-fake-openvmm` binary.
testing = ["dep:getrandom", "dep:serde", "dep:serde_json", "dep:nix", "dep:windows-sys"]
# The `nvx-rs` command-line interface of `host::cli` and its `nvx-rs` binary, which `nvx.py`
# runs for the steps that it delegates.
cli = ["host"]
# The serde form of `Hypervisor`. The `host` feature enables it.
serde = ["dep:serde"]
# The programs that run in Linux guests: the `guest` module and the `nvx-*` guest binaries. Build
Expand All @@ -53,6 +56,7 @@ windows-sys = { version = "0.61", optional = true, features = [
"Win32_Foundation",
"Win32_Security",
"Win32_Storage_FileSystem",
"Win32_System_Console",
"Win32_System_IO",
"Win32_System_LibraryLoader",
"Win32_System_Pipes",
Expand Down Expand Up @@ -94,6 +98,12 @@ path = "src/bin/nvx-fake-openvmm.rs"
required-features = ["testing"]
doc = false

[[bin]]
name = "nvx-rs"
path = "src/bin/nvx-rs.rs"
required-features = ["cli"]
doc = false

# The guest binaries. Their unit tests live in the library, so the binaries have no test harness.
[[bin]]
name = "nvx-console-pending"
Expand Down
Loading
Loading