Prepare, configure, and manage Firecracker microVMs in seconds!
virtualization
linux
microvm
firecracker
1use anyhow::{anyhow, Context, Result};
2use std::process::{Command, Output, Stdio};
3
4pub fn has_sudo() -> bool {
5 Command::new("sudo")
6 .arg("-h")
7 .output()
8 .map(|output| output.status.success())
9 .unwrap_or(false)
10}
11
12pub fn is_root() -> bool {
13 unsafe { libc::getuid() == 0 }
14}
15
16pub fn run_command(command: &str, args: &[&str], use_sudo: bool) -> Result<Output> {
17 let mut cmd = if use_sudo {
18 if !has_sudo() && !is_root() {
19 return Err(anyhow!(
20 "sudo is required for command '{}', but not available",
21 command
22 ));
23 }
24 let mut c = Command::new("sudo");
25 c.arg(command);
26
27 match is_root() {
28 true => Command::new(command),
29 false => c,
30 }
31 } else {
32 Command::new(command)
33 };
34
35 let output = cmd
36 .args(args)
37 .stdin(Stdio::inherit())
38 .stderr(Stdio::piped())
39 .output()
40 .with_context(|| format!("Failed to execute {}", command))?;
41
42 if !output.status.success() {
43 let stderr = String::from_utf8_lossy(&output.stderr);
44 let stdout = String::from_utf8_lossy(&output.stdout);
45 return Err(anyhow!(
46 "Command {} failed: {} {} {} {}",
47 command,
48 stderr,
49 stdout,
50 args.iter()
51 .map(|s| s.to_string())
52 .collect::<Vec<_>>()
53 .join(" "),
54 output.status.code().unwrap_or(-1),
55 ));
56 }
57 Ok(output)
58}