From f69ce9605429ffe5579987d98796bdcabb9e06e0 Mon Sep 17 00:00:00 2001 From: Alex Zenla Date: Wed, 17 Jan 2024 12:36:13 -0800 Subject: [PATCH] hypha-agent: command line arguments --- hypha/Cargo.toml | 4 ++ hypha/bin/agent.rs | 20 ++++++++- hypha/src/agent/mod.rs | 55 +++++++++-------------- xenclient/examples/boot.rs | 11 +++-- xenclient/src/create.rs | 92 -------------------------------------- xenclient/src/lib.rs | 26 ++++++----- 6 files changed, 63 insertions(+), 145 deletions(-) delete mode 100644 xenclient/src/create.rs diff --git a/hypha/Cargo.toml b/hypha/Cargo.toml index cfecf75..f83abb2 100644 --- a/hypha/Cargo.toml +++ b/hypha/Cargo.toml @@ -10,6 +10,10 @@ path = "../xenclient" [dependencies] log = "0.4.20" +[dependencies.clap] +version = "4.4.18" +features = ["derive"] + [lib] path = "src/lib.rs" diff --git a/hypha/bin/agent.rs b/hypha/bin/agent.rs index 124b4b7..74365e4 100644 --- a/hypha/bin/agent.rs +++ b/hypha/bin/agent.rs @@ -1,8 +1,26 @@ +use clap::Parser; use hypha::agent::Agent; use hypha::error::Result; +#[derive(Parser, Debug)] +#[command(version, about)] +struct AgentArgs { + #[arg(short, long)] + kernel: String, + + #[arg(short, long)] + initrd: String, + + #[arg(short, long, default_value_t = 1)] + cpus: u32, + + #[arg(short, long, default_value_t = 512)] + mem: u64, +} + fn main() -> Result<()> { - let mut agent = Agent::new()?; + let args = AgentArgs::parse(); + let mut agent = Agent::new(args.kernel, args.initrd, args.cpus, args.mem)?; let domid = agent.launch()?; println!("launched domain: {}", domid); Ok(()) diff --git a/hypha/src/agent/mod.rs b/hypha/src/agent/mod.rs index af36d5f..1ecaf1c 100644 --- a/hypha/src/agent/mod.rs +++ b/hypha/src/agent/mod.rs @@ -1,49 +1,34 @@ -use crate::error::{HyphaError, Result}; -use std::fs::{read_dir, DirEntry}; -use xenclient::create::DomainConfig; -use xenclient::XenClient; +use crate::error::Result; +use xenclient::{DomainConfig, XenClient}; pub struct Agent { client: XenClient, + kernel_path: String, + initrd_path: String, + vcpus: u32, + mem: u64, } impl Agent { - pub fn new() -> Result { + pub fn new(kernel_path: String, initrd_path: String, vcpus: u32, mem: u64) -> Result { let client = XenClient::open()?; - Ok(Agent { client }) + Ok(Agent { + client, + kernel_path, + initrd_path, + vcpus, + mem, + }) } pub fn launch(&mut self) -> Result { - let kernel_path = self.find_boot_path("vmlinuz-")?; - let initrd_path = self.find_boot_path("initrd.img-")?; - let config = DomainConfig { - max_vcpus: 1, - mem_mb: 512, - kernel_path, - initrd_path, - cmdline: "debug elevator=noop".to_string(), + max_vcpus: self.vcpus, + mem_mb: self.mem, + kernel_path: self.kernel_path.as_str(), + initrd_path: self.initrd_path.as_str(), + cmdline: "debug elevator=noop", }; - Ok(self.client.create(config)?) - } - - fn find_boot_path(&self, prefix: &str) -> Result { - let vmlinuz = read_dir("/boot")? - .filter_map(|x| x.ok()) - .filter(|x| { - x.file_name() - .to_str() - .ok_or(HyphaError::new("invalid direntry")) - .map(|x| x.starts_with(prefix)) - .unwrap_or(false) - }) - .collect::>(); - Ok(vmlinuz - .first() - .ok_or(HyphaError::new("unable to find suitable image"))? - .path() - .to_str() - .ok_or(HyphaError::new("invalid direntry"))? - .to_string()) + Ok(self.client.create(&config)?) } } diff --git a/xenclient/examples/boot.rs b/xenclient/examples/boot.rs index 8e62750..c2092c6 100644 --- a/xenclient/examples/boot.rs +++ b/xenclient/examples/boot.rs @@ -1,6 +1,5 @@ use std::{env, process}; -use xenclient::create::DomainConfig; -use xenclient::{XenClient, XenClientError}; +use xenclient::{DomainConfig, XenClient, XenClientError}; fn main() -> Result<(), XenClientError> { env_logger::init(); @@ -16,11 +15,11 @@ fn main() -> Result<(), XenClientError> { let config = DomainConfig { max_vcpus: 1, mem_mb: 512, - kernel_path: kernel_image_path.to_string(), - initrd_path: initrd_path.to_string(), - cmdline: "debug elevator=noop".to_string(), + kernel_path: kernel_image_path.as_str(), + initrd_path: initrd_path.as_str(), + cmdline: "debug elevator=noop", }; - let domid = client.create(config)?; + let domid = client.create(&config)?; println!("created domain {}", domid); Ok(()) } diff --git a/xenclient/src/create.rs b/xenclient/src/create.rs deleted file mode 100644 index a1aea43..0000000 --- a/xenclient/src/create.rs +++ /dev/null @@ -1,92 +0,0 @@ -use std::collections::HashMap; - -pub struct DomainConfig { - pub max_vcpus: u32, - pub mem_mb: u64, - pub kernel_path: String, - pub initrd_path: String, - pub cmdline: String, -} - -pub struct PvDomainStore { - kernel: String, - ramdisk: Option, - cmdline: Option, -} - -pub struct DomainStore { - vm_entries: HashMap, - domain_entries: HashMap, -} - -impl DomainStore { - pub fn new() -> DomainStore { - DomainStore { - vm_entries: HashMap::new(), - domain_entries: HashMap::new(), - } - } - - pub fn put_vm(&mut self, key: &str, value: String) { - self.vm_entries.insert(key.to_string(), value); - } - - pub fn put_vm_str(&mut self, key: &str, value: &str) { - self.put_vm(key, value.to_string()); - } - - pub fn put_domain(&mut self, key: &str, value: String) { - self.vm_entries.insert(key.to_string(), value); - } - - pub fn put_domain_str(&mut self, key: &str, value: &str) { - self.put_domain(key, value.to_string()); - } - - pub fn configure_memory(&mut self, maxkb: u32, targetkb: u32, videokb: u32) { - self.put_domain("memory/static-max", maxkb.to_string()); - self.put_domain("memory/target", targetkb.to_string()); - self.put_domain("memory/videoram", videokb.to_string()); - } - - pub fn configure_cpus(&mut self, _maxvcpus: u32) {} - - pub fn configure_pv(&mut self, pv: PvDomainStore) { - self.put_vm_str("image/ostype", "linux"); - self.put_vm("image/kernel", pv.kernel); - - match pv.ramdisk { - None => {} - Some(ramdisk) => self.put_vm("image/ramdisk", ramdisk), - } - - match pv.cmdline { - None => {} - Some(cmdline) => self.put_vm("image/cmdline", cmdline), - } - } - - pub fn clone_vm_entries(&self) -> HashMap { - self.vm_entries.clone() - } - - pub fn clone_domain_entries(&self) -> HashMap { - self.domain_entries.clone() - } -} - -impl Default for DomainStore { - fn default() -> Self { - DomainStore::new() - } -} - -impl PvDomainStore { - pub fn new(kernel: String, ramdisk: Option, cmdline: Option) -> PvDomainStore { - PvDomainStore { - kernel, - ramdisk, - cmdline, - } - } -} diff --git a/xenclient/src/lib.rs b/xenclient/src/lib.rs index ae2db62..9db75b7 100644 --- a/xenclient/src/lib.rs +++ b/xenclient/src/lib.rs @@ -1,12 +1,10 @@ pub mod boot; -pub mod create; pub mod elfloader; pub mod mem; pub mod sys; mod x86; use crate::boot::BootSetup; -use crate::create::DomainConfig; use crate::elfloader::ElfImageLoader; use crate::x86::X86BootSetup; use std::error::Error; @@ -80,6 +78,14 @@ impl From for XenClientError { } } +pub struct DomainConfig<'a> { + pub max_vcpus: u32, + pub mem_mb: u64, + pub kernel_path: &'a str, + pub initrd_path: &'a str, + pub cmdline: &'a str, +} + impl XenClient { pub fn open() -> Result { let store = XsdClient::open()?; @@ -87,7 +93,7 @@ impl XenClient { Ok(XenClient { store, call }) } - pub fn create(&mut self, config: DomainConfig) -> Result { + pub fn create(&mut self, config: &DomainConfig) -> Result { let domain = CreateDomain { max_vcpus: config.max_vcpus, ..Default::default() @@ -99,9 +105,7 @@ impl XenClient { let libxl_path = format!("/libxl/{}", domid); let ro_perm = XsPermissions { id: 0, perms: 0 }; - let rw_perm = XsPermissions { id: 0, perms: 0 }; - let no_perm = XsPermissions { id: 0, perms: 0 }; { @@ -156,7 +160,7 @@ impl XenClient { self.call.set_max_vcpus(domid, config.max_vcpus)?; self.call.set_max_mem(domid, config.mem_mb * 1024)?; - let image_loader = ElfImageLoader::load_file_kernel(config.kernel_path.as_str())?; + let image_loader = ElfImageLoader::load_file_kernel(config.kernel_path)?; let console_evtchn: u32; let xenstore_evtchn: u32; @@ -166,7 +170,7 @@ impl XenClient { { let mut boot = BootSetup::new(&self.call, domid); let mut arch = X86BootSetup::new(); - let initrd = read(config.initrd_path.as_str())?; + let initrd = read(config.initrd_path)?; let mut state = boot.initialize( &mut arch, &image_loader, @@ -174,7 +178,7 @@ impl XenClient { config.max_vcpus, config.mem_mb, )?; - boot.boot(&mut arch, &mut state, config.cmdline.as_str())?; + boot.boot(&mut arch, &mut state, config.cmdline)?; console_evtchn = state.console_evtchn; xenstore_evtchn = state.store_evtchn; console_mfn = boot.phys.p2m[state.console_segment.pfn as usize]; @@ -186,15 +190,15 @@ impl XenClient { tx.write_string(format!("{}/image/os_type", vm_path).as_str(), "linux")?; tx.write_string( format!("{}/image/kernel", vm_path).as_str(), - &config.kernel_path, + config.kernel_path, )?; tx.write_string( format!("{}/image/ramdisk", vm_path).as_str(), - &config.initrd_path, + config.initrd_path, )?; tx.write_string( format!("{}/image/cmdline", vm_path).as_str(), - &config.cmdline, + config.cmdline, )?; tx.write_string(