mirror of
https://github.com/google/alioth.git
synced 2024-10-23 23:09:57 +00:00
feat(cli): track error sources with snafu (2/n)
Signed-off-by: Changyuan Lyu <changyuanl@google.com>
This commit is contained in:
parent
089a7a2e67
commit
f10a1367e2
3 changed files with 82 additions and 33 deletions
9
Cargo.lock
generated
9
Cargo.lock
generated
|
@ -35,12 +35,13 @@ name = "alioth-cli"
|
|||
version = "0.2.0"
|
||||
dependencies = [
|
||||
"alioth",
|
||||
"anyhow",
|
||||
"alioth-macros",
|
||||
"clap",
|
||||
"flexi_logger",
|
||||
"log",
|
||||
"serde",
|
||||
"serde-aco",
|
||||
"snafu",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -114,12 +115,6 @@ dependencies = [
|
|||
"windows-sys 0.52.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "anyhow"
|
||||
version = "1.0.82"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f538837af36e6f6a9be0faa67f9a314f8119e4e4b5867c6ab40ed60360142519"
|
||||
|
||||
[[package]]
|
||||
name = "assert_matches"
|
||||
version = "1.5.0"
|
||||
|
|
|
@ -11,10 +11,11 @@ license.workspace = true
|
|||
log = "0.4"
|
||||
flexi_logger = "0.28"
|
||||
clap = { version = "4", features = ["derive"] }
|
||||
anyhow = "1"
|
||||
snafu.workspace = true
|
||||
alioth = { version = "0.2.0", path = "../alioth" }
|
||||
serde.workspace = true
|
||||
serde-aco = { version = "0.2.0", path = "../serde-aco" }
|
||||
macros = { version = "0.2.0", path = "../macros", package = "alioth-macros" }
|
||||
|
||||
[[bin]]
|
||||
path = "src/main.rs"
|
||||
|
|
|
@ -25,10 +25,11 @@ use alioth::virtio::dev::fs::VuFsParam;
|
|||
use alioth::virtio::dev::net::NetParam;
|
||||
use alioth::virtio::dev::vsock::VhostVsockParam;
|
||||
use alioth::vm::Machine;
|
||||
use anyhow::Result;
|
||||
use clap::{Args, Parser, Subcommand};
|
||||
use flexi_logger::{FileSpec, Logger};
|
||||
use macros::trace_error;
|
||||
use serde::Deserialize;
|
||||
use snafu::{ResultExt, Snafu};
|
||||
|
||||
#[derive(Parser, Debug)]
|
||||
#[command(author, version, about)]
|
||||
|
@ -130,73 +131,125 @@ struct RunArgs {
|
|||
vsock: Option<String>,
|
||||
}
|
||||
|
||||
fn main_run(args: RunArgs) -> Result<()> {
|
||||
#[trace_error]
|
||||
#[derive(Snafu)]
|
||||
#[snafu(module, context(suffix(false)))]
|
||||
pub enum Error {
|
||||
#[snafu(display("Failed to parse {arg}"))]
|
||||
ParseArg {
|
||||
arg: String,
|
||||
error: serde_aco::Error,
|
||||
},
|
||||
#[snafu(display("Failed to access system hypervisor"))]
|
||||
Hypervisor { source: alioth::hv::Error },
|
||||
#[snafu(display("Failed to create a VM"))]
|
||||
CreateVm { error: alioth::vm::Error },
|
||||
#[snafu(display("Failed to create a device"))]
|
||||
CreateDevice { error: alioth::vm::Error },
|
||||
#[snafu(display("Failed to open {path:?}"))]
|
||||
OpenFile {
|
||||
path: PathBuf,
|
||||
error: std::io::Error,
|
||||
},
|
||||
#[snafu(display("Failed to configure the fw-cfg device"))]
|
||||
FwCfg { error: std::io::Error },
|
||||
#[snafu(display("{s} is not a valid CString"))]
|
||||
CreateCString { s: String },
|
||||
#[snafu(display("Failed to boot a VM"))]
|
||||
BootVm { error: alioth::vm::Error },
|
||||
#[snafu(display("VM did not shutdown peacefully"))]
|
||||
WaitVm { error: alioth::vm::Error },
|
||||
}
|
||||
|
||||
fn main_run(args: RunArgs) -> Result<(), Error> {
|
||||
let hv_config = if let Some(hv_cfg_opt) = args.hypervisor {
|
||||
serde_aco::from_arg(&hv_cfg_opt)?
|
||||
serde_aco::from_arg(&hv_cfg_opt).context(error::ParseArg { arg: hv_cfg_opt })?
|
||||
} else {
|
||||
Hypervisor::default()
|
||||
};
|
||||
let hypervisor = match hv_config {
|
||||
Hypervisor::Kvm(kvm_config) => Kvm::new(kvm_config),
|
||||
Hypervisor::Kvm(kvm_config) => Kvm::new(kvm_config).context(error::Hypervisor),
|
||||
}?;
|
||||
let coco = match args.coco {
|
||||
None => None,
|
||||
Some(c) => Some(serde_aco::from_arg(&c)?),
|
||||
Some(c) => Some(serde_aco::from_arg(&c).context(error::ParseArg { arg: c })?),
|
||||
};
|
||||
let board_config = BoardConfig {
|
||||
mem_size: serde_aco::from_arg(&args.mem_size)?,
|
||||
mem_size: serde_aco::from_arg(&args.mem_size)
|
||||
.context(error::ParseArg { arg: args.mem_size })?,
|
||||
num_cpu: args.num_cpu,
|
||||
coco,
|
||||
};
|
||||
let mut vm = Machine::new(hypervisor, board_config)?;
|
||||
let mut vm = Machine::new(hypervisor, board_config).context(error::CreateVm)?;
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
vm.add_com1()?;
|
||||
vm.add_com1().context(error::CreateDevice)?;
|
||||
|
||||
if args.pvpanic {
|
||||
vm.add_pvpanic()?;
|
||||
vm.add_pvpanic().context(error::CreateDevice)?;
|
||||
}
|
||||
|
||||
if args.firmware.is_some() || !args.fw_cfgs.is_empty() {
|
||||
let params = args
|
||||
.fw_cfgs
|
||||
.iter()
|
||||
.map(|s| serde_aco::from_arg(s))
|
||||
.into_iter()
|
||||
.map(|s| serde_aco::from_arg(&s).context(error::ParseArg { arg: s }))
|
||||
.collect::<Result<Vec<_>, _>>()?;
|
||||
let fw_cfg = vm.add_fw_cfg(params.into_iter())?;
|
||||
let fw_cfg = vm
|
||||
.add_fw_cfg(params.into_iter())
|
||||
.context(error::CreateDevice)?;
|
||||
let mut dev = fw_cfg.lock();
|
||||
if let Some(kernel) = &args.kernel {
|
||||
dev.add_kernel_data(File::open(kernel)?)?
|
||||
dev.add_kernel_data(File::open(kernel).with_context(|_| error::OpenFile {
|
||||
path: kernel.to_owned(),
|
||||
})?)
|
||||
.context(error::FwCfg)?
|
||||
}
|
||||
if let Some(initramfs) = &args.initramfs {
|
||||
dev.add_initramfs_data(File::open(initramfs)?)?;
|
||||
dev.add_initramfs_data(File::open(initramfs).with_context(|_| error::OpenFile {
|
||||
path: initramfs.to_owned(),
|
||||
})?)
|
||||
.context(error::FwCfg)?;
|
||||
}
|
||||
if let Some(cmdline) = &args.cmd_line {
|
||||
let cmdline_c = CString::new(cmdline.as_str())?;
|
||||
let Ok(cmdline_c) = CString::new(cmdline.as_str()) else {
|
||||
return error::CreateCString {
|
||||
s: cmdline.to_owned(),
|
||||
}
|
||||
.fail();
|
||||
};
|
||||
dev.add_kernel_cmdline(cmdline_c);
|
||||
}
|
||||
};
|
||||
|
||||
if args.entropy {
|
||||
vm.add_virtio_dev("virtio-entropy".to_owned(), EntropyParam)?;
|
||||
vm.add_virtio_dev("virtio-entropy".to_owned(), EntropyParam)
|
||||
.context(error::CreateDevice)?;
|
||||
}
|
||||
for (index, net_opt) in args.net.into_iter().enumerate() {
|
||||
let net_param: NetParam = serde_aco::from_arg(&net_opt)?;
|
||||
vm.add_virtio_dev(format!("virtio-net-{index}"), net_param)?;
|
||||
let net_param: NetParam =
|
||||
serde_aco::from_arg(&net_opt).context(error::ParseArg { arg: net_opt })?;
|
||||
vm.add_virtio_dev(format!("virtio-net-{index}"), net_param)
|
||||
.context(error::CreateDevice)?;
|
||||
}
|
||||
for (index, blk) in args.blk.into_iter().enumerate() {
|
||||
let param = BlockParam { path: blk.into() };
|
||||
vm.add_virtio_dev(format!("virtio-blk-{index}"), param)?;
|
||||
vm.add_virtio_dev(format!("virtio-blk-{index}"), param)
|
||||
.context(error::CreateDevice)?;
|
||||
}
|
||||
for (index, fs) in args.fs.into_iter().enumerate() {
|
||||
let param: FsParam = serde_aco::from_arg(&fs)?;
|
||||
let param: FsParam = serde_aco::from_arg(&fs).context(error::ParseArg { arg: fs })?;
|
||||
match param {
|
||||
FsParam::Vu(p) => vm.add_virtio_dev(format!("vu-fs-{index}"), p)?,
|
||||
FsParam::Vu(p) => vm
|
||||
.add_virtio_dev(format!("vu-fs-{index}"), p)
|
||||
.context(error::CreateDevice)?,
|
||||
};
|
||||
}
|
||||
if let Some(vsock) = args.vsock {
|
||||
let param = serde_aco::from_arg(&vsock)?;
|
||||
let param = serde_aco::from_arg(&vsock).context(error::ParseArg { arg: vsock })?;
|
||||
match param {
|
||||
VsockParam::Vhost(p) => vm.add_virtio_dev("vhost-vsock".to_owned(), p)?,
|
||||
VsockParam::Vhost(p) => vm
|
||||
.add_virtio_dev("vhost-vsock".to_owned(), p)
|
||||
.context(error::CreateDevice)?,
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -228,9 +281,9 @@ fn main_run(args: RunArgs) -> Result<()> {
|
|||
vm.add_payload(payload);
|
||||
}
|
||||
|
||||
vm.boot()?;
|
||||
vm.boot().context(error::BootVm)?;
|
||||
for result in vm.wait() {
|
||||
result?;
|
||||
result.context(error::WaitVm)?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue