mirror of
https://github.com/cloud-hypervisor/cloud-hypervisor.git
synced 2024-12-22 05:35:20 +00:00
ch-remote: switch to argh
Since argh does not support `--option=value`, we need to change the integration test code to become `--option value`. Signed-off-by: Wei Liu <liuwe@microsoft.com>
This commit is contained in:
parent
1ba995d952
commit
d5558aea2a
1
Cargo.lock
generated
1
Cargo.lock
generated
@ -177,6 +177,7 @@ version = "29.0.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"api_client",
|
||||
"argh",
|
||||
"clap",
|
||||
"dirs",
|
||||
"epoll",
|
||||
|
@ -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" }
|
||||
|
@ -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<u8>,
|
||||
memory: &Option<String>,
|
||||
balloon: &Option<String>,
|
||||
) -> Result<(), Error> {
|
||||
let desired_vcpus: Option<u8> = if let Some(cpus) = cpus {
|
||||
Some(cpus.parse().map_err(Error::InvalidCpuCount)?)
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
let desired_ram: Option<u64> = 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::<String>("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::<String>("cpus")
|
||||
.map(|x| x as &str),
|
||||
matches
|
||||
.subcommand_matches("resize")
|
||||
.unwrap()
|
||||
.get_one::<String>("memory")
|
||||
.map(|x| x as &str),
|
||||
matches
|
||||
.subcommand_matches("resize")
|
||||
.unwrap()
|
||||
.get_one::<String>("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::<String>("id")
|
||||
.unwrap(),
|
||||
matches
|
||||
.subcommand_matches("resize-zone")
|
||||
.unwrap()
|
||||
.get_one::<String>("size")
|
||||
.unwrap(),
|
||||
),
|
||||
Some("add-device") => add_device_api_command(
|
||||
&mut socket,
|
||||
matches
|
||||
.subcommand_matches("add-device")
|
||||
.unwrap()
|
||||
.get_one::<String>("device_config")
|
||||
.unwrap(),
|
||||
),
|
||||
Some("remove-device") => remove_device_api_command(
|
||||
&mut socket,
|
||||
matches
|
||||
.subcommand_matches("remove-device")
|
||||
.unwrap()
|
||||
.get_one::<String>("id")
|
||||
.unwrap(),
|
||||
),
|
||||
Some("add-disk") => add_disk_api_command(
|
||||
&mut socket,
|
||||
matches
|
||||
.subcommand_matches("add-disk")
|
||||
.unwrap()
|
||||
.get_one::<String>("disk_config")
|
||||
.unwrap(),
|
||||
),
|
||||
Some("add-fs") => add_fs_api_command(
|
||||
&mut socket,
|
||||
matches
|
||||
.subcommand_matches("add-fs")
|
||||
.unwrap()
|
||||
.get_one::<String>("fs_config")
|
||||
.unwrap(),
|
||||
),
|
||||
Some("add-pmem") => add_pmem_api_command(
|
||||
&mut socket,
|
||||
matches
|
||||
.subcommand_matches("add-pmem")
|
||||
.unwrap()
|
||||
.get_one::<String>("pmem_config")
|
||||
.unwrap(),
|
||||
),
|
||||
Some("add-net") => add_net_api_command(
|
||||
&mut socket,
|
||||
matches
|
||||
.subcommand_matches("add-net")
|
||||
.unwrap()
|
||||
.get_one::<String>("net_config")
|
||||
.unwrap(),
|
||||
),
|
||||
Some("add-user-device") => add_user_device_api_command(
|
||||
&mut socket,
|
||||
matches
|
||||
.subcommand_matches("add-user-device")
|
||||
.unwrap()
|
||||
.get_one::<String>("device_config")
|
||||
.unwrap(),
|
||||
),
|
||||
Some("add-vdpa") => add_vdpa_api_command(
|
||||
&mut socket,
|
||||
matches
|
||||
.subcommand_matches("add-vdpa")
|
||||
.unwrap()
|
||||
.get_one::<String>("vdpa_config")
|
||||
.unwrap(),
|
||||
),
|
||||
Some("add-vsock") => add_vsock_api_command(
|
||||
&mut socket,
|
||||
matches
|
||||
.subcommand_matches("add-vsock")
|
||||
.unwrap()
|
||||
.get_one::<String>("vsock_config")
|
||||
.unwrap(),
|
||||
),
|
||||
Some("snapshot") => snapshot_api_command(
|
||||
&mut socket,
|
||||
matches
|
||||
.subcommand_matches("snapshot")
|
||||
.unwrap()
|
||||
.get_one::<String>("snapshot_config")
|
||||
.unwrap(),
|
||||
),
|
||||
Some("restore") => restore_api_command(
|
||||
&mut socket,
|
||||
matches
|
||||
.subcommand_matches("restore")
|
||||
.unwrap()
|
||||
.get_one::<String>("restore_config")
|
||||
.unwrap(),
|
||||
),
|
||||
Some("coredump") => coredump_api_command(
|
||||
&mut socket,
|
||||
matches
|
||||
.subcommand_matches("coredump")
|
||||
.unwrap()
|
||||
.get_one::<String>("coredump_config")
|
||||
.unwrap(),
|
||||
),
|
||||
Some("send-migration") => send_migration_api_command(
|
||||
&mut socket,
|
||||
matches
|
||||
.subcommand_matches("send-migration")
|
||||
.unwrap()
|
||||
.get_one::<String>("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::<String>("receive_migration_config")
|
||||
.unwrap(),
|
||||
),
|
||||
Some("create") => create_api_command(
|
||||
&mut socket,
|
||||
matches
|
||||
.subcommand_matches("create")
|
||||
.unwrap()
|
||||
.get_one::<String>("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<String>,
|
||||
}
|
||||
|
||||
#[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<u8>,
|
||||
|
||||
#[argh(option, long = "memory")]
|
||||
/// new memory size in bytes (supports K/M/G suffix)"
|
||||
memory: Option<String>,
|
||||
|
||||
#[argh(option, long = "balloon")]
|
||||
/// new balloon size in bytes (supports K/M/G suffix)"
|
||||
balloon: Option<String>,
|
||||
}
|
||||
|
||||
#[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("<device_id>")),
|
||||
)
|
||||
.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("<destination_url>"),
|
||||
),
|
||||
)
|
||||
.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("<file_path>")),
|
||||
)
|
||||
.subcommand(
|
||||
Command::new("send-migration")
|
||||
.about("Initiate a VM migration")
|
||||
.arg(
|
||||
Arg::new("send_migration_config")
|
||||
.index(1)
|
||||
.help("<destination_url>"),
|
||||
)
|
||||
.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("<receiver_url>"),
|
||||
),
|
||||
)
|
||||
.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)
|
||||
};
|
||||
|
@ -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<u8>) {
|
||||
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"))
|
||||
|
Loading…
Reference in New Issue
Block a user