krata/hypha/bin/controller.rs

148 lines
3.8 KiB
Rust
Raw Normal View History

use env_logger::Env;
use anyhow::{anyhow, Result};
use clap::{Parser, Subcommand};
2024-01-17 22:29:05 +00:00
use hypha::ctl::Controller;
2024-01-18 14:15:42 +00:00
use std::path::PathBuf;
2024-01-17 22:29:05 +00:00
#[derive(Parser, Debug)]
#[command(version, about)]
struct ControllerArgs {
2024-01-18 14:15:42 +00:00
#[arg(short, long, default_value = "auto")]
store: String,
#[command(subcommand)]
command: Commands,
}
#[derive(Subcommand, Debug)]
enum Commands {
2024-01-22 01:21:19 +00:00
List {},
Launch {
2024-01-22 01:21:19 +00:00
#[arg(short, long, default_value = "auto")]
2024-01-21 12:49:31 +00:00
kernel: String,
2024-01-22 01:21:19 +00:00
#[arg(short = 'r', long, default_value = "auto")]
2024-01-21 12:49:31 +00:00
initrd: String,
#[arg(short, long, default_value_t = 1)]
cpus: u32,
#[arg(short, long, default_value_t = 512)]
mem: u64,
2024-01-22 10:15:53 +00:00
#[arg(long)]
config_bundle: Option<String>,
#[arg[short, long]]
env: Option<Vec<String>>,
#[arg()]
image: String,
#[arg(allow_hyphen_values = true, trailing_var_arg = true)]
run: Vec<String>,
},
Destroy {
#[arg()]
container: String,
},
2024-01-21 12:49:31 +00:00
Console {
#[arg()]
container: String,
2024-01-21 12:49:31 +00:00
},
2024-01-17 22:29:05 +00:00
}
fn main() -> Result<()> {
env_logger::Builder::from_env(Env::default().default_filter_or("warn")).init();
2024-01-17 22:29:05 +00:00
let args = ControllerArgs::parse();
2024-01-18 14:15:42 +00:00
let store_path = if args.store == "auto" {
default_store_path().ok_or_else(|| anyhow!("unable to determine default store path"))
2024-01-18 08:02:21 +00:00
} else {
2024-01-18 14:15:42 +00:00
Ok(PathBuf::from(args.store))
2024-01-18 08:02:21 +00:00
}?;
2024-01-18 14:15:42 +00:00
let store_path = store_path
.to_str()
.map(|x| x.to_string())
.ok_or_else(|| anyhow!("unable to convert store path to string"))?;
2024-01-18 14:15:42 +00:00
2024-01-22 01:21:19 +00:00
let mut controller = Controller::new(store_path.clone())?;
match args.command {
2024-01-21 12:49:31 +00:00
Commands::Launch {
kernel,
initrd,
image,
cpus,
mem,
2024-01-22 10:15:53 +00:00
config_bundle,
env,
run,
2024-01-21 12:49:31 +00:00
} => {
2024-01-22 01:21:19 +00:00
let kernel = map_kernel_path(&store_path, kernel);
let initrd = map_initrd_path(&store_path, initrd);
let (uuid, _domid) = controller.launch(
2024-01-22 10:15:53 +00:00
&kernel,
&initrd,
config_bundle.as_deref(),
&image,
cpus,
mem,
env,
if run.is_empty() { None } else { Some(run) },
2024-01-22 10:15:53 +00:00
)?;
println!("launched container: {}", uuid);
}
2024-01-21 12:49:31 +00:00
Commands::Destroy { container } => {
controller.destroy(&container)?;
}
2024-01-21 12:49:31 +00:00
Commands::Console { container } => {
controller.console(&container)?;
2024-01-21 12:49:31 +00:00
}
2024-01-22 01:21:19 +00:00
Commands::List { .. } => {
let containers = controller.list()?;
let mut table = cli_tables::Table::new();
let header = vec!["domain", "uuid", "image"];
table.push_row(&header)?;
for container in containers {
let row = vec![
container.domid.to_string(),
container.uuid.to_string(),
container.image,
];
table.push_row_string(&row)?;
}
2024-01-22 10:15:53 +00:00
if table.num_records() == 1 {
println!("no containers have been launched");
} else {
println!("{}", table.to_string());
}
2024-01-22 01:21:19 +00:00
}
}
2024-01-17 22:29:05 +00:00
Ok(())
}
2024-01-18 08:02:21 +00:00
2024-01-22 01:21:19 +00:00
fn map_kernel_path(store: &str, value: String) -> String {
if value == "auto" {
return format!("{}/default/kernel", store);
}
value
}
fn map_initrd_path(store: &str, value: String) -> String {
if value == "auto" {
return format!("{}/default/initrd", store);
}
value
}
2024-01-18 14:15:42 +00:00
fn default_store_path() -> Option<PathBuf> {
2024-01-18 08:02:21 +00:00
let user_dirs = directories::UserDirs::new()?;
let mut path = user_dirs.home_dir().to_path_buf();
2024-01-18 14:15:42 +00:00
if path == PathBuf::from("/root") {
path.push("/var/lib/hypha")
} else {
path.push(".hypha");
}
Some(path)
2024-01-18 08:02:21 +00:00
}