1pub mod disk_image;
10mod linux_direct_serial_agent;
11#[expect(missing_docs)]
14pub mod openhcl_diag;
15pub mod requirements;
16mod test;
17mod tracing;
18mod vm;
19mod worker;
20
21pub use petri_artifacts_core::ArtifactHandle;
22pub use petri_artifacts_core::ArtifactResolver;
23pub use petri_artifacts_core::AsArtifactHandle;
24pub use petri_artifacts_core::ErasedArtifactHandle;
25pub use petri_artifacts_core::ResolveTestArtifact;
26pub use petri_artifacts_core::ResolvedArtifact;
27pub use petri_artifacts_core::ResolvedOptionalArtifact;
28pub use petri_artifacts_core::TestArtifactRequirements;
29pub use petri_artifacts_core::TestArtifacts;
30pub use pipette_client as pipette;
31pub use test::PetriTestParams;
32pub use test::RunTest;
33pub use test::SimpleTest;
34pub use test::TestCase;
35pub use test::test_macro_support;
36pub use test::test_main;
37pub use tracing::*;
38pub use vm::*;
39
40use jiff::Timestamp;
41use std::process::Command;
42use std::process::Stdio;
43use thiserror::Error;
44
45pub const SIZE_1_KB: u64 = 1024;
47pub const SIZE_1_MB: u64 = 1024 * SIZE_1_KB;
49pub const SIZE_1_GB: u64 = 1024 * SIZE_1_MB;
51
52#[expect(missing_docs)] pub enum ShutdownKind {
55 Shutdown,
56 Reboot,
57 }
59
60#[derive(Error, Debug)]
62pub enum CommandError {
63 #[error("failed to launch command")]
65 Launch(#[from] std::io::Error),
66 #[error("command exited with non-zero status ({0}): {1}")]
68 Command(std::process::ExitStatus, String),
69 #[error("command output is not utf-8")]
71 Utf8(#[from] std::string::FromUtf8Error),
72}
73
74pub async fn run_host_cmd(mut cmd: Command) -> Result<String, CommandError> {
76 cmd.stderr(Stdio::piped()).stdin(Stdio::null());
77
78 let cmd_debug = format!("{cmd:?}");
79 ::tracing::debug!(cmd = cmd_debug, "executing command");
80
81 let start = Timestamp::now();
82 let output = blocking::unblock(move || cmd.output()).await?;
83 let time_elapsed = Timestamp::now() - start;
84
85 let stdout_str = String::from_utf8_lossy(&output.stdout).to_string();
86 let stderr_str = String::from_utf8_lossy(&output.stderr).to_string();
87 ::tracing::debug!(
88 cmd = cmd_debug,
89 stdout_str,
90 stderr_str,
91 "command exited in {:.3}s with status {}",
92 time_elapsed.total(jiff::Unit::Second).unwrap(),
93 output.status
94 );
95
96 if !output.status.success() {
97 return Err(CommandError::Command(output.status, stderr_str));
98 }
99
100 Ok(String::from_utf8(output.stdout)?.trim().to_owned())
101}