main: switch command parsing to use clap

Partially revert 111225a2a5
and add the new dbus and pvpanic arguments.

As we are switching back to clap observe the following changes.

A few examples:

1. `-v -v -v` needs to be written as`-vvv`
2. `--disk D1 --disk D2` and others need to be written as `--disk D1 D2`.
3. `--option value` needs to be written as `--option=value.`

Change integration tests to adapt to the breaking changes.

Signed-off-by: Wei Liu <liuwe@microsoft.com>
Signed-off-by: Ravi kumar Veeramally <ravikumar.veeramally@intel.com>
This commit is contained in:
Wei Liu
2023-07-08 01:38:51 +00:00
committed by Bo Chen
parent 6113483363
commit 7bc3452139
10 changed files with 807 additions and 469 deletions

View File

@@ -4,6 +4,7 @@
//
pub use crate::vm_config::*;
use clap::ArgMatches;
use option_parser::{
ByteSized, IntegerList, OptionParser, OptionParserError, StringList, Toggle, Tuple,
};
@@ -402,6 +403,90 @@ pub struct VmParams<'a> {
pub tpm: Option<&'a str>,
}
impl<'a> VmParams<'a> {
pub fn from_arg_matches(args: &'a ArgMatches) -> Self {
// These .unwrap()s cannot fail as there is a default value defined
let cpus = args.get_one::<String>("cpus").unwrap();
let memory = args.get_one::<String>("memory").unwrap();
let memory_zones: Option<Vec<&str>> = args
.get_many::<String>("memory-zone")
.map(|x| x.map(|y| y as &str).collect());
let rng = args.get_one::<String>("rng").unwrap();
let serial = args.get_one::<String>("serial").unwrap();
let firmware = args.get_one::<String>("firmware").map(|x| x as &str);
let kernel = args.get_one::<String>("kernel").map(|x| x as &str);
let initramfs = args.get_one::<String>("initramfs").map(|x| x as &str);
let cmdline = args.get_one::<String>("cmdline").map(|x| x as &str);
let disks: Option<Vec<&str>> = args
.get_many::<String>("disk")
.map(|x| x.map(|y| y as &str).collect());
let net: Option<Vec<&str>> = args
.get_many::<String>("net")
.map(|x| x.map(|y| y as &str).collect());
let console = args.get_one::<String>("console").unwrap();
let balloon = args.get_one::<String>("balloon").map(|x| x as &str);
let fs: Option<Vec<&str>> = args
.get_many::<String>("fs")
.map(|x| x.map(|y| y as &str).collect());
let pmem: Option<Vec<&str>> = args
.get_many::<String>("pmem")
.map(|x| x.map(|y| y as &str).collect());
let devices: Option<Vec<&str>> = args
.get_many::<String>("device")
.map(|x| x.map(|y| y as &str).collect());
let user_devices: Option<Vec<&str>> = args
.get_many::<String>("user-device")
.map(|x| x.map(|y| y as &str).collect());
let vdpa: Option<Vec<&str>> = args
.get_many::<String>("vdpa")
.map(|x| x.map(|y| y as &str).collect());
let vsock: Option<&str> = args.get_one::<String>("vsock").map(|x| x as &str);
let pvpanic = args.get_flag("pvpanic");
#[cfg(target_arch = "x86_64")]
let sgx_epc: Option<Vec<&str>> = args
.get_many::<String>("sgx-epc")
.map(|x| x.map(|y| y as &str).collect());
let numa: Option<Vec<&str>> = args
.get_many::<String>("numa")
.map(|x| x.map(|y| y as &str).collect());
let watchdog = args.get_flag("watchdog");
let platform = args.get_one::<String>("platform").map(|x| x as &str);
#[cfg(feature = "guest_debug")]
let gdb = args.contains_id("gdb");
let tpm: Option<&str> = args.get_one::<String>("tpm").map(|x| x as &str);
VmParams {
cpus,
memory,
memory_zones,
firmware,
kernel,
initramfs,
cmdline,
disks,
net,
rng,
balloon,
fs,
pmem,
serial,
console,
devices,
user_devices,
vdpa,
vsock,
pvpanic,
#[cfg(target_arch = "x86_64")]
sgx_epc,
numa,
watchdog,
#[cfg(feature = "guest_debug")]
gdb,
platform,
tpm,
}
}
}
#[derive(Debug)]
pub enum ParseHotplugMethodError {
InvalidValue(String),
@@ -776,6 +861,14 @@ impl MemoryConfig {
}
impl DiskConfig {
pub const SYNTAX: &'static str = "Disk parameters \
\"path=<disk_image_path>,readonly=on|off,direct=on|off,iommu=on|off,\
num_queues=<number_of_queues>,queue_size=<size_of_each_queue>,\
vhost_user=on|off,socket=<vhost_user_socket_path>,\
bw_size=<bytes>,bw_one_time_burst=<bytes>,bw_refill_time=<ms>,\
ops_size=<io_ops>,ops_one_time_burst=<io_ops>,ops_refill_time=<ms>,\
id=<device_id>,pci_segment=<segment_id>\"";
pub fn parse(disk: &str) -> Result<Self> {
let mut parser = OptionParser::new();
parser
@@ -951,6 +1044,14 @@ impl FromStr for VhostMode {
}
impl NetConfig {
pub const SYNTAX: &'static str = "Network parameters \
\"tap=<if_name>,ip=<ip_addr>,mask=<net_mask>,mac=<mac_addr>,fd=<fd1,fd2...>,iommu=on|off,\
num_queues=<number_of_queues>,queue_size=<size_of_each_queue>,id=<device_id>,\
vhost_user=<vhost_user_enable>,socket=<vhost_user_socket_path>,vhost_mode=client|server,\
bw_size=<bytes>,bw_one_time_burst=<bytes>,bw_refill_time=<ms>,\
ops_size=<io_ops>,ops_one_time_burst=<io_ops>,ops_refill_time=<ms>,pci_segment=<segment_id>\
offload_tso=on|off,offload_ufo=on|off,offload_csum=on|off\"";
pub fn parse(net: &str) -> Result<Self> {
let mut parser = OptionParser::new();
@@ -1191,6 +1292,10 @@ impl RngConfig {
}
impl BalloonConfig {
pub const SYNTAX: &'static str =
"Balloon parameters \"size=<balloon_size>,deflate_on_oom=on|off,\
free_page_reporting=on|off\"";
pub fn parse(balloon: &str) -> Result<Self> {
let mut parser = OptionParser::new();
parser.add("size");
@@ -1225,6 +1330,10 @@ impl BalloonConfig {
}
impl FsConfig {
pub const SYNTAX: &'static str = "virtio-fs parameters \
\"tag=<tag_name>,socket=<socket_path>,num_queues=<number_of_queues>,\
queue_size=<size_of_each_queue>,id=<device_id>,pci_segment=<segment_id>\"";
pub fn parse(fs: &str) -> Result<Self> {
let mut parser = OptionParser::new();
parser
@@ -1289,6 +1398,10 @@ impl FsConfig {
}
impl PmemConfig {
pub const SYNTAX: &'static str = "Persistent memory parameters \
\"file=<backing_file_path>,size=<persistent_memory_size>,iommu=on|off,\
discard_writes=on|off,id=<device_id>,pci_segment=<segment_id>\"";
pub fn parse(pmem: &str) -> Result<Self> {
let mut parser = OptionParser::new();
parser
@@ -1402,6 +1515,9 @@ impl ConsoleConfig {
}
impl DeviceConfig {
pub const SYNTAX: &'static str =
"Direct device assignment parameters \"path=<device_path>,iommu=on|off,id=<device_id>,pci_segment=<segment_id>\"";
pub fn parse(device: &str) -> Result<Self> {
let mut parser = OptionParser::new();
parser.add("path").add("id").add("iommu").add("pci_segment");
@@ -1448,6 +1564,9 @@ impl DeviceConfig {
}
impl UserDeviceConfig {
pub const SYNTAX: &'static str =
"Userspace device socket=<socket_path>,id=<device_id>,pci_segment=<segment_id>\"";
pub fn parse(user_device: &str) -> Result<Self> {
let mut parser = OptionParser::new();
parser.add("socket").add("id").add("pci_segment");
@@ -1490,6 +1609,10 @@ impl UserDeviceConfig {
}
impl VdpaConfig {
pub const SYNTAX: &'static str = "vDPA device \
\"path=<device_path>,num_queues=<number_of_queues>,iommu=on|off,\
id=<device_id>,pci_segment=<segment_id>\"";
pub fn parse(vdpa: &str) -> Result<Self> {
let mut parser = OptionParser::new();
parser
@@ -1546,6 +1669,9 @@ impl VdpaConfig {
}
impl VsockConfig {
pub const SYNTAX: &'static str = "Virtio VSOCK parameters \
\"cid=<context_id>,socket=<socket_path>,iommu=on|off,id=<device_id>,pci_segment=<segment_id>\"";
pub fn parse(vsock: &str) -> Result<Self> {
let mut parser = OptionParser::new();
parser
@@ -1603,6 +1729,9 @@ impl VsockConfig {
#[cfg(target_arch = "x86_64")]
impl SgxEpcConfig {
pub const SYNTAX: &'static str = "SGX EPC parameters \
\"id=<epc_section_identifier>,size=<epc_section_size>,prefault=on|off\"";
pub fn parse(sgx_epc: &str) -> Result<Self> {
let mut parser = OptionParser::new();
parser.add("id").add("size").add("prefault");
@@ -1625,6 +1754,10 @@ impl SgxEpcConfig {
}
impl NumaConfig {
pub const SYNTAX: &'static str = "Settings related to a given NUMA node \
\"guest_numa_id=<node_id>,cpus=<cpus_id>,distances=<list_of_distances_to_destination_nodes>,\
memory_zones=<list_of_memory_zones>,sgx_epc_sections=<list_of_sgx_epc_sections>\"";
pub fn parse(numa: &str) -> Result<Self> {
let mut parser = OptionParser::new();
parser
@@ -1689,6 +1822,11 @@ pub struct RestoreConfig {
}
impl RestoreConfig {
pub const SYNTAX: &'static str = "Restore from a VM snapshot. \
\nRestore parameters \"source_url=<source_url>,prefault=on|off\" \
\n`source_url` should be a valid URL (e.g file:///foo/bar or tcp://192.168.1.10/foo) \
\n`prefault` brings memory pages in when enabled (disabled by default)";
pub fn parse(restore: &str) -> Result<Self> {
let mut parser = OptionParser::new();
parser.add("source_url").add("prefault");
@@ -1712,6 +1850,9 @@ impl RestoreConfig {
}
impl TpmConfig {
pub const SYNTAX: &'static str = "TPM device \
\"(UNIX Domain Socket from swtpm) socket=</path/to/a/socket>\"";
pub fn parse(tpm: &str) -> Result<Self> {
let mut parser = OptionParser::new();
parser.add("socket");