diff --git a/Cargo.lock b/Cargo.lock index 97c46fe63..ac877789d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -177,6 +177,7 @@ version = "29.0.0" dependencies = [ "anyhow", "api_client", + "argh", "clap", "dirs", "epoll", diff --git a/Cargo.toml b/Cargo.toml index ddbcc0cba..86775d841 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -26,6 +26,7 @@ strip = true [dependencies] anyhow = "1.0.68" api_client = { path = "api_client" } +argh = "0.1.9" clap = { version = "4.0.32", features = ["wrap_help","cargo","string"] } epoll = "4.3.1" event_monitor = { path = "event_monitor" } diff --git a/src/bin/ch-remote.rs b/src/bin/ch-remote.rs index ec709d8b6..e39ff4710 100644 --- a/src/bin/ch-remote.rs +++ b/src/bin/ch-remote.rs @@ -7,7 +7,7 @@ use api_client::simple_api_command; use api_client::simple_api_command_with_fds; use api_client::simple_api_full_command; use api_client::Error as ApiClientError; -use clap::{Arg, ArgAction, ArgMatches, Command}; +use argh::FromArgs; use option_parser::{ByteSized, ByteSizedParseError}; use std::fmt; use std::io::Read; @@ -18,7 +18,6 @@ use std::process; enum Error { Connect(std::io::Error), ApiClient(ApiClientError), - InvalidCpuCount(std::num::ParseIntError), InvalidMemorySize(ByteSizedParseError), InvalidBalloonSize(ByteSizedParseError), AddDeviceConfig(vmm::config::Error), @@ -40,7 +39,6 @@ impl fmt::Display for Error { match self { ApiClient(e) => e.fmt(f), Connect(e) => write!(f, "Error opening HTTP socket: {e}"), - InvalidCpuCount(e) => write!(f, "Error parsing CPU count: {e}"), InvalidMemorySize(e) => write!(f, "Error parsing memory size: {e:?}"), InvalidBalloonSize(e) => write!(f, "Error parsing balloon size: {e:?}"), AddDeviceConfig(e) => write!(f, "Error parsing device syntax: {e}"), @@ -60,16 +58,10 @@ impl fmt::Display for Error { fn resize_api_command( socket: &mut UnixStream, - cpus: Option<&str>, - memory: Option<&str>, - balloon: Option<&str>, + desired_vcpus: Option, + memory: &Option, + balloon: &Option, ) -> Result<(), Error> { - let desired_vcpus: Option = if let Some(cpus) = cpus { - Some(cpus.parse().map_err(Error::InvalidCpuCount)?) - } else { - None - }; - let desired_ram: Option = if let Some(memory) = memory { Some( memory @@ -325,366 +317,387 @@ fn create_api_command(socket: &mut UnixStream, path: &str) -> Result<(), Error> simple_api_command(socket, "PUT", "create", Some(&data)).map_err(Error::ApiClient) } -fn do_command(matches: &ArgMatches) -> Result<(), Error> { - let mut socket = UnixStream::connect(matches.get_one::("api-socket").unwrap()) - .map_err(Error::Connect)?; +fn do_command(toplevel: &TopLevel) -> Result<(), Error> { + let mut socket = + UnixStream::connect(toplevel.api_socket.as_deref().unwrap()).map_err(Error::Connect)?; - match matches.subcommand_name() { - Some("info") => { + match toplevel.command { + SubCommandEnum::Boot(_) => { + simple_api_command(&mut socket, "PUT", "boot", None).map_err(Error::ApiClient) + } + SubCommandEnum::Delete(_) => { + simple_api_command(&mut socket, "PUT", "delete", None).map_err(Error::ApiClient) + } + SubCommandEnum::ShutdownVmm(_) => { + simple_api_command(&mut socket, "PUT", "shutdown-vmm", None).map_err(Error::ApiClient) + } + SubCommandEnum::Resume(_) => { + simple_api_command(&mut socket, "PUT", "resume", None).map_err(Error::ApiClient) + } + SubCommandEnum::PowerButton(_) => { + simple_api_command(&mut socket, "PUT", "power-button", None).map_err(Error::ApiClient) + } + SubCommandEnum::Reboot(_) => { + simple_api_command(&mut socket, "PUT", "reboot", None).map_err(Error::ApiClient) + } + SubCommandEnum::Pause(_) => { + simple_api_command(&mut socket, "PUT", "pause", None).map_err(Error::ApiClient) + } + SubCommandEnum::Info(_) => { simple_api_command(&mut socket, "GET", "info", None).map_err(Error::ApiClient) } - Some("counters") => { + SubCommandEnum::Counters(_) => { simple_api_command(&mut socket, "GET", "counters", None).map_err(Error::ApiClient) } - Some("ping") => { + SubCommandEnum::Ping(_) => { simple_api_full_command(&mut socket, "GET", "vmm.ping", None).map_err(Error::ApiClient) } - Some("shutdown-vmm") => simple_api_full_command(&mut socket, "PUT", "vmm.shutdown", None) - .map_err(Error::ApiClient), - Some("resize") => resize_api_command( + SubCommandEnum::Shutdown(_) => { + simple_api_full_command(&mut socket, "PUT", "vmm.shutdown", None) + .map_err(Error::ApiClient) + } + SubCommandEnum::Resize(ref config) => { + resize_api_command(&mut socket, config.cpus, &config.memory, &config.balloon) + } + SubCommandEnum::ResizeZone(ref config) => { + resize_zone_api_command(&mut socket, &config.id, &config.size) + } + SubCommandEnum::AddDevice(ref config) => { + add_device_api_command(&mut socket, &config.device_config) + } + SubCommandEnum::RemoveDevice(ref config) => { + remove_device_api_command(&mut socket, &config.device_config) + } + SubCommandEnum::AddDisk(ref config) => { + add_disk_api_command(&mut socket, &config.disk_config) + } + SubCommandEnum::AddFs(ref config) => add_fs_api_command(&mut socket, &config.fs_config), + SubCommandEnum::AddPmem(ref config) => { + add_pmem_api_command(&mut socket, &config.pmem_config) + } + SubCommandEnum::AddNet(ref config) => add_net_api_command(&mut socket, &config.net_config), + SubCommandEnum::AddUserDevice(ref config) => { + add_user_device_api_command(&mut socket, &config.device_config) + } + SubCommandEnum::AddVdpa(ref config) => { + add_vdpa_api_command(&mut socket, &config.vdpa_config) + } + SubCommandEnum::AddVsock(ref config) => { + add_vsock_api_command(&mut socket, &config.vsock_config) + } + SubCommandEnum::Snapshot(ref config) => { + snapshot_api_command(&mut socket, &config.snapshot_config) + } + SubCommandEnum::Restore(ref config) => { + restore_api_command(&mut socket, &config.restore_config) + } + SubCommandEnum::Coredump(ref config) => { + coredump_api_command(&mut socket, &config.coredump_config) + } + SubCommandEnum::SendMigration(ref config) => send_migration_api_command( &mut socket, - matches - .subcommand_matches("resize") - .unwrap() - .get_one::("cpus") - .map(|x| x as &str), - matches - .subcommand_matches("resize") - .unwrap() - .get_one::("memory") - .map(|x| x as &str), - matches - .subcommand_matches("resize") - .unwrap() - .get_one::("balloon") - .map(|x| x as &str), + &config.send_migration_config, + config.send_migration_local, ), - Some("resize-zone") => resize_zone_api_command( - &mut socket, - matches - .subcommand_matches("resize-zone") - .unwrap() - .get_one::("id") - .unwrap(), - matches - .subcommand_matches("resize-zone") - .unwrap() - .get_one::("size") - .unwrap(), - ), - Some("add-device") => add_device_api_command( - &mut socket, - matches - .subcommand_matches("add-device") - .unwrap() - .get_one::("device_config") - .unwrap(), - ), - Some("remove-device") => remove_device_api_command( - &mut socket, - matches - .subcommand_matches("remove-device") - .unwrap() - .get_one::("id") - .unwrap(), - ), - Some("add-disk") => add_disk_api_command( - &mut socket, - matches - .subcommand_matches("add-disk") - .unwrap() - .get_one::("disk_config") - .unwrap(), - ), - Some("add-fs") => add_fs_api_command( - &mut socket, - matches - .subcommand_matches("add-fs") - .unwrap() - .get_one::("fs_config") - .unwrap(), - ), - Some("add-pmem") => add_pmem_api_command( - &mut socket, - matches - .subcommand_matches("add-pmem") - .unwrap() - .get_one::("pmem_config") - .unwrap(), - ), - Some("add-net") => add_net_api_command( - &mut socket, - matches - .subcommand_matches("add-net") - .unwrap() - .get_one::("net_config") - .unwrap(), - ), - Some("add-user-device") => add_user_device_api_command( - &mut socket, - matches - .subcommand_matches("add-user-device") - .unwrap() - .get_one::("device_config") - .unwrap(), - ), - Some("add-vdpa") => add_vdpa_api_command( - &mut socket, - matches - .subcommand_matches("add-vdpa") - .unwrap() - .get_one::("vdpa_config") - .unwrap(), - ), - Some("add-vsock") => add_vsock_api_command( - &mut socket, - matches - .subcommand_matches("add-vsock") - .unwrap() - .get_one::("vsock_config") - .unwrap(), - ), - Some("snapshot") => snapshot_api_command( - &mut socket, - matches - .subcommand_matches("snapshot") - .unwrap() - .get_one::("snapshot_config") - .unwrap(), - ), - Some("restore") => restore_api_command( - &mut socket, - matches - .subcommand_matches("restore") - .unwrap() - .get_one::("restore_config") - .unwrap(), - ), - Some("coredump") => coredump_api_command( - &mut socket, - matches - .subcommand_matches("coredump") - .unwrap() - .get_one::("coredump_config") - .unwrap(), - ), - Some("send-migration") => send_migration_api_command( - &mut socket, - matches - .subcommand_matches("send-migration") - .unwrap() - .get_one::("send_migration_config") - .unwrap(), - matches - .subcommand_matches("send-migration") - .unwrap() - .get_flag("send_migration_local"), - ), - Some("receive-migration") => receive_migration_api_command( - &mut socket, - matches - .subcommand_matches("receive-migration") - .unwrap() - .get_one::("receive_migration_config") - .unwrap(), - ), - Some("create") => create_api_command( - &mut socket, - matches - .subcommand_matches("create") - .unwrap() - .get_one::("path") - .unwrap(), - ), - Some(c) => simple_api_command(&mut socket, "PUT", c, None).map_err(Error::ApiClient), - None => unreachable!(), + SubCommandEnum::ReceiveMigration(ref config) => { + receive_migration_api_command(&mut socket, &config.receive_migration_config) + } + SubCommandEnum::Create(ref config) => create_api_command(&mut socket, &config.vm_config), + SubCommandEnum::Version(_) => { + // Already handled outside of this function + panic!() + } } } +#[derive(FromArgs, PartialEq, Debug)] +#[doc = "Remotely control a cloud-hypervisor VMM.\n\nPlease refer to cloud-hypervisor for configuration syntaxes."] +struct TopLevel { + #[argh(subcommand)] + command: SubCommandEnum, + + #[argh(option, long = "api-socket")] + /// HTTP API socket path (UNIX domain socket) + api_socket: Option, +} + +#[derive(FromArgs, PartialEq, Debug)] +#[argh(subcommand)] +enum SubCommandEnum { + AddDevice(AddDeviceSubcommand), + AddDisk(AddDiskSubcommand), + AddFs(AddFsSubcommand), + AddPmem(AddPmemSubcommand), + AddNet(AddNetSubcommand), + AddUserDevice(AddUserDeviceSubcommand), + AddVdpa(AddVdpaSubcommand), + AddVsock(AddVsockSubcommand), + RemoveDevice(RemoveDeviceSubcommand), + Info(InfoSubcommand), + Counters(CountersSubcommand), + Pause(PauseSubcommand), + Reboot(RebootSubcommand), + PowerButton(PowerButtonSubcommand), + Resume(ResumeSubcommand), + Boot(BootSubcommand), + Delete(DeleteSubcommand), + Shutdown(ShutdownSubcommand), + Ping(PingSubcommand), + ShutdownVmm(ShutdownVmmSubcommand), + Resize(ResizeSubcommand), + ResizeZone(ResizeZoneSubcommand), + Snapshot(SnapshotSubcommand), + Restore(RestoreSubcommand), + Coredump(CoredumpSubcommand), + SendMigration(SendMigrationSubcommand), + ReceiveMigration(ReceiveMigrationSubcommand), + Create(CreateSubcommand), + Version(VersionSubcommand), +} + +#[derive(FromArgs, PartialEq, Debug)] +#[argh(subcommand, name = "add-device")] +/// Add VFIO device +struct AddDeviceSubcommand { + #[argh(positional)] + /// device config + device_config: String, +} + +#[derive(FromArgs, PartialEq, Debug)] +#[argh(subcommand, name = "add-disk")] +/// Add block device +struct AddDiskSubcommand { + #[argh(positional)] + /// disk config + disk_config: String, +} + +#[derive(FromArgs, PartialEq, Debug)] +#[argh(subcommand, name = "add-fs")] +/// Add virtio-fs backed fs device +struct AddFsSubcommand { + #[argh(positional)] + /// virtio-fs config + fs_config: String, +} + +#[derive(FromArgs, PartialEq, Debug)] +#[argh(subcommand, name = "add-pmem")] +/// Add virtio-fs backed fs device +struct AddPmemSubcommand { + #[argh(positional)] + /// pmem config + pmem_config: String, +} + +#[derive(FromArgs, PartialEq, Debug)] +#[argh(subcommand, name = "add-net")] +/// Add virtio-fs backed fs device +struct AddNetSubcommand { + #[argh(positional)] + /// net config + net_config: String, +} + +#[derive(FromArgs, PartialEq, Debug)] +#[argh(subcommand, name = "add-user-device")] +/// Add userspace device +struct AddUserDeviceSubcommand { + #[argh(positional)] + /// device config + device_config: String, +} + +#[derive(FromArgs, PartialEq, Debug)] +#[argh(subcommand, name = "add-vdpa")] +/// Add vdpa device +struct AddVdpaSubcommand { + #[argh(positional)] + /// vdpa config + vdpa_config: String, +} + +#[derive(FromArgs, PartialEq, Debug)] +#[argh(subcommand, name = "add-vsock")] +/// Add vsock device +struct AddVsockSubcommand { + #[argh(positional)] + /// vsock config + vsock_config: String, +} + +#[derive(FromArgs, PartialEq, Debug)] +#[argh(subcommand, name = "remove-device")] +/// Remove VFIO device +struct RemoveDeviceSubcommand { + #[argh(positional)] + /// device config + device_config: String, +} + +#[derive(FromArgs, PartialEq, Debug)] +#[argh(subcommand, name = "info")] +/// Information on the VM +struct InfoSubcommand {} + +#[derive(FromArgs, PartialEq, Debug)] +#[argh(subcommand, name = "counters")] +/// Counters from the VM +struct CountersSubcommand {} + +#[derive(FromArgs, PartialEq, Debug)] +#[argh(subcommand, name = "pause")] +/// Pause the VM +struct PauseSubcommand {} + +#[derive(FromArgs, PartialEq, Debug)] +#[argh(subcommand, name = "reboot")] +/// Reboot the VM +struct RebootSubcommand {} + +#[derive(FromArgs, PartialEq, Debug)] +#[argh(subcommand, name = "power-button")] +/// Trigger a power button in the VM +struct PowerButtonSubcommand {} + +#[derive(FromArgs, PartialEq, Debug)] +#[argh(subcommand, name = "resume")] +/// Resume the VM +struct ResumeSubcommand {} + +#[derive(FromArgs, PartialEq, Debug)] +#[argh(subcommand, name = "boot")] +/// Boot a created VM +struct BootSubcommand {} + +#[derive(FromArgs, PartialEq, Debug)] +#[argh(subcommand, name = "delete")] +/// Delete a VM +struct DeleteSubcommand {} + +#[derive(FromArgs, PartialEq, Debug)] +#[argh(subcommand, name = "shutdown")] +/// Shutdown a VM +struct ShutdownSubcommand {} + +#[derive(FromArgs, PartialEq, Debug)] +#[argh(subcommand, name = "ping")] +/// Ping the VMM to check for API server availability +struct PingSubcommand {} + +#[derive(FromArgs, PartialEq, Debug)] +#[argh(subcommand, name = "shutdown-vmm")] +/// Shutdown the VMM +struct ShutdownVmmSubcommand {} + +#[derive(FromArgs, PartialEq, Debug)] +#[argh(subcommand, name = "resize")] +/// Resize the VM +struct ResizeSubcommand { + #[argh(option, long = "cpus")] + /// new VCPUs count + cpus: Option, + + #[argh(option, long = "memory")] + /// new memory size in bytes (supports K/M/G suffix)" + memory: Option, + + #[argh(option, long = "balloon")] + /// new balloon size in bytes (supports K/M/G suffix)" + balloon: Option, +} + +#[derive(FromArgs, PartialEq, Debug)] +#[argh(subcommand, name = "resize-zone")] +/// Resize a memory zone +struct ResizeZoneSubcommand { + #[argh(option, long = "id")] + /// memory zone identifier + id: String, + + #[argh(option, long = "size")] + /// new memory size in bytes (supports K/M/G suffix)" + size: String, +} + +#[derive(FromArgs, PartialEq, Debug)] +#[argh(subcommand, name = "snapshot")] +/// Create a snapshot from VM +struct SnapshotSubcommand { + #[argh(positional)] + /// destination_url + snapshot_config: String, +} + +#[derive(FromArgs, PartialEq, Debug)] +#[argh(subcommand, name = "restore")] +/// Restore VM from a snapshot +struct RestoreSubcommand { + #[argh(positional)] + /// restore config + restore_config: String, +} + +#[derive(FromArgs, PartialEq, Debug)] +#[argh(subcommand, name = "coredump")] +/// Create a coredump from VM +struct CoredumpSubcommand { + #[argh(positional)] + /// coredump config + coredump_config: String, +} + +#[derive(FromArgs, PartialEq, Debug)] +#[argh(subcommand, name = "send-migration")] +/// Initiate a VM migration +struct SendMigrationSubcommand { + #[argh(switch, long = "local")] + /// local migration + send_migration_local: bool, + + #[argh(positional)] + /// destination_url + send_migration_config: String, +} + +#[derive(FromArgs, PartialEq, Debug)] +#[argh(subcommand, name = "receive-migration")] +/// Receive a VM migration +struct ReceiveMigrationSubcommand { + #[argh(positional)] + /// receiver url + receive_migration_config: String, +} + +#[derive(FromArgs, PartialEq, Debug)] +#[argh(subcommand, name = "create")] +/// Create a VM from a JSON configuration +struct CreateSubcommand { + #[argh(positional, default = "String::from(\"-\")")] + /// vm config + vm_config: String, +} + +#[derive(FromArgs, PartialEq, Debug)] +#[argh(subcommand, name = "version")] +/// Print version information +struct VersionSubcommand {} + fn main() { - let app = Command::new("ch-remote") - .author(env!("CARGO_PKG_AUTHORS")) - .subcommand_required(true) - .about("Remotely control a cloud-hypervisor VMM.") - .arg( - Arg::new("api-socket") - .long("api-socket") - .help("HTTP API socket path (UNIX domain socket).") - .num_args(1) - .required(true), - ) - .subcommand( - Command::new("add-device").about("Add VFIO device").arg( - Arg::new("device_config") - .index(1) - .help(vmm::config::DeviceConfig::SYNTAX), - ), - ) - .subcommand( - Command::new("add-disk").about("Add block device").arg( - Arg::new("disk_config") - .index(1) - .help(vmm::config::DiskConfig::SYNTAX), - ), - ) - .subcommand( - Command::new("add-fs") - .about("Add virtio-fs backed fs device") - .arg( - Arg::new("fs_config") - .index(1) - .help(vmm::config::FsConfig::SYNTAX), - ), - ) - .subcommand( - Command::new("add-pmem") - .about("Add persistent memory device") - .arg( - Arg::new("pmem_config") - .index(1) - .help(vmm::config::PmemConfig::SYNTAX), - ), - ) - .subcommand( - Command::new("add-net").about("Add network device").arg( - Arg::new("net_config") - .index(1) - .help(vmm::config::NetConfig::SYNTAX), - ), - ) - .subcommand( - Command::new("add-user-device") - .about("Add userspace device") - .arg( - Arg::new("device_config") - .index(1) - .help(vmm::config::UserDeviceConfig::SYNTAX), - ), - ) - .subcommand( - Command::new("add-vdpa").about("Add vDPA device").arg( - Arg::new("vdpa_config") - .index(1) - .help(vmm::config::VdpaConfig::SYNTAX), - ), - ) - .subcommand( - Command::new("add-vsock").about("Add vsock device").arg( - Arg::new("vsock_config") - .index(1) - .help(vmm::config::VsockConfig::SYNTAX), - ), - ) - .subcommand( - Command::new("remove-device") - .about("Remove VFIO device") - .arg(Arg::new("id").index(1).help("")), - ) - .subcommand(Command::new("info").about("Info on the VM")) - .subcommand(Command::new("counters").about("Counters from the VM")) - .subcommand(Command::new("pause").about("Pause the VM")) - .subcommand(Command::new("reboot").about("Reboot the VM")) - .subcommand(Command::new("power-button").about("Trigger a power button in the VM")) - .subcommand( - Command::new("resize") - .about("Resize the VM") - .arg( - Arg::new("cpus") - .long("cpus") - .help("New vCPUs count") - .num_args(1), - ) - .arg( - Arg::new("memory") - .long("memory") - .help("New memory size in bytes (supports K/M/G suffix)") - .num_args(1), - ) - .arg( - Arg::new("balloon") - .long("balloon") - .help("New balloon size in bytes (supports K/M/G suffix)") - .num_args(1), - ), - ) - .subcommand( - Command::new("resize-zone") - .about("Resize a memory zone") - .arg( - Arg::new("id") - .long("id") - .help("Memory zone identifier") - .num_args(1), - ) - .arg( - Arg::new("size") - .long("size") - .help("New memory zone size in bytes (supports K/M/G suffix)") - .num_args(1), - ), - ) - .subcommand(Command::new("resume").about("Resume the VM")) - .subcommand(Command::new("boot").about("Boot a created VM")) - .subcommand(Command::new("delete").about("Delete a VM")) - .subcommand(Command::new("shutdown").about("Shutdown the VM")) - .subcommand( - Command::new("snapshot") - .about("Create a snapshot from VM") - .arg( - Arg::new("snapshot_config") - .index(1) - .help(""), - ), - ) - .subcommand( - Command::new("restore") - .about("Restore VM from a snapshot") - .arg( - Arg::new("restore_config") - .index(1) - .help(vmm::config::RestoreConfig::SYNTAX), - ), - ) - .subcommand( - Command::new("coredump") - .about("Create a coredump from VM") - .arg(Arg::new("coredump_config").index(1).help("")), - ) - .subcommand( - Command::new("send-migration") - .about("Initiate a VM migration") - .arg( - Arg::new("send_migration_config") - .index(1) - .help(""), - ) - .arg( - Arg::new("send_migration_local") - .long("local") - .num_args(0) - .action(ArgAction::SetTrue), - ), - ) - .subcommand( - Command::new("receive-migration") - .about("Receive a VM migration") - .arg( - Arg::new("receive_migration_config") - .index(1) - .help(""), - ), - ) - .subcommand( - Command::new("create") - .about("Create VM from a JSON configuration") - .arg(Arg::new("path").index(1).default_value("-")), - ) - .subcommand(Command::new("ping").about("Ping the VMM to check for API server availability")) - .subcommand(Command::new("shutdown-vmm").about("Shutdown the VMM")); + let toplevel: TopLevel = argh::from_env(); - let matches = app.get_matches(); + if matches!(toplevel.command, SubCommandEnum::Version(_)) { + println!("{} {}", env!("CARGO_BIN_NAME"), env!("BUILT_VERSION")); + return; + } - if let Err(e) = do_command(&matches) { + if toplevel.api_socket.is_none() { + println!("Please specify --api-socket"); + process::exit(1) + } + + if let Err(e) = do_command(&toplevel) { eprintln!("Error running command: {e}"); process::exit(1) }; diff --git a/tests/integration.rs b/tests/integration.rs index 674c92ea5..9c8789b9b 100644 --- a/tests/integration.rs +++ b/tests/integration.rs @@ -246,7 +246,7 @@ fn curl_command(api_socket: &str, method: &str, url: &str, http_body: Option<&st fn remote_command(api_socket: &str, command: &str, arg: Option<&str>) -> bool { let mut cmd = Command::new(clh_command("ch-remote")); - cmd.args([&format!("--api-socket={api_socket}"), command]); + cmd.args(["--api-socket", api_socket, command]); if let Some(arg) = arg { cmd.arg(arg); @@ -264,7 +264,7 @@ fn remote_command(api_socket: &str, command: &str, arg: Option<&str>) -> bool { fn remote_command_w_output(api_socket: &str, command: &str, arg: Option<&str>) -> (bool, Vec) { let mut cmd = Command::new(clh_command("ch-remote")); - cmd.args([&format!("--api-socket={api_socket}"), command]); + cmd.args(["--api-socket", api_socket, command]); if let Some(arg) = arg { cmd.arg(arg); @@ -283,18 +283,18 @@ fn resize_command( event_file: Option<&str>, ) -> bool { let mut cmd = Command::new(clh_command("ch-remote")); - cmd.args([&format!("--api-socket={api_socket}"), "resize"]); + cmd.args(["--api-socket", api_socket, "resize"]); if let Some(desired_vcpus) = desired_vcpus { - cmd.arg(format!("--cpus={desired_vcpus}")); + cmd.args(["--cpus", &format!("{desired_vcpus}")]); } if let Some(desired_ram) = desired_ram { - cmd.arg(format!("--memory={desired_ram}")); + cmd.args(["--memory", &format!("{desired_ram}")]); } if let Some(desired_balloon) = desired_balloon { - cmd.arg(format!("--balloon={desired_balloon}")); + cmd.args(["--balloon", &format!("{desired_balloon}")]); } let ret = cmd.status().expect("Failed to launch ch-remote").success(); @@ -319,10 +319,13 @@ fn resize_command( fn resize_zone_command(api_socket: &str, id: &str, desired_size: &str) -> bool { let mut cmd = Command::new(clh_command("ch-remote")); cmd.args([ - &format!("--api-socket={api_socket}"), + "--api-socket", + api_socket, "resize-zone", - &format!("--id={id}"), - &format!("--size={desired_size}"), + "--id", + id, + "--size", + desired_size, ]); cmd.status().expect("Failed to launch ch-remote").success() @@ -3861,7 +3864,7 @@ mod common_parallel { let vfio_hotplug_output = guest .ssh_command_l1( "sudo /mnt/ch-remote \ - --api-socket=/tmp/ch_api.sock \ + --api-socket /tmp/ch_api.sock \ add-device path=/sys/bus/pci/devices/0000:00:09.0,id=vfio123", ) .unwrap(); @@ -3901,7 +3904,7 @@ mod common_parallel { guest .ssh_command_l1( "sudo /mnt/ch-remote \ - --api-socket=/tmp/ch_api.sock \ + --api-socket /tmp/ch_api.sock \ remove-device vfio123", ) .unwrap(); @@ -3932,7 +3935,7 @@ mod common_parallel { guest .ssh_command_l1( "sudo /mnt/ch-remote \ - --api-socket=/tmp/ch_api.sock \ + --api-socket /tmp/ch_api.sock \ resize --memory=1073741824", ) .unwrap(); @@ -7927,7 +7930,7 @@ mod vfio { let vfio_hotplug_output = guest .ssh_command_l1( "sudo /mnt/ch-remote \ - --api-socket=/tmp/ch_api.sock \ + --api-socket /tmp/ch_api.sock \ add-device path=/sys/bus/pci/devices/0000:00:09.0,id=vfio123", ) .unwrap(); @@ -7967,7 +7970,7 @@ mod vfio { guest .ssh_command_l1( "sudo /mnt/ch-remote \ - --api-socket=/tmp/ch_api.sock \ + --api-socket /tmp/ch_api.sock \ remove-device vfio123", ) .unwrap(); @@ -7998,7 +8001,7 @@ mod vfio { guest .ssh_command_l1( "sudo /mnt/ch-remote \ - --api-socket=/tmp/ch_api.sock \ + --api-socket /tmp/ch_api.sock \ resize --memory=1073741824", ) .unwrap(); @@ -8157,7 +8160,8 @@ mod live_migration { // Start to receive migration from the destintion VM let mut receive_migration = Command::new(clh_command("ch-remote")) .args([ - &format!("--api-socket={dest_api_socket}"), + "--api-socket", + dest_api_socket, "receive-migration", &format! {"unix:{migration_socket}"}, ]) @@ -8170,14 +8174,15 @@ mod live_migration { // Start to send migration from the source VM let mut args = [ - format!("--api-socket={}", &src_api_socket), + "--api-socket".to_string(), + src_api_socket.to_string(), "send-migration".to_string(), format! {"unix:{migration_socket}"}, ] .to_vec(); if local { - args.insert(2, "--local".to_string()); + args.insert(3, "--local".to_string()); } let mut send_migration = Command::new(clh_command("ch-remote"))