2019-02-21 16:39:34 +00:00
|
|
|
// Copyright © 2019 Intel Corporation
|
|
|
|
//
|
|
|
|
// SPDX-License-Identifier: Apache-2.0
|
|
|
|
//
|
|
|
|
|
2021-02-17 11:19:39 +00:00
|
|
|
#[macro_use]
|
|
|
|
extern crate event_monitor;
|
|
|
|
|
2023-01-12 18:50:20 +00:00
|
|
|
use argh::FromArgs;
|
2019-09-25 13:01:49 +00:00
|
|
|
use libc::EFD_NONBLOCK;
|
2023-04-27 12:43:57 +00:00
|
|
|
use log::{warn, LevelFilter};
|
2021-03-04 16:00:41 +00:00
|
|
|
use option_parser::OptionParser;
|
2021-08-17 03:40:11 +00:00
|
|
|
use seccompiler::SeccompAction;
|
2022-03-07 10:42:33 +00:00
|
|
|
use signal_hook::consts::SIGSYS;
|
2020-10-26 16:16:56 +00:00
|
|
|
use std::env;
|
2021-02-17 11:19:39 +00:00
|
|
|
use std::fs::File;
|
2021-04-09 23:46:55 +00:00
|
|
|
use std::os::unix::io::{FromRawFd, RawFd};
|
2019-09-25 13:01:49 +00:00
|
|
|
use std::sync::mpsc::channel;
|
2019-09-24 14:00:00 +00:00
|
|
|
use std::sync::{Arc, Mutex};
|
2020-10-26 16:16:56 +00:00
|
|
|
use thiserror::Error;
|
2023-03-25 12:18:13 +00:00
|
|
|
#[cfg(feature = "dbus_api")]
|
2023-04-05 12:22:05 +00:00
|
|
|
use vmm::api::dbus::{dbus_api_graceful_shutdown, DBusApiOptions};
|
2019-05-23 19:48:05 +00:00
|
|
|
use vmm::config;
|
2019-09-25 13:01:49 +00:00
|
|
|
use vmm_sys_util::eventfd::EventFd;
|
vmm: ensure signal handlers run on the right thread
Despite setting up a dedicated thread for signal handling, we weren't
making sure that the signals we were listening for there were actually
dispatched to the right thread. While the signal-hook provides an
iterator API, so we can know that we're only processing the signals
coming out of the iterator on our signal handling thread, the actual
signal handling code from signal-hook, which pushes the signals onto
the iterator, can run on any thread. This can lead to seccomp
violations when the signal-hook signal handler does something that
isn't allowed on that thread by our seccomp policy.
To reproduce, resize a terminal running cloud-hypervisor continuously
for a few minutes. Eventually, the kernel will deliver a SIGWINCH to
a thread with a restrictive seccomp policy, and a seccomp violation
will trigger.
As part of this change, it's also necessary to allow rt_sigreturn(2)
on the signal handling thread, so signal handlers are actually allowed
to run on it. The fact that this didn't seem to be needed before
makes me think that signal handlers were almost _never_ actually
running on the signal handling thread.
Signed-off-by: Alyssa Ross <hi@alyssa.is>
2021-09-02 19:16:45 +00:00
|
|
|
use vmm_sys_util::signal::block_signal;
|
2019-03-07 13:56:43 +00:00
|
|
|
|
2023-01-17 12:53:55 +00:00
|
|
|
#[cfg(feature = "dhat-heap")]
|
|
|
|
#[global_allocator]
|
|
|
|
static ALLOC: dhat::Alloc = dhat::Alloc;
|
|
|
|
|
2020-10-26 16:16:56 +00:00
|
|
|
#[derive(Error, Debug)]
|
|
|
|
enum Error {
|
|
|
|
#[error("Failed to create API EventFd: {0}")]
|
2021-03-25 17:01:21 +00:00
|
|
|
CreateApiEventFd(#[source] std::io::Error),
|
2022-09-27 11:17:40 +00:00
|
|
|
#[cfg(feature = "guest_debug")]
|
2022-02-20 03:51:34 +00:00
|
|
|
#[error("Failed to create Debug EventFd: {0}")]
|
|
|
|
CreateDebugEventFd(#[source] std::io::Error),
|
2023-04-27 12:43:57 +00:00
|
|
|
#[error("Failed to create exit EventFd: {0}")]
|
|
|
|
CreateExitEventFd(#[source] std::io::Error),
|
2022-07-20 22:09:38 +00:00
|
|
|
#[error("Failed to open hypervisor interface (is hypervisor interface available?): {0}")]
|
2020-10-26 16:16:56 +00:00
|
|
|
CreateHypervisor(#[source] hypervisor::HypervisorError),
|
|
|
|
#[error("Failed to start the VMM thread: {0}")]
|
2021-03-25 17:01:21 +00:00
|
|
|
StartVmmThread(#[source] vmm::Error),
|
2020-10-26 16:16:56 +00:00
|
|
|
#[error("Error parsing config: {0}")]
|
|
|
|
ParsingConfig(vmm::config::Error),
|
|
|
|
#[error("Error creating VM: {0:?}")]
|
|
|
|
VmCreate(vmm::api::ApiError),
|
|
|
|
#[error("Error booting VM: {0:?}")]
|
|
|
|
VmBoot(vmm::api::ApiError),
|
|
|
|
#[error("Error restoring VM: {0:?}")]
|
|
|
|
VmRestore(vmm::api::ApiError),
|
|
|
|
#[error("Error parsing restore: {0}")]
|
|
|
|
ParsingRestore(vmm::config::Error),
|
|
|
|
#[error("Failed to join on VMM thread: {0:?}")]
|
|
|
|
ThreadJoin(std::boxed::Box<dyn std::any::Any + std::marker::Send>),
|
|
|
|
#[error("VMM thread exited with error: {0}")]
|
|
|
|
VmmThread(#[source] vmm::Error),
|
2021-04-09 23:46:55 +00:00
|
|
|
#[error("Error parsing --api-socket: {0}")]
|
|
|
|
ParsingApiSocket(std::num::ParseIntError),
|
2021-04-07 14:33:00 +00:00
|
|
|
#[error("Error parsing --event-monitor: {0}")]
|
|
|
|
ParsingEventMonitor(option_parser::OptionParserError),
|
2023-04-05 12:22:05 +00:00
|
|
|
#[cfg(feature = "dbus_api")]
|
|
|
|
#[error("`--dbus-object-path` option isn't provided")]
|
|
|
|
MissingDBusObjectPath,
|
|
|
|
#[cfg(feature = "dbus_api")]
|
|
|
|
#[error("`--dbus-service-name` option isn't provided")]
|
|
|
|
MissingDBusServiceName,
|
2021-04-07 14:33:00 +00:00
|
|
|
#[error("Error parsing --event-monitor: path or fd required")]
|
|
|
|
BareEventMonitor,
|
|
|
|
#[error("Error doing event monitor I/O: {0}")]
|
|
|
|
EventMonitorIo(std::io::Error),
|
2022-09-27 11:17:40 +00:00
|
|
|
#[cfg(feature = "guest_debug")]
|
2022-02-20 03:51:34 +00:00
|
|
|
#[error("Error parsing --gdb: {0}")]
|
|
|
|
ParsingGdb(option_parser::OptionParserError),
|
2022-09-27 11:17:40 +00:00
|
|
|
#[cfg(feature = "guest_debug")]
|
2022-02-20 03:51:34 +00:00
|
|
|
#[error("Error parsing --gdb: path required")]
|
|
|
|
BareGdb,
|
2021-04-07 14:33:00 +00:00
|
|
|
#[error("Error creating log file: {0}")]
|
|
|
|
LogFileCreation(std::io::Error),
|
|
|
|
#[error("Error setting up logger: {0}")]
|
|
|
|
LoggerSetup(log::SetLoggerError),
|
2020-10-26 16:16:56 +00:00
|
|
|
}
|
|
|
|
|
2019-08-07 11:19:21 +00:00
|
|
|
struct Logger {
|
2019-08-15 15:41:40 +00:00
|
|
|
output: Mutex<Box<dyn std::io::Write + Send>>,
|
2019-08-07 11:19:21 +00:00
|
|
|
start: std::time::Instant,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl log::Log for Logger {
|
|
|
|
fn enabled(&self, _metadata: &log::Metadata) -> bool {
|
|
|
|
true
|
|
|
|
}
|
|
|
|
|
|
|
|
fn log(&self, record: &log::Record) {
|
|
|
|
if !self.enabled(record.metadata()) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
let now = std::time::Instant::now();
|
|
|
|
let duration = now.duration_since(self.start);
|
|
|
|
|
2020-02-04 11:16:31 +00:00
|
|
|
if record.file().is_some() && record.line().is_some() {
|
2023-05-31 08:33:47 +00:00
|
|
|
write!(
|
2019-08-07 11:19:21 +00:00
|
|
|
*(*(self.output.lock().unwrap())),
|
2023-05-31 08:33:47 +00:00
|
|
|
"cloud-hypervisor: {:.6?}: <{}> {}:{}:{} -- {}\r\n",
|
2019-08-07 11:19:21 +00:00
|
|
|
duration,
|
2020-12-18 14:47:39 +00:00
|
|
|
std::thread::current().name().unwrap_or("anonymous"),
|
2019-08-07 11:19:21 +00:00
|
|
|
record.level(),
|
|
|
|
record.file().unwrap(),
|
|
|
|
record.line().unwrap(),
|
|
|
|
record.args()
|
|
|
|
)
|
|
|
|
} else {
|
2023-05-31 08:33:47 +00:00
|
|
|
write!(
|
2019-08-07 11:19:21 +00:00
|
|
|
*(*(self.output.lock().unwrap())),
|
2023-05-31 08:33:47 +00:00
|
|
|
"cloud-hypervisor: {:.6?}: <{}> {}:{} -- {}\r\n",
|
2019-08-07 11:19:21 +00:00
|
|
|
duration,
|
2020-12-18 14:47:39 +00:00
|
|
|
std::thread::current().name().unwrap_or("anonymous"),
|
2019-08-07 11:19:21 +00:00
|
|
|
record.level(),
|
|
|
|
record.target(),
|
|
|
|
record.args()
|
|
|
|
)
|
2020-02-04 14:52:25 +00:00
|
|
|
}
|
|
|
|
.ok();
|
2019-08-07 11:19:21 +00:00
|
|
|
}
|
|
|
|
fn flush(&self) {}
|
|
|
|
}
|
|
|
|
|
2023-01-10 22:55:30 +00:00
|
|
|
fn default_vcpus() -> String {
|
|
|
|
format!(
|
|
|
|
"boot={},max_phys_bits={}",
|
|
|
|
config::DEFAULT_VCPUS,
|
|
|
|
config::DEFAULT_MAX_PHYS_BITS
|
|
|
|
)
|
|
|
|
}
|
|
|
|
|
|
|
|
fn default_memory() -> String {
|
|
|
|
format!("size={}M", config::DEFAULT_MEMORY_MB)
|
|
|
|
}
|
2019-12-13 07:34:39 +00:00
|
|
|
|
2023-01-10 22:55:30 +00:00
|
|
|
fn default_rng() -> String {
|
|
|
|
format!("src={}", config::DEFAULT_RNG_SOURCE)
|
2019-12-13 07:34:39 +00:00
|
|
|
}
|
|
|
|
|
2023-01-12 18:50:20 +00:00
|
|
|
#[derive(FromArgs)]
|
|
|
|
/// Launch a cloud-hypervisor VMM.
|
|
|
|
pub struct TopLevel {
|
|
|
|
#[argh(option, long = "cpus", default = "default_vcpus()")]
|
vmm: Improve "cloud-hypervisor --help" view format
Rust documentation comments follows 80 char per line. But some of
these help options doesn't have space in between. Longlines of
text is starting from beginning of the next line instead of
proper format.
Before fix:
Options:
--cpus boot=<boot_vcpus>,max=<max_vcpus>,topology=<threads_per_core>:<cores_per_die>:<dies_per_package>:<packages>,kvm_hyperv=on|off,max_phys_bits=<maximum_number_of_physical_bits>,affinity=<list_of_vcpus_with_their_associated_cpuset>,features=<list_of_features_to_enable>
After fix:
Options:
--cpus boot=<boot_vcpus>, max=<max_vcpus>,
topology=<threads_per_core>:<cores_per_die>:<dies_per_package>:<packages>,
kvm_hyperv=on|off,
max_phys_bits=<maximum_number_of_physical_bits>,
affinity=<list_of_vcpus_with_their_associated_cpuset>,
features=<list_of_features_to_enable>
Signed-off-by: Ravi kumar Veeramally <ravikumar.veeramally@intel.com>
2023-05-25 14:40:37 +00:00
|
|
|
/// boot=<boot_vcpus>, max=<max_vcpus>, topology=<threads_per_core>:<cores_per_die>:<dies_per_package>:<packages>, kvm_hyperv=on|off, max_phys_bits=<maximum_number_of_physical_bits>, affinity=<list_of_vcpus_with_their_associated_cpuset>, features=<list_of_features_to_enable>
|
2023-01-12 18:50:20 +00:00
|
|
|
cpus: String,
|
2022-09-15 04:11:59 +00:00
|
|
|
|
2023-01-12 18:50:20 +00:00
|
|
|
#[argh(option, long = "platform")]
|
vmm: Improve "cloud-hypervisor --help" view format
Rust documentation comments follows 80 char per line. But some of
these help options doesn't have space in between. Longlines of
text is starting from beginning of the next line instead of
proper format.
Before fix:
Options:
--cpus boot=<boot_vcpus>,max=<max_vcpus>,topology=<threads_per_core>:<cores_per_die>:<dies_per_package>:<packages>,kvm_hyperv=on|off,max_phys_bits=<maximum_number_of_physical_bits>,affinity=<list_of_vcpus_with_their_associated_cpuset>,features=<list_of_features_to_enable>
After fix:
Options:
--cpus boot=<boot_vcpus>, max=<max_vcpus>,
topology=<threads_per_core>:<cores_per_die>:<dies_per_package>:<packages>,
kvm_hyperv=on|off,
max_phys_bits=<maximum_number_of_physical_bits>,
affinity=<list_of_vcpus_with_their_associated_cpuset>,
features=<list_of_features_to_enable>
Signed-off-by: Ravi kumar Veeramally <ravikumar.veeramally@intel.com>
2023-05-25 14:40:37 +00:00
|
|
|
/// num_pci_segments=<num_pci_segments>, iommu_segments=<list_of_segments>, serial_number=<dmi_device_serial_number>, uuid=<dmi_device_uuid>, oem_strings=<list_of_strings>
|
2023-01-12 18:50:20 +00:00
|
|
|
platform: Option<String>,
|
|
|
|
|
|
|
|
#[argh(option, long = "memory", default = "default_memory()")]
|
vmm: Improve "cloud-hypervisor --help" view format
Rust documentation comments follows 80 char per line. But some of
these help options doesn't have space in between. Longlines of
text is starting from beginning of the next line instead of
proper format.
Before fix:
Options:
--cpus boot=<boot_vcpus>,max=<max_vcpus>,topology=<threads_per_core>:<cores_per_die>:<dies_per_package>:<packages>,kvm_hyperv=on|off,max_phys_bits=<maximum_number_of_physical_bits>,affinity=<list_of_vcpus_with_their_associated_cpuset>,features=<list_of_features_to_enable>
After fix:
Options:
--cpus boot=<boot_vcpus>, max=<max_vcpus>,
topology=<threads_per_core>:<cores_per_die>:<dies_per_package>:<packages>,
kvm_hyperv=on|off,
max_phys_bits=<maximum_number_of_physical_bits>,
affinity=<list_of_vcpus_with_their_associated_cpuset>,
features=<list_of_features_to_enable>
Signed-off-by: Ravi kumar Veeramally <ravikumar.veeramally@intel.com>
2023-05-25 14:40:37 +00:00
|
|
|
/// size=<guest_memory_size>, mergeable=on|off, shared=on|off, hugepages=on|off, hugepage_size=<hugepage_size>, hotplug_method=acpi|virtio-mem, hotplug_size=<hotpluggable_memory_size>, hotplugged_size=<hotplugged_memory_size>, prefault=on|off, thp=on|off
|
2023-01-12 18:50:20 +00:00
|
|
|
memory: String,
|
|
|
|
|
|
|
|
#[argh(option, long = "memory-zone")]
|
vmm: Improve "cloud-hypervisor --help" view format
Rust documentation comments follows 80 char per line. But some of
these help options doesn't have space in between. Longlines of
text is starting from beginning of the next line instead of
proper format.
Before fix:
Options:
--cpus boot=<boot_vcpus>,max=<max_vcpus>,topology=<threads_per_core>:<cores_per_die>:<dies_per_package>:<packages>,kvm_hyperv=on|off,max_phys_bits=<maximum_number_of_physical_bits>,affinity=<list_of_vcpus_with_their_associated_cpuset>,features=<list_of_features_to_enable>
After fix:
Options:
--cpus boot=<boot_vcpus>, max=<max_vcpus>,
topology=<threads_per_core>:<cores_per_die>:<dies_per_package>:<packages>,
kvm_hyperv=on|off,
max_phys_bits=<maximum_number_of_physical_bits>,
affinity=<list_of_vcpus_with_their_associated_cpuset>,
features=<list_of_features_to_enable>
Signed-off-by: Ravi kumar Veeramally <ravikumar.veeramally@intel.com>
2023-05-25 14:40:37 +00:00
|
|
|
/// size=<guest_memory_region_size>, file=<backing_file>, shared=on|off, hugepages=on|off, hugepage_size=<hugepage_size>, host_numa_node=<node_id>, id=<zone_identifier>, hotplug_size=<hotpluggable_memory_size>, hotplugged_size=<hotplugged_memory_size>, prefault=on|off
|
2023-01-12 18:50:20 +00:00
|
|
|
memory_zone: Vec<String>,
|
|
|
|
|
|
|
|
#[argh(option, long = "firmware")]
|
|
|
|
/// path to firmware that is loaded in an architectural specific way
|
|
|
|
firmware: Option<String>,
|
|
|
|
|
|
|
|
#[argh(option, long = "kernel")]
|
|
|
|
/// path to kernel or firmware that supports a PVH entry point or architecture equivalent
|
|
|
|
kernel: Option<String>,
|
|
|
|
|
|
|
|
#[argh(option, long = "initramfs")]
|
|
|
|
/// path to initramfs image
|
|
|
|
initramfs: Option<String>,
|
|
|
|
|
|
|
|
#[argh(option, long = "cmdline")]
|
|
|
|
/// kernel command line
|
|
|
|
cmdline: Option<String>,
|
|
|
|
|
|
|
|
#[argh(option, long = "disk")]
|
vmm: Improve "cloud-hypervisor --help" view format
Rust documentation comments follows 80 char per line. But some of
these help options doesn't have space in between. Longlines of
text is starting from beginning of the next line instead of
proper format.
Before fix:
Options:
--cpus boot=<boot_vcpus>,max=<max_vcpus>,topology=<threads_per_core>:<cores_per_die>:<dies_per_package>:<packages>,kvm_hyperv=on|off,max_phys_bits=<maximum_number_of_physical_bits>,affinity=<list_of_vcpus_with_their_associated_cpuset>,features=<list_of_features_to_enable>
After fix:
Options:
--cpus boot=<boot_vcpus>, max=<max_vcpus>,
topology=<threads_per_core>:<cores_per_die>:<dies_per_package>:<packages>,
kvm_hyperv=on|off,
max_phys_bits=<maximum_number_of_physical_bits>,
affinity=<list_of_vcpus_with_their_associated_cpuset>,
features=<list_of_features_to_enable>
Signed-off-by: Ravi kumar Veeramally <ravikumar.veeramally@intel.com>
2023-05-25 14:40:37 +00:00
|
|
|
/// 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>
|
2023-01-12 18:50:20 +00:00
|
|
|
disk: Vec<String>,
|
|
|
|
|
|
|
|
#[argh(option, long = "net")]
|
vmm: Improve "cloud-hypervisor --help" view format
Rust documentation comments follows 80 char per line. But some of
these help options doesn't have space in between. Longlines of
text is starting from beginning of the next line instead of
proper format.
Before fix:
Options:
--cpus boot=<boot_vcpus>,max=<max_vcpus>,topology=<threads_per_core>:<cores_per_die>:<dies_per_package>:<packages>,kvm_hyperv=on|off,max_phys_bits=<maximum_number_of_physical_bits>,affinity=<list_of_vcpus_with_their_associated_cpuset>,features=<list_of_features_to_enable>
After fix:
Options:
--cpus boot=<boot_vcpus>, max=<max_vcpus>,
topology=<threads_per_core>:<cores_per_die>:<dies_per_package>:<packages>,
kvm_hyperv=on|off,
max_phys_bits=<maximum_number_of_physical_bits>,
affinity=<list_of_vcpus_with_their_associated_cpuset>,
features=<list_of_features_to_enable>
Signed-off-by: Ravi kumar Veeramally <ravikumar.veeramally@intel.com>
2023-05-25 14:40:37 +00:00
|
|
|
/// 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
|
2023-01-12 18:50:20 +00:00
|
|
|
net: Vec<String>,
|
|
|
|
|
|
|
|
#[argh(option, long = "rng", default = "default_rng()")]
|
vmm: Improve "cloud-hypervisor --help" view format
Rust documentation comments follows 80 char per line. But some of
these help options doesn't have space in between. Longlines of
text is starting from beginning of the next line instead of
proper format.
Before fix:
Options:
--cpus boot=<boot_vcpus>,max=<max_vcpus>,topology=<threads_per_core>:<cores_per_die>:<dies_per_package>:<packages>,kvm_hyperv=on|off,max_phys_bits=<maximum_number_of_physical_bits>,affinity=<list_of_vcpus_with_their_associated_cpuset>,features=<list_of_features_to_enable>
After fix:
Options:
--cpus boot=<boot_vcpus>, max=<max_vcpus>,
topology=<threads_per_core>:<cores_per_die>:<dies_per_package>:<packages>,
kvm_hyperv=on|off,
max_phys_bits=<maximum_number_of_physical_bits>,
affinity=<list_of_vcpus_with_their_associated_cpuset>,
features=<list_of_features_to_enable>
Signed-off-by: Ravi kumar Veeramally <ravikumar.veeramally@intel.com>
2023-05-25 14:40:37 +00:00
|
|
|
/// src=<entropy_source_path>, iommu=on|off
|
2023-01-12 18:50:20 +00:00
|
|
|
rng: String,
|
|
|
|
|
|
|
|
#[argh(option, long = "balloon")]
|
vmm: Improve "cloud-hypervisor --help" view format
Rust documentation comments follows 80 char per line. But some of
these help options doesn't have space in between. Longlines of
text is starting from beginning of the next line instead of
proper format.
Before fix:
Options:
--cpus boot=<boot_vcpus>,max=<max_vcpus>,topology=<threads_per_core>:<cores_per_die>:<dies_per_package>:<packages>,kvm_hyperv=on|off,max_phys_bits=<maximum_number_of_physical_bits>,affinity=<list_of_vcpus_with_their_associated_cpuset>,features=<list_of_features_to_enable>
After fix:
Options:
--cpus boot=<boot_vcpus>, max=<max_vcpus>,
topology=<threads_per_core>:<cores_per_die>:<dies_per_package>:<packages>,
kvm_hyperv=on|off,
max_phys_bits=<maximum_number_of_physical_bits>,
affinity=<list_of_vcpus_with_their_associated_cpuset>,
features=<list_of_features_to_enable>
Signed-off-by: Ravi kumar Veeramally <ravikumar.veeramally@intel.com>
2023-05-25 14:40:37 +00:00
|
|
|
/// size=<balloon_size>, deflate_on_oom=on|off, free_page_reporting=on|off
|
2023-01-12 18:50:20 +00:00
|
|
|
balloon: Option<String>,
|
|
|
|
|
|
|
|
#[argh(option, long = "fs")]
|
vmm: Improve "cloud-hypervisor --help" view format
Rust documentation comments follows 80 char per line. But some of
these help options doesn't have space in between. Longlines of
text is starting from beginning of the next line instead of
proper format.
Before fix:
Options:
--cpus boot=<boot_vcpus>,max=<max_vcpus>,topology=<threads_per_core>:<cores_per_die>:<dies_per_package>:<packages>,kvm_hyperv=on|off,max_phys_bits=<maximum_number_of_physical_bits>,affinity=<list_of_vcpus_with_their_associated_cpuset>,features=<list_of_features_to_enable>
After fix:
Options:
--cpus boot=<boot_vcpus>, max=<max_vcpus>,
topology=<threads_per_core>:<cores_per_die>:<dies_per_package>:<packages>,
kvm_hyperv=on|off,
max_phys_bits=<maximum_number_of_physical_bits>,
affinity=<list_of_vcpus_with_their_associated_cpuset>,
features=<list_of_features_to_enable>
Signed-off-by: Ravi kumar Veeramally <ravikumar.veeramally@intel.com>
2023-05-25 14:40:37 +00:00
|
|
|
/// tag=<tag_name>, socket=<socket_path>, num_queues=<number_of_queues>, queue_size=<size_of_each_queue>, id=<device_id>, pci_segment=<segment_id>
|
2023-01-12 18:50:20 +00:00
|
|
|
fs: Vec<String>,
|
|
|
|
|
|
|
|
#[argh(option, long = "pmem")]
|
vmm: Improve "cloud-hypervisor --help" view format
Rust documentation comments follows 80 char per line. But some of
these help options doesn't have space in between. Longlines of
text is starting from beginning of the next line instead of
proper format.
Before fix:
Options:
--cpus boot=<boot_vcpus>,max=<max_vcpus>,topology=<threads_per_core>:<cores_per_die>:<dies_per_package>:<packages>,kvm_hyperv=on|off,max_phys_bits=<maximum_number_of_physical_bits>,affinity=<list_of_vcpus_with_their_associated_cpuset>,features=<list_of_features_to_enable>
After fix:
Options:
--cpus boot=<boot_vcpus>, max=<max_vcpus>,
topology=<threads_per_core>:<cores_per_die>:<dies_per_package>:<packages>,
kvm_hyperv=on|off,
max_phys_bits=<maximum_number_of_physical_bits>,
affinity=<list_of_vcpus_with_their_associated_cpuset>,
features=<list_of_features_to_enable>
Signed-off-by: Ravi kumar Veeramally <ravikumar.veeramally@intel.com>
2023-05-25 14:40:37 +00:00
|
|
|
/// file=<backing_file_path>, size=<persistent_memory_size>, iommu=on|off, discard_writes=on|off, id=<device_id>, pci_segment=<segment_id>
|
2023-01-12 18:50:20 +00:00
|
|
|
pmem: Vec<String>,
|
|
|
|
|
|
|
|
#[argh(option, long = "serial", default = "String::from(\"null\")")]
|
|
|
|
/// off|null|pty|tty|file=/path/to/a/file
|
|
|
|
serial: String,
|
|
|
|
|
|
|
|
#[argh(option, long = "console", default = "String::from(\"tty\")")]
|
vmm: Improve "cloud-hypervisor --help" view format
Rust documentation comments follows 80 char per line. But some of
these help options doesn't have space in between. Longlines of
text is starting from beginning of the next line instead of
proper format.
Before fix:
Options:
--cpus boot=<boot_vcpus>,max=<max_vcpus>,topology=<threads_per_core>:<cores_per_die>:<dies_per_package>:<packages>,kvm_hyperv=on|off,max_phys_bits=<maximum_number_of_physical_bits>,affinity=<list_of_vcpus_with_their_associated_cpuset>,features=<list_of_features_to_enable>
After fix:
Options:
--cpus boot=<boot_vcpus>, max=<max_vcpus>,
topology=<threads_per_core>:<cores_per_die>:<dies_per_package>:<packages>,
kvm_hyperv=on|off,
max_phys_bits=<maximum_number_of_physical_bits>,
affinity=<list_of_vcpus_with_their_associated_cpuset>,
features=<list_of_features_to_enable>
Signed-off-by: Ravi kumar Veeramally <ravikumar.veeramally@intel.com>
2023-05-25 14:40:37 +00:00
|
|
|
/// off|null|pty|tty|file=/path/to/a/file, iommu=on|off
|
2023-01-12 18:50:20 +00:00
|
|
|
console: String,
|
|
|
|
|
|
|
|
#[argh(option, long = "device")]
|
vmm: Improve "cloud-hypervisor --help" view format
Rust documentation comments follows 80 char per line. But some of
these help options doesn't have space in between. Longlines of
text is starting from beginning of the next line instead of
proper format.
Before fix:
Options:
--cpus boot=<boot_vcpus>,max=<max_vcpus>,topology=<threads_per_core>:<cores_per_die>:<dies_per_package>:<packages>,kvm_hyperv=on|off,max_phys_bits=<maximum_number_of_physical_bits>,affinity=<list_of_vcpus_with_their_associated_cpuset>,features=<list_of_features_to_enable>
After fix:
Options:
--cpus boot=<boot_vcpus>, max=<max_vcpus>,
topology=<threads_per_core>:<cores_per_die>:<dies_per_package>:<packages>,
kvm_hyperv=on|off,
max_phys_bits=<maximum_number_of_physical_bits>,
affinity=<list_of_vcpus_with_their_associated_cpuset>,
features=<list_of_features_to_enable>
Signed-off-by: Ravi kumar Veeramally <ravikumar.veeramally@intel.com>
2023-05-25 14:40:37 +00:00
|
|
|
/// path=<device_path>, iommu=on|off, id=<device_id>, pci_segment=<segment_id>
|
2023-01-12 18:50:20 +00:00
|
|
|
device: Vec<String>,
|
|
|
|
|
|
|
|
#[argh(option, long = "user-device")]
|
vmm: Improve "cloud-hypervisor --help" view format
Rust documentation comments follows 80 char per line. But some of
these help options doesn't have space in between. Longlines of
text is starting from beginning of the next line instead of
proper format.
Before fix:
Options:
--cpus boot=<boot_vcpus>,max=<max_vcpus>,topology=<threads_per_core>:<cores_per_die>:<dies_per_package>:<packages>,kvm_hyperv=on|off,max_phys_bits=<maximum_number_of_physical_bits>,affinity=<list_of_vcpus_with_their_associated_cpuset>,features=<list_of_features_to_enable>
After fix:
Options:
--cpus boot=<boot_vcpus>, max=<max_vcpus>,
topology=<threads_per_core>:<cores_per_die>:<dies_per_package>:<packages>,
kvm_hyperv=on|off,
max_phys_bits=<maximum_number_of_physical_bits>,
affinity=<list_of_vcpus_with_their_associated_cpuset>,
features=<list_of_features_to_enable>
Signed-off-by: Ravi kumar Veeramally <ravikumar.veeramally@intel.com>
2023-05-25 14:40:37 +00:00
|
|
|
/// socket=<socket_path>, id=<device_id>, pci_segment=<segment_id>
|
2023-01-12 18:50:20 +00:00
|
|
|
user_device: Vec<String>,
|
|
|
|
|
|
|
|
#[argh(option, long = "vdpa")]
|
vmm: Improve "cloud-hypervisor --help" view format
Rust documentation comments follows 80 char per line. But some of
these help options doesn't have space in between. Longlines of
text is starting from beginning of the next line instead of
proper format.
Before fix:
Options:
--cpus boot=<boot_vcpus>,max=<max_vcpus>,topology=<threads_per_core>:<cores_per_die>:<dies_per_package>:<packages>,kvm_hyperv=on|off,max_phys_bits=<maximum_number_of_physical_bits>,affinity=<list_of_vcpus_with_their_associated_cpuset>,features=<list_of_features_to_enable>
After fix:
Options:
--cpus boot=<boot_vcpus>, max=<max_vcpus>,
topology=<threads_per_core>:<cores_per_die>:<dies_per_package>:<packages>,
kvm_hyperv=on|off,
max_phys_bits=<maximum_number_of_physical_bits>,
affinity=<list_of_vcpus_with_their_associated_cpuset>,
features=<list_of_features_to_enable>
Signed-off-by: Ravi kumar Veeramally <ravikumar.veeramally@intel.com>
2023-05-25 14:40:37 +00:00
|
|
|
/// path=<device_path>, num_queues=<number_of_queues>, iommu=on|off, id=<device_id>, pci_segment=<segment_id>
|
2023-01-12 18:50:20 +00:00
|
|
|
vdpa: Vec<String>,
|
|
|
|
|
|
|
|
#[argh(option, long = "vsock")]
|
vmm: Improve "cloud-hypervisor --help" view format
Rust documentation comments follows 80 char per line. But some of
these help options doesn't have space in between. Longlines of
text is starting from beginning of the next line instead of
proper format.
Before fix:
Options:
--cpus boot=<boot_vcpus>,max=<max_vcpus>,topology=<threads_per_core>:<cores_per_die>:<dies_per_package>:<packages>,kvm_hyperv=on|off,max_phys_bits=<maximum_number_of_physical_bits>,affinity=<list_of_vcpus_with_their_associated_cpuset>,features=<list_of_features_to_enable>
After fix:
Options:
--cpus boot=<boot_vcpus>, max=<max_vcpus>,
topology=<threads_per_core>:<cores_per_die>:<dies_per_package>:<packages>,
kvm_hyperv=on|off,
max_phys_bits=<maximum_number_of_physical_bits>,
affinity=<list_of_vcpus_with_their_associated_cpuset>,
features=<list_of_features_to_enable>
Signed-off-by: Ravi kumar Veeramally <ravikumar.veeramally@intel.com>
2023-05-25 14:40:37 +00:00
|
|
|
/// cid=<context_id>, socket=<socket_path>, iommu=on|off, id=<device_id>, pci_segment=<segment_id>
|
2023-01-12 18:50:20 +00:00
|
|
|
vsock: Option<String>,
|
|
|
|
|
2023-06-15 04:02:45 +00:00
|
|
|
#[argh(switch, long = "pvpanic")]
|
|
|
|
/// enable pvpanic device
|
|
|
|
pvpanic: bool,
|
|
|
|
|
2023-01-12 18:50:20 +00:00
|
|
|
#[argh(option, long = "numa")]
|
vmm: Improve "cloud-hypervisor --help" view format
Rust documentation comments follows 80 char per line. But some of
these help options doesn't have space in between. Longlines of
text is starting from beginning of the next line instead of
proper format.
Before fix:
Options:
--cpus boot=<boot_vcpus>,max=<max_vcpus>,topology=<threads_per_core>:<cores_per_die>:<dies_per_package>:<packages>,kvm_hyperv=on|off,max_phys_bits=<maximum_number_of_physical_bits>,affinity=<list_of_vcpus_with_their_associated_cpuset>,features=<list_of_features_to_enable>
After fix:
Options:
--cpus boot=<boot_vcpus>, max=<max_vcpus>,
topology=<threads_per_core>:<cores_per_die>:<dies_per_package>:<packages>,
kvm_hyperv=on|off,
max_phys_bits=<maximum_number_of_physical_bits>,
affinity=<list_of_vcpus_with_their_associated_cpuset>,
features=<list_of_features_to_enable>
Signed-off-by: Ravi kumar Veeramally <ravikumar.veeramally@intel.com>
2023-05-25 14:40:37 +00:00
|
|
|
/// 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>
|
2023-01-12 18:50:20 +00:00
|
|
|
numa: Vec<String>,
|
|
|
|
|
|
|
|
#[argh(switch, long = "watchdog")]
|
|
|
|
/// enable virtio-watchdog
|
|
|
|
watchdog: bool,
|
|
|
|
|
|
|
|
#[argh(switch, short = 'v')]
|
|
|
|
/// set the level of debugging output
|
|
|
|
verbosity: u8,
|
|
|
|
|
|
|
|
#[argh(option, long = "log-file")]
|
|
|
|
/// path to log file
|
|
|
|
log_file: Option<String>,
|
|
|
|
|
|
|
|
#[argh(option, long = "api-socket")]
|
|
|
|
/// path=<path/to/a/file>|fd=<fd>
|
|
|
|
api_socket: Option<String>,
|
|
|
|
|
2023-04-05 12:22:05 +00:00
|
|
|
#[cfg(feature = "dbus_api")]
|
|
|
|
#[argh(option, long = "dbus-service-name")]
|
|
|
|
/// well known name of the service
|
|
|
|
dbus_name: Option<String>,
|
|
|
|
|
|
|
|
#[cfg(feature = "dbus_api")]
|
|
|
|
#[argh(option, long = "dbus-object-path")]
|
|
|
|
/// object path to serve the dbus interface
|
|
|
|
dbus_path: Option<String>,
|
|
|
|
|
|
|
|
#[cfg(feature = "dbus_api")]
|
|
|
|
#[argh(switch, long = "dbus-system-bus")]
|
|
|
|
/// use the system bus instead of a session bus
|
|
|
|
dbus_system_bus: bool,
|
|
|
|
|
2023-01-12 18:50:20 +00:00
|
|
|
#[argh(option, long = "event-monitor")]
|
|
|
|
/// path=<path/to/a/file>|fd=<fd>
|
|
|
|
event_monitor: Option<String>,
|
|
|
|
|
|
|
|
#[argh(option, long = "restore")]
|
vmm: Improve "cloud-hypervisor --help" view format
Rust documentation comments follows 80 char per line. But some of
these help options doesn't have space in between. Longlines of
text is starting from beginning of the next line instead of
proper format.
Before fix:
Options:
--cpus boot=<boot_vcpus>,max=<max_vcpus>,topology=<threads_per_core>:<cores_per_die>:<dies_per_package>:<packages>,kvm_hyperv=on|off,max_phys_bits=<maximum_number_of_physical_bits>,affinity=<list_of_vcpus_with_their_associated_cpuset>,features=<list_of_features_to_enable>
After fix:
Options:
--cpus boot=<boot_vcpus>, max=<max_vcpus>,
topology=<threads_per_core>:<cores_per_die>:<dies_per_package>:<packages>,
kvm_hyperv=on|off,
max_phys_bits=<maximum_number_of_physical_bits>,
affinity=<list_of_vcpus_with_their_associated_cpuset>,
features=<list_of_features_to_enable>
Signed-off-by: Ravi kumar Veeramally <ravikumar.veeramally@intel.com>
2023-05-25 14:40:37 +00:00
|
|
|
/// source_url=<source_url>, prefault=on|off
|
2023-01-12 18:50:20 +00:00
|
|
|
restore: Option<String>,
|
|
|
|
|
|
|
|
#[argh(option, long = "seccomp", default = "String::from(\"true\")")]
|
|
|
|
/// seccomp configuration (true, false or log)
|
|
|
|
seccomp: String,
|
|
|
|
|
|
|
|
#[argh(option, long = "tpm")]
|
|
|
|
/// socket=<path/to/a/socket>
|
|
|
|
tpm: Option<String>,
|
2020-07-08 07:18:45 +00:00
|
|
|
|
|
|
|
#[cfg(target_arch = "x86_64")]
|
2023-01-12 18:50:20 +00:00
|
|
|
#[argh(option, long = "sgx-epc")]
|
vmm: Improve "cloud-hypervisor --help" view format
Rust documentation comments follows 80 char per line. But some of
these help options doesn't have space in between. Longlines of
text is starting from beginning of the next line instead of
proper format.
Before fix:
Options:
--cpus boot=<boot_vcpus>,max=<max_vcpus>,topology=<threads_per_core>:<cores_per_die>:<dies_per_package>:<packages>,kvm_hyperv=on|off,max_phys_bits=<maximum_number_of_physical_bits>,affinity=<list_of_vcpus_with_their_associated_cpuset>,features=<list_of_features_to_enable>
After fix:
Options:
--cpus boot=<boot_vcpus>, max=<max_vcpus>,
topology=<threads_per_core>:<cores_per_die>:<dies_per_package>:<packages>,
kvm_hyperv=on|off,
max_phys_bits=<maximum_number_of_physical_bits>,
affinity=<list_of_vcpus_with_their_associated_cpuset>,
features=<list_of_features_to_enable>
Signed-off-by: Ravi kumar Veeramally <ravikumar.veeramally@intel.com>
2023-05-25 14:40:37 +00:00
|
|
|
/// id=<epc_section_identifier>, size=<epc_section_size>, prefault=on|off
|
2023-01-12 18:50:20 +00:00
|
|
|
sgx_epc: Vec<String>,
|
2020-07-08 07:18:45 +00:00
|
|
|
|
2022-09-27 11:17:40 +00:00
|
|
|
#[cfg(feature = "guest_debug")]
|
2023-01-12 18:50:20 +00:00
|
|
|
#[argh(option, long = "gdb")]
|
|
|
|
/// path=<path/to/a/file>
|
|
|
|
gdb: Option<String>,
|
|
|
|
|
|
|
|
#[argh(switch, short = 'V', long = "version")]
|
|
|
|
/// print version information
|
|
|
|
version: bool,
|
2019-12-12 16:57:11 +00:00
|
|
|
}
|
|
|
|
|
2023-01-12 18:50:20 +00:00
|
|
|
impl TopLevel {
|
|
|
|
fn to_vm_params(&self) -> config::VmParams<'_> {
|
|
|
|
let cpus = &self.cpus;
|
|
|
|
let memory = &self.memory;
|
|
|
|
let memory_zones = if !self.memory_zone.is_empty() {
|
|
|
|
Some(self.memory_zone.iter().map(|x| x.as_str()).collect())
|
|
|
|
} else {
|
|
|
|
None
|
|
|
|
};
|
|
|
|
let rng = &self.rng;
|
|
|
|
let serial = &self.serial;
|
|
|
|
let firmware = self.firmware.as_deref();
|
|
|
|
let kernel = self.kernel.as_deref();
|
|
|
|
let initramfs = self.initramfs.as_deref();
|
|
|
|
let cmdline = self.cmdline.as_deref();
|
|
|
|
|
|
|
|
let disks = if !self.disk.is_empty() {
|
|
|
|
Some(self.disk.iter().map(|x| x.as_str()).collect())
|
|
|
|
} else {
|
|
|
|
None
|
|
|
|
};
|
|
|
|
|
|
|
|
let net = if !self.net.is_empty() {
|
|
|
|
Some(self.net.iter().map(|x| x.as_str()).collect())
|
|
|
|
} else {
|
|
|
|
None
|
|
|
|
};
|
|
|
|
|
|
|
|
let console = &self.console;
|
|
|
|
let balloon = self.balloon.as_deref();
|
|
|
|
let fs = if !self.fs.is_empty() {
|
|
|
|
Some(self.fs.iter().map(|x| x.as_str()).collect())
|
|
|
|
} else {
|
|
|
|
None
|
|
|
|
};
|
|
|
|
|
|
|
|
let pmem = if !self.pmem.is_empty() {
|
|
|
|
Some(self.pmem.iter().map(|x| x.as_str()).collect())
|
|
|
|
} else {
|
|
|
|
None
|
|
|
|
};
|
|
|
|
let devices = if !self.device.is_empty() {
|
|
|
|
Some(self.device.iter().map(|x| x.as_str()).collect())
|
|
|
|
} else {
|
|
|
|
None
|
|
|
|
};
|
|
|
|
let user_devices = if !self.user_device.is_empty() {
|
|
|
|
Some(self.user_device.iter().map(|x| x.as_str()).collect())
|
|
|
|
} else {
|
|
|
|
None
|
|
|
|
};
|
|
|
|
let vdpa = if !self.vdpa.is_empty() {
|
|
|
|
Some(self.vdpa.iter().map(|x| x.as_str()).collect())
|
|
|
|
} else {
|
|
|
|
None
|
|
|
|
};
|
|
|
|
|
|
|
|
let vsock = self.vsock.as_deref();
|
2023-06-15 04:02:45 +00:00
|
|
|
|
|
|
|
let pvpanic = self.pvpanic;
|
|
|
|
|
2023-01-12 18:50:20 +00:00
|
|
|
#[cfg(target_arch = "x86_64")]
|
|
|
|
let sgx_epc = if !self.sgx_epc.is_empty() {
|
|
|
|
Some(self.sgx_epc.iter().map(|x| x.as_str()).collect())
|
|
|
|
} else {
|
|
|
|
None
|
|
|
|
};
|
|
|
|
|
|
|
|
let numa = if !self.numa.is_empty() {
|
|
|
|
Some(self.numa.iter().map(|x| x.as_str()).collect())
|
|
|
|
} else {
|
|
|
|
None
|
|
|
|
};
|
|
|
|
let watchdog = self.watchdog;
|
|
|
|
let platform = self.platform.as_deref();
|
|
|
|
#[cfg(feature = "guest_debug")]
|
|
|
|
let gdb = self.gdb.is_some();
|
|
|
|
let tpm = self.tpm.as_deref();
|
|
|
|
|
|
|
|
config::VmParams {
|
|
|
|
cpus,
|
|
|
|
memory,
|
|
|
|
memory_zones,
|
|
|
|
firmware,
|
|
|
|
kernel,
|
|
|
|
initramfs,
|
|
|
|
cmdline,
|
|
|
|
disks,
|
|
|
|
net,
|
|
|
|
rng,
|
|
|
|
balloon,
|
|
|
|
fs,
|
|
|
|
pmem,
|
|
|
|
serial,
|
|
|
|
console,
|
|
|
|
devices,
|
|
|
|
user_devices,
|
|
|
|
vdpa,
|
|
|
|
vsock,
|
2023-06-15 04:02:45 +00:00
|
|
|
pvpanic,
|
2023-01-12 18:50:20 +00:00
|
|
|
#[cfg(target_arch = "x86_64")]
|
|
|
|
sgx_epc,
|
|
|
|
numa,
|
|
|
|
watchdog,
|
|
|
|
#[cfg(feature = "guest_debug")]
|
|
|
|
gdb,
|
|
|
|
platform,
|
|
|
|
tpm,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
fn start_vmm(toplevel: TopLevel) -> Result<Option<String>, Error> {
|
|
|
|
let log_level = match toplevel.verbosity {
|
2021-04-07 14:33:00 +00:00
|
|
|
0 => LevelFilter::Warn,
|
|
|
|
1 => LevelFilter::Info,
|
|
|
|
2 => LevelFilter::Debug,
|
|
|
|
_ => LevelFilter::Trace,
|
|
|
|
};
|
|
|
|
|
2023-01-12 18:50:20 +00:00
|
|
|
let log_file: Box<dyn std::io::Write + Send> = if let Some(ref file) = toplevel.log_file {
|
2021-04-07 14:33:00 +00:00
|
|
|
Box::new(std::fs::File::create(std::path::Path::new(file)).map_err(Error::LogFileCreation)?)
|
|
|
|
} else {
|
|
|
|
Box::new(std::io::stderr())
|
|
|
|
};
|
|
|
|
|
|
|
|
log::set_boxed_logger(Box::new(Logger {
|
|
|
|
output: Mutex::new(log_file),
|
|
|
|
start: std::time::Instant::now(),
|
|
|
|
}))
|
|
|
|
.map(|()| log::set_max_level(log_level))
|
|
|
|
.map_err(Error::LoggerSetup)?;
|
|
|
|
|
2023-01-12 18:50:20 +00:00
|
|
|
let (api_socket_path, api_socket_fd) = if let Some(ref socket_config) = toplevel.api_socket {
|
|
|
|
let mut parser = OptionParser::new();
|
|
|
|
parser.add("path").add("fd");
|
|
|
|
parser.parse(socket_config).unwrap_or_default();
|
|
|
|
|
|
|
|
if let Some(fd) = parser.get("fd") {
|
|
|
|
(
|
|
|
|
None,
|
|
|
|
Some(fd.parse::<RawFd>().map_err(Error::ParsingApiSocket)?),
|
|
|
|
)
|
|
|
|
} else if let Some(path) = parser.get("path") {
|
|
|
|
(Some(path), None)
|
2021-04-09 23:46:55 +00:00
|
|
|
} else {
|
2023-01-12 18:50:20 +00:00
|
|
|
(toplevel.api_socket.as_ref().map(|s| s.to_string()), None)
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
(None, None)
|
|
|
|
};
|
2021-04-09 23:46:55 +00:00
|
|
|
|
2023-04-05 12:22:05 +00:00
|
|
|
#[cfg(feature = "dbus_api")]
|
|
|
|
let dbus_options = match (&toplevel.dbus_name, &toplevel.dbus_path) {
|
|
|
|
(Some(ref name), Some(ref path)) => Ok(Some(DBusApiOptions {
|
|
|
|
service_name: name.to_owned(),
|
|
|
|
object_path: path.to_owned(),
|
|
|
|
system_bus: toplevel.dbus_system_bus,
|
|
|
|
})),
|
|
|
|
(Some(_), None) => Err(Error::MissingDBusObjectPath),
|
|
|
|
(None, Some(_)) => Err(Error::MissingDBusServiceName),
|
|
|
|
(None, None) => Ok(None),
|
|
|
|
}?;
|
|
|
|
|
2023-01-12 18:50:20 +00:00
|
|
|
if let Some(ref monitor_config) = toplevel.event_monitor {
|
2021-04-07 14:33:00 +00:00
|
|
|
let mut parser = OptionParser::new();
|
|
|
|
parser.add("path").add("fd");
|
|
|
|
parser
|
|
|
|
.parse(monitor_config)
|
|
|
|
.map_err(Error::ParsingEventMonitor)?;
|
|
|
|
|
|
|
|
let file = if parser.is_set("fd") {
|
|
|
|
let fd = parser
|
|
|
|
.convert("fd")
|
|
|
|
.map_err(Error::ParsingEventMonitor)?
|
|
|
|
.unwrap();
|
2022-11-16 23:23:07 +00:00
|
|
|
// SAFETY: fd is valid
|
2021-04-07 14:33:00 +00:00
|
|
|
unsafe { File::from_raw_fd(fd) }
|
|
|
|
} else if parser.is_set("path") {
|
|
|
|
std::fs::OpenOptions::new()
|
|
|
|
.write(true)
|
|
|
|
.create(true)
|
|
|
|
.open(parser.get("path").unwrap())
|
|
|
|
.map_err(Error::EventMonitorIo)?
|
|
|
|
} else {
|
|
|
|
return Err(Error::BareEventMonitor);
|
|
|
|
};
|
|
|
|
event_monitor::set_monitor(file).map_err(Error::EventMonitorIo)?;
|
|
|
|
}
|
|
|
|
|
2019-09-25 13:01:49 +00:00
|
|
|
let (api_request_sender, api_request_receiver) = channel();
|
2021-03-25 17:01:21 +00:00
|
|
|
let api_evt = EventFd::new(EFD_NONBLOCK).map_err(Error::CreateApiEventFd)?;
|
2019-09-25 13:01:49 +00:00
|
|
|
|
2023-03-22 21:03:02 +00:00
|
|
|
let api_request_sender_clone = api_request_sender.clone();
|
2023-01-12 18:50:20 +00:00
|
|
|
let seccomp_action = match &toplevel.seccomp as &str {
|
|
|
|
"true" => SeccompAction::Trap,
|
|
|
|
"false" => SeccompAction::Allow,
|
|
|
|
"log" => SeccompAction::Log,
|
|
|
|
val => {
|
|
|
|
// The user providing an invalid value will be rejected
|
|
|
|
panic!("Invalid parameter {val} for \"--seccomp\" flag");
|
2020-03-20 15:11:45 +00:00
|
|
|
}
|
|
|
|
};
|
2021-01-11 18:32:35 +00:00
|
|
|
|
|
|
|
if seccomp_action == SeccompAction::Trap {
|
2022-03-07 10:42:33 +00:00
|
|
|
// SAFETY: We only using signal_hook for managing signals and only execute signal
|
|
|
|
// handler safe functions (writing to stderr) and manipulating signals.
|
|
|
|
unsafe {
|
|
|
|
signal_hook::low_level::register(signal_hook::consts::SIGSYS, || {
|
|
|
|
eprint!(
|
|
|
|
"\n==== Possible seccomp violation ====\n\
|
|
|
|
Try running with `strace -ff` to identify the cause and open an issue: \
|
|
|
|
https://github.com/cloud-hypervisor/cloud-hypervisor/issues/new\n"
|
|
|
|
);
|
|
|
|
signal_hook::low_level::emulate_default_handler(SIGSYS).unwrap();
|
2021-01-11 18:32:35 +00:00
|
|
|
})
|
2022-03-07 10:42:33 +00:00
|
|
|
}
|
2022-12-14 11:41:15 +00:00
|
|
|
.map_err(|e| eprintln!("Error adding SIGSYS signal handler: {e}"))
|
2022-03-07 10:42:33 +00:00
|
|
|
.ok();
|
2021-01-11 18:32:35 +00:00
|
|
|
}
|
|
|
|
|
vmm: ensure signal handlers run on the right thread
Despite setting up a dedicated thread for signal handling, we weren't
making sure that the signals we were listening for there were actually
dispatched to the right thread. While the signal-hook provides an
iterator API, so we can know that we're only processing the signals
coming out of the iterator on our signal handling thread, the actual
signal handling code from signal-hook, which pushes the signals onto
the iterator, can run on any thread. This can lead to seccomp
violations when the signal-hook signal handler does something that
isn't allowed on that thread by our seccomp policy.
To reproduce, resize a terminal running cloud-hypervisor continuously
for a few minutes. Eventually, the kernel will deliver a SIGWINCH to
a thread with a restrictive seccomp policy, and a seccomp violation
will trigger.
As part of this change, it's also necessary to allow rt_sigreturn(2)
on the signal handling thread, so signal handlers are actually allowed
to run on it. The fact that this didn't seem to be needed before
makes me think that signal handlers were almost _never_ actually
running on the signal handling thread.
Signed-off-by: Alyssa Ross <hi@alyssa.is>
2021-09-02 19:16:45 +00:00
|
|
|
// Before we start any threads, mask the signals we'll be
|
|
|
|
// installing handlers for, to make sure they only ever run on the
|
|
|
|
// dedicated signal handling thread we'll start in a bit.
|
2022-07-08 11:55:29 +00:00
|
|
|
for sig in &vmm::vm::Vm::HANDLED_SIGNALS {
|
|
|
|
if let Err(e) = block_signal(*sig) {
|
2022-12-14 11:41:15 +00:00
|
|
|
eprintln!("Error blocking signals: {e}");
|
2022-07-08 11:55:29 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
for sig in &vmm::Vmm::HANDLED_SIGNALS {
|
2021-12-03 21:24:27 +00:00
|
|
|
if let Err(e) = block_signal(*sig) {
|
2022-12-14 11:41:15 +00:00
|
|
|
eprintln!("Error blocking signals: {e}");
|
2021-09-15 14:43:40 +00:00
|
|
|
}
|
vmm: ensure signal handlers run on the right thread
Despite setting up a dedicated thread for signal handling, we weren't
making sure that the signals we were listening for there were actually
dispatched to the right thread. While the signal-hook provides an
iterator API, so we can know that we're only processing the signals
coming out of the iterator on our signal handling thread, the actual
signal handling code from signal-hook, which pushes the signals onto
the iterator, can run on any thread. This can lead to seccomp
violations when the signal-hook signal handler does something that
isn't allowed on that thread by our seccomp policy.
To reproduce, resize a terminal running cloud-hypervisor continuously
for a few minutes. Eventually, the kernel will deliver a SIGWINCH to
a thread with a restrictive seccomp policy, and a seccomp violation
will trigger.
As part of this change, it's also necessary to allow rt_sigreturn(2)
on the signal handling thread, so signal handlers are actually allowed
to run on it. The fact that this didn't seem to be needed before
makes me think that signal handlers were almost _never_ actually
running on the signal handling thread.
Signed-off-by: Alyssa Ross <hi@alyssa.is>
2021-09-02 19:16:45 +00:00
|
|
|
}
|
|
|
|
|
2021-02-17 11:19:39 +00:00
|
|
|
event!("vmm", "starting");
|
|
|
|
|
2020-10-26 16:16:56 +00:00
|
|
|
let hypervisor = hypervisor::new().map_err(Error::CreateHypervisor)?;
|
2022-02-20 03:51:34 +00:00
|
|
|
|
2022-09-27 11:17:40 +00:00
|
|
|
#[cfg(feature = "guest_debug")]
|
2023-01-12 18:50:20 +00:00
|
|
|
let gdb_socket_path = if let Some(ref gdb_config) = toplevel.gdb {
|
2022-02-20 03:51:34 +00:00
|
|
|
let mut parser = OptionParser::new();
|
|
|
|
parser.add("path");
|
|
|
|
parser.parse(gdb_config).map_err(Error::ParsingGdb)?;
|
|
|
|
|
|
|
|
if parser.is_set("path") {
|
|
|
|
Some(std::path::PathBuf::from(parser.get("path").unwrap()))
|
|
|
|
} else {
|
|
|
|
return Err(Error::BareGdb);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
None
|
|
|
|
};
|
2022-09-27 11:17:40 +00:00
|
|
|
#[cfg(feature = "guest_debug")]
|
2022-02-20 03:51:34 +00:00
|
|
|
let debug_evt = EventFd::new(EFD_NONBLOCK).map_err(Error::CreateDebugEventFd)?;
|
2022-09-27 11:17:40 +00:00
|
|
|
#[cfg(feature = "guest_debug")]
|
2022-02-20 03:51:34 +00:00
|
|
|
let vm_debug_evt = EventFd::new(EFD_NONBLOCK).map_err(Error::CreateDebugEventFd)?;
|
|
|
|
|
2023-04-27 12:43:57 +00:00
|
|
|
let exit_evt = EventFd::new(EFD_NONBLOCK).map_err(Error::CreateExitEventFd)?;
|
|
|
|
|
2023-03-25 12:18:13 +00:00
|
|
|
let vmm_thread_handle = vmm::start_vmm_thread(
|
2023-04-07 08:22:08 +00:00
|
|
|
vmm::VmmVersionInfo::new(env!("BUILD_VERSION"), env!("CARGO_PKG_VERSION")),
|
2021-04-09 23:46:55 +00:00
|
|
|
&api_socket_path,
|
|
|
|
api_socket_fd,
|
2023-04-05 12:22:05 +00:00
|
|
|
#[cfg(feature = "dbus_api")]
|
|
|
|
dbus_options,
|
2019-09-26 16:19:00 +00:00
|
|
|
api_evt.try_clone().unwrap(),
|
2023-03-22 21:03:02 +00:00
|
|
|
api_request_sender_clone,
|
2019-09-26 16:19:00 +00:00
|
|
|
api_request_receiver,
|
2022-09-27 11:17:40 +00:00
|
|
|
#[cfg(feature = "guest_debug")]
|
2022-02-20 03:51:34 +00:00
|
|
|
gdb_socket_path,
|
2022-09-27 11:17:40 +00:00
|
|
|
#[cfg(feature = "guest_debug")]
|
2022-02-20 03:51:34 +00:00
|
|
|
debug_evt.try_clone().unwrap(),
|
2022-09-27 11:17:40 +00:00
|
|
|
#[cfg(feature = "guest_debug")]
|
2022-02-20 03:51:34 +00:00
|
|
|
vm_debug_evt.try_clone().unwrap(),
|
2023-04-27 12:43:57 +00:00
|
|
|
exit_evt.try_clone().unwrap(),
|
2020-07-30 21:21:58 +00:00
|
|
|
&seccomp_action,
|
2020-07-14 11:37:06 +00:00
|
|
|
hypervisor,
|
2020-10-26 16:16:56 +00:00
|
|
|
)
|
2021-03-25 17:01:21 +00:00
|
|
|
.map_err(Error::StartVmmThread)?;
|
2019-09-25 13:01:49 +00:00
|
|
|
|
2023-04-27 12:43:57 +00:00
|
|
|
let r: Result<(), Error> = (|| {
|
|
|
|
let payload_present = toplevel.kernel.is_some() || toplevel.firmware.is_some();
|
|
|
|
|
|
|
|
if payload_present {
|
|
|
|
let vm_params = toplevel.to_vm_params();
|
|
|
|
let vm_config = config::VmConfig::parse(vm_params).map_err(Error::ParsingConfig)?;
|
|
|
|
|
|
|
|
// Create and boot the VM based off the VM config we just built.
|
|
|
|
let sender = api_request_sender.clone();
|
|
|
|
vmm::api::vm_create(
|
|
|
|
api_evt.try_clone().unwrap(),
|
|
|
|
api_request_sender,
|
|
|
|
Arc::new(Mutex::new(vm_config)),
|
|
|
|
)
|
|
|
|
.map_err(Error::VmCreate)?;
|
|
|
|
vmm::api::vm_boot(api_evt.try_clone().unwrap(), sender).map_err(Error::VmBoot)?;
|
|
|
|
} else if let Some(restore_params) = toplevel.restore {
|
|
|
|
vmm::api::vm_restore(
|
|
|
|
api_evt.try_clone().unwrap(),
|
|
|
|
api_request_sender,
|
|
|
|
Arc::new(
|
|
|
|
config::RestoreConfig::parse(&restore_params).map_err(Error::ParsingRestore)?,
|
|
|
|
),
|
|
|
|
)
|
|
|
|
.map_err(Error::VmRestore)?;
|
|
|
|
}
|
|
|
|
|
|
|
|
Ok(())
|
|
|
|
})();
|
|
|
|
|
|
|
|
if r.is_err() {
|
|
|
|
if let Err(e) = exit_evt.write(1) {
|
|
|
|
warn!("writing to exit EventFd: {e}");
|
|
|
|
}
|
2019-09-19 07:52:55 +00:00
|
|
|
}
|
2019-09-25 13:01:49 +00:00
|
|
|
|
2023-03-25 12:18:13 +00:00
|
|
|
vmm_thread_handle
|
|
|
|
.thread_handle
|
2020-10-26 16:16:56 +00:00
|
|
|
.join()
|
|
|
|
.map_err(Error::ThreadJoin)?
|
2021-04-09 23:46:55 +00:00
|
|
|
.map_err(Error::VmmThread)?;
|
|
|
|
|
2023-03-25 12:18:13 +00:00
|
|
|
#[cfg(feature = "dbus_api")]
|
2023-04-05 12:22:05 +00:00
|
|
|
if let Some(chs) = vmm_thread_handle.dbus_shutdown_chs {
|
|
|
|
dbus_api_graceful_shutdown(chs);
|
|
|
|
}
|
2023-03-25 12:18:13 +00:00
|
|
|
|
2023-05-22 14:36:07 +00:00
|
|
|
r.map(|_| api_socket_path)
|
2019-02-21 16:04:44 +00:00
|
|
|
}
|
2019-05-23 15:45:13 +00:00
|
|
|
|
2020-01-21 14:59:37 +00:00
|
|
|
fn main() {
|
2023-01-17 12:53:55 +00:00
|
|
|
#[cfg(feature = "dhat-heap")]
|
|
|
|
let _profiler = dhat::Profiler::new_heap();
|
|
|
|
|
2020-05-27 13:37:41 +00:00
|
|
|
// Ensure all created files (.e.g sockets) are only accessible by this user
|
2022-11-16 23:23:07 +00:00
|
|
|
// SAFETY: trivially safe
|
2020-05-27 13:37:41 +00:00
|
|
|
let _ = unsafe { libc::umask(0o077) };
|
|
|
|
|
2023-01-12 18:50:20 +00:00
|
|
|
let toplevel: TopLevel = argh::from_env();
|
|
|
|
|
|
|
|
if toplevel.version {
|
2023-04-07 08:15:23 +00:00
|
|
|
println!("{} {}", env!("CARGO_BIN_NAME"), env!("BUILD_VERSION"));
|
2023-01-12 18:50:20 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
let exit_code = match start_vmm(toplevel) {
|
2021-04-09 23:46:55 +00:00
|
|
|
Ok(path) => {
|
|
|
|
path.map(|s| std::fs::remove_file(s).ok());
|
|
|
|
0
|
|
|
|
}
|
|
|
|
Err(e) => {
|
2022-12-14 11:41:15 +00:00
|
|
|
eprintln!("{e}");
|
2021-04-09 23:46:55 +00:00
|
|
|
1
|
|
|
|
}
|
2021-03-16 18:26:10 +00:00
|
|
|
};
|
|
|
|
|
2023-01-17 12:53:55 +00:00
|
|
|
#[cfg(feature = "dhat-heap")]
|
|
|
|
drop(_profiler);
|
|
|
|
|
2021-03-16 18:26:10 +00:00
|
|
|
std::process::exit(exit_code);
|
2020-01-21 14:59:37 +00:00
|
|
|
}
|
|
|
|
|
2019-12-12 17:35:33 +00:00
|
|
|
#[cfg(test)]
|
|
|
|
mod unit_tests {
|
2020-03-04 02:16:07 +00:00
|
|
|
use crate::config::HotplugMethod;
|
2023-01-12 18:50:20 +00:00
|
|
|
use crate::TopLevel;
|
2019-12-12 17:35:33 +00:00
|
|
|
use std::path::PathBuf;
|
|
|
|
use vmm::config::{
|
2022-10-06 12:45:37 +00:00
|
|
|
ConsoleConfig, ConsoleOutputMode, CpuFeatures, CpusConfig, MemoryConfig, PayloadConfig,
|
2023-01-12 18:50:20 +00:00
|
|
|
RngConfig, VmConfig,
|
2019-12-12 17:35:33 +00:00
|
|
|
};
|
|
|
|
|
2023-01-12 18:50:20 +00:00
|
|
|
// Taken from argh
|
|
|
|
fn cmd<'a>(default: &'a str, path: &'a str) -> &'a str {
|
|
|
|
std::path::Path::new(path)
|
|
|
|
.file_name()
|
|
|
|
.and_then(|s| s.to_str())
|
|
|
|
.unwrap_or(default)
|
|
|
|
}
|
|
|
|
|
|
|
|
// Some code taken from argh since it does not provide a helper to parse arbitrary strings
|
2019-12-12 17:35:33 +00:00
|
|
|
fn get_vm_config_from_vec(args: &[&str]) -> VmConfig {
|
2023-01-12 18:50:20 +00:00
|
|
|
let strings: Vec<String> = args.iter().map(|x| x.to_string()).collect();
|
|
|
|
let cmd = cmd(&strings[0], &strings[0]);
|
|
|
|
let strs: Vec<&str> = strings.iter().map(|s| s.as_str()).collect();
|
|
|
|
let toplevel = <TopLevel as argh::FromArgs>::from_args(&[cmd], &strs[1..]).unwrap_or_else(
|
|
|
|
|early_exit| {
|
|
|
|
std::process::exit(match early_exit.status {
|
|
|
|
Ok(()) => {
|
|
|
|
println!("{}", early_exit.output);
|
|
|
|
0
|
|
|
|
}
|
|
|
|
Err(()) => {
|
|
|
|
eprintln!(
|
|
|
|
"{}\nRun {} --help for more information.",
|
|
|
|
early_exit.output, cmd
|
|
|
|
);
|
|
|
|
1
|
|
|
|
}
|
|
|
|
})
|
|
|
|
},
|
|
|
|
);
|
2019-12-12 17:35:33 +00:00
|
|
|
|
2023-01-12 18:50:20 +00:00
|
|
|
let vm_params = toplevel.to_vm_params();
|
2019-12-12 17:35:33 +00:00
|
|
|
|
|
|
|
VmConfig::parse(vm_params).unwrap()
|
|
|
|
}
|
|
|
|
|
|
|
|
fn compare_vm_config_cli_vs_json(
|
|
|
|
cli: &[&str],
|
|
|
|
openapi: &str,
|
|
|
|
equal: bool,
|
|
|
|
) -> (VmConfig, VmConfig) {
|
|
|
|
let cli_vm_config = get_vm_config_from_vec(cli);
|
|
|
|
let openapi_vm_config: VmConfig = serde_json::from_str(openapi).unwrap();
|
|
|
|
|
2022-01-05 10:45:46 +00:00
|
|
|
if equal {
|
|
|
|
assert_eq!(cli_vm_config, openapi_vm_config);
|
|
|
|
} else {
|
|
|
|
assert_ne!(cli_vm_config, openapi_vm_config);
|
|
|
|
}
|
2019-12-12 17:35:33 +00:00
|
|
|
|
|
|
|
(cli_vm_config, openapi_vm_config)
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_valid_vm_config_default() {
|
2020-04-06 16:00:38 +00:00
|
|
|
let cli = vec!["cloud-hypervisor", "--kernel", "/path/to/kernel"];
|
2022-08-10 10:24:31 +00:00
|
|
|
let openapi = r#"{ "payload": {"kernel": "/path/to/kernel"} }"#;
|
2019-12-12 17:35:33 +00:00
|
|
|
|
|
|
|
// First we check we get identical VmConfig structures.
|
|
|
|
let (result_vm_config, _) = compare_vm_config_cli_vs_json(&cli, openapi, true);
|
|
|
|
|
|
|
|
// As a second step, we validate all the default values.
|
2022-01-05 10:45:46 +00:00
|
|
|
let expected_vm_config = VmConfig {
|
|
|
|
cpus: CpusConfig {
|
|
|
|
boot_vcpus: 1,
|
|
|
|
max_vcpus: 1,
|
|
|
|
topology: None,
|
|
|
|
kvm_hyperv: false,
|
|
|
|
max_phys_bits: 46,
|
|
|
|
affinity: None,
|
2022-03-01 18:25:30 +00:00
|
|
|
features: CpuFeatures::default(),
|
2022-01-05 10:45:46 +00:00
|
|
|
},
|
|
|
|
memory: MemoryConfig {
|
|
|
|
size: 536_870_912,
|
|
|
|
mergeable: false,
|
|
|
|
hotplug_method: HotplugMethod::Acpi,
|
|
|
|
hotplug_size: None,
|
|
|
|
hotplugged_size: None,
|
|
|
|
shared: false,
|
|
|
|
hugepages: false,
|
|
|
|
hugepage_size: None,
|
|
|
|
prefault: false,
|
|
|
|
zones: None,
|
2022-11-07 16:25:36 +00:00
|
|
|
thp: true,
|
2022-01-05 10:45:46 +00:00
|
|
|
},
|
2022-08-10 10:24:31 +00:00
|
|
|
payload: Some(PayloadConfig {
|
|
|
|
kernel: Some(PathBuf::from("/path/to/kernel")),
|
|
|
|
..Default::default()
|
|
|
|
}),
|
2022-01-05 10:45:46 +00:00
|
|
|
disks: None,
|
|
|
|
net: None,
|
|
|
|
rng: RngConfig {
|
|
|
|
src: PathBuf::from("/dev/urandom"),
|
|
|
|
iommu: false,
|
|
|
|
},
|
|
|
|
balloon: None,
|
|
|
|
fs: None,
|
|
|
|
pmem: None,
|
|
|
|
serial: ConsoleConfig {
|
|
|
|
file: None,
|
|
|
|
mode: ConsoleOutputMode::Null,
|
2019-12-12 17:35:33 +00:00
|
|
|
iommu: false,
|
2022-01-05 10:45:46 +00:00
|
|
|
},
|
|
|
|
console: ConsoleConfig {
|
|
|
|
file: None,
|
|
|
|
mode: ConsoleOutputMode::Tty,
|
|
|
|
iommu: false,
|
|
|
|
},
|
|
|
|
devices: None,
|
|
|
|
user_devices: None,
|
2022-03-11 09:57:42 +00:00
|
|
|
vdpa: None,
|
2022-01-05 10:45:46 +00:00
|
|
|
vsock: None,
|
2023-06-15 04:02:45 +00:00
|
|
|
pvpanic: false,
|
2022-01-05 10:45:46 +00:00
|
|
|
iommu: false,
|
|
|
|
#[cfg(target_arch = "x86_64")]
|
|
|
|
sgx_epc: None,
|
|
|
|
numa: None,
|
|
|
|
watchdog: false,
|
2022-09-27 11:17:40 +00:00
|
|
|
#[cfg(feature = "guest_debug")]
|
2022-02-20 03:51:34 +00:00
|
|
|
gdb: false,
|
2022-01-05 10:45:46 +00:00
|
|
|
platform: None,
|
2022-09-15 04:11:59 +00:00
|
|
|
tpm: None,
|
2023-04-14 23:44:41 +00:00
|
|
|
preserved_fds: None,
|
2022-01-05 10:45:46 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
assert_eq!(expected_vm_config, result_vm_config);
|
2019-12-12 17:35:33 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_valid_vm_config_cpus() {
|
2023-07-12 04:25:25 +00:00
|
|
|
[
|
2019-12-12 17:35:33 +00:00
|
|
|
(
|
2020-04-06 16:00:38 +00:00
|
|
|
vec![
|
|
|
|
"cloud-hypervisor",
|
|
|
|
"--kernel",
|
|
|
|
"/path/to/kernel",
|
|
|
|
"--cpus",
|
|
|
|
"boot=1",
|
|
|
|
],
|
2019-12-12 17:35:33 +00:00
|
|
|
r#"{
|
2022-08-10 10:24:31 +00:00
|
|
|
"payload": {"kernel": "/path/to/kernel"},
|
2019-12-12 17:35:33 +00:00
|
|
|
"cpus": {"boot_vcpus": 1, "max_vcpus": 1}
|
|
|
|
}"#,
|
|
|
|
true,
|
|
|
|
),
|
|
|
|
(
|
2020-04-06 16:00:38 +00:00
|
|
|
vec![
|
|
|
|
"cloud-hypervisor",
|
|
|
|
"--kernel",
|
|
|
|
"/path/to/kernel",
|
|
|
|
"--cpus",
|
|
|
|
"boot=1,max=3",
|
|
|
|
],
|
2019-12-12 17:35:33 +00:00
|
|
|
r#"{
|
2022-08-10 10:24:31 +00:00
|
|
|
"payload": {"kernel": "/path/to/kernel"},
|
2019-12-12 17:35:33 +00:00
|
|
|
"cpus": {"boot_vcpus": 1, "max_vcpus": 3}
|
|
|
|
}"#,
|
|
|
|
true,
|
|
|
|
),
|
|
|
|
(
|
2020-04-06 16:00:38 +00:00
|
|
|
vec![
|
|
|
|
"cloud-hypervisor",
|
|
|
|
"--kernel",
|
|
|
|
"/path/to/kernel",
|
|
|
|
"--cpus",
|
|
|
|
"boot=2,max=4",
|
|
|
|
],
|
2019-12-12 17:35:33 +00:00
|
|
|
r#"{
|
2022-08-10 10:24:31 +00:00
|
|
|
"payload": {"kernel": "/path/to/kernel"},
|
2019-12-12 17:35:33 +00:00
|
|
|
"cpus": {"boot_vcpus": 1, "max_vcpus": 3}
|
|
|
|
}"#,
|
|
|
|
false,
|
|
|
|
),
|
|
|
|
]
|
|
|
|
.iter()
|
|
|
|
.for_each(|(cli, openapi, equal)| {
|
|
|
|
compare_vm_config_cli_vs_json(cli, openapi, *equal);
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_valid_vm_config_memory() {
|
|
|
|
vec![
|
|
|
|
(
|
2020-04-06 16:00:38 +00:00
|
|
|
vec!["cloud-hypervisor", "--kernel", "/path/to/kernel", "--memory", "size=1073741824"],
|
2019-12-12 17:35:33 +00:00
|
|
|
r#"{
|
2022-08-10 10:24:31 +00:00
|
|
|
"payload": {"kernel": "/path/to/kernel"},
|
2019-12-12 17:35:33 +00:00
|
|
|
"memory": {"size": 1073741824}
|
|
|
|
}"#,
|
|
|
|
true,
|
|
|
|
),
|
|
|
|
(
|
2020-04-06 16:00:38 +00:00
|
|
|
vec!["cloud-hypervisor", "--kernel", "/path/to/kernel", "--memory", "size=1G"],
|
2019-12-12 17:35:33 +00:00
|
|
|
r#"{
|
2022-08-10 10:24:31 +00:00
|
|
|
"payload": {"kernel": "/path/to/kernel"},
|
2019-12-12 17:35:33 +00:00
|
|
|
"memory": {"size": 1073741824}
|
|
|
|
}"#,
|
|
|
|
true,
|
|
|
|
),
|
|
|
|
(
|
2020-04-06 16:00:38 +00:00
|
|
|
vec!["cloud-hypervisor", "--kernel", "/path/to/kernel", "--memory", "size=1G,mergeable=on"],
|
2019-12-12 17:35:33 +00:00
|
|
|
r#"{
|
2022-08-10 10:24:31 +00:00
|
|
|
"payload": {"kernel": "/path/to/kernel"},
|
2019-12-12 17:35:33 +00:00
|
|
|
"memory": {"size": 1073741824, "mergeable": true}
|
|
|
|
}"#,
|
|
|
|
true,
|
|
|
|
),
|
|
|
|
(
|
2020-04-06 16:00:38 +00:00
|
|
|
vec!["cloud-hypervisor", "--kernel", "/path/to/kernel", "--memory", "size=1G,mergeable=off"],
|
2019-12-12 17:35:33 +00:00
|
|
|
r#"{
|
2022-08-10 10:24:31 +00:00
|
|
|
"payload": {"kernel": "/path/to/kernel"},
|
2019-12-12 17:35:33 +00:00
|
|
|
"memory": {"size": 1073741824, "mergeable": false}
|
|
|
|
}"#,
|
|
|
|
true,
|
|
|
|
),
|
|
|
|
(
|
2020-04-06 16:00:38 +00:00
|
|
|
vec!["cloud-hypervisor", "--kernel", "/path/to/kernel", "--memory", "size=1G,mergeable=on"],
|
2019-12-12 17:35:33 +00:00
|
|
|
r#"{
|
2022-08-10 10:24:31 +00:00
|
|
|
"payload": {"kernel": "/path/to/kernel"},
|
2019-12-12 17:35:33 +00:00
|
|
|
"memory": {"size": 1073741824, "mergeable": false}
|
|
|
|
}"#,
|
|
|
|
false,
|
|
|
|
),
|
2020-03-04 06:39:26 +00:00
|
|
|
(
|
2020-04-06 16:00:38 +00:00
|
|
|
vec!["cloud-hypervisor", "--kernel", "/path/to/kernel", "--memory", "size=1G,hotplug_size=1G"],
|
2020-03-04 06:39:26 +00:00
|
|
|
r#"{
|
2022-08-10 10:24:31 +00:00
|
|
|
"payload": {"kernel": "/path/to/kernel"},
|
2020-03-04 06:39:26 +00:00
|
|
|
"memory": {"size": 1073741824, "hotplug_method": "Acpi", "hotplug_size": 1073741824}
|
|
|
|
}"#,
|
|
|
|
true,
|
|
|
|
),
|
|
|
|
(
|
2020-04-06 16:00:38 +00:00
|
|
|
vec!["cloud-hypervisor", "--kernel", "/path/to/kernel", "--memory", "size=1G,hotplug_method=virtio-mem,hotplug_size=1G"],
|
2020-03-04 06:39:26 +00:00
|
|
|
r#"{
|
2022-08-10 10:24:31 +00:00
|
|
|
"payload": {"kernel": "/path/to/kernel"},
|
2020-03-04 06:39:26 +00:00
|
|
|
"memory": {"size": 1073741824, "hotplug_method": "VirtioMem", "hotplug_size": 1073741824}
|
|
|
|
}"#,
|
|
|
|
true,
|
|
|
|
),
|
2019-12-12 17:35:33 +00:00
|
|
|
]
|
|
|
|
.iter()
|
|
|
|
.for_each(|(cli, openapi, equal)| {
|
|
|
|
compare_vm_config_cli_vs_json(cli, openapi, *equal);
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_valid_vm_config_kernel() {
|
2023-07-12 04:25:25 +00:00
|
|
|
[(
|
2019-12-12 17:35:33 +00:00
|
|
|
vec!["cloud-hypervisor", "--kernel", "/path/to/kernel"],
|
|
|
|
r#"{
|
2022-08-10 10:24:31 +00:00
|
|
|
"payload": {"kernel": "/path/to/kernel"}
|
2019-12-12 17:35:33 +00:00
|
|
|
}"#,
|
|
|
|
true,
|
|
|
|
)]
|
|
|
|
.iter()
|
|
|
|
.for_each(|(cli, openapi, equal)| {
|
|
|
|
compare_vm_config_cli_vs_json(cli, openapi, *equal);
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_valid_vm_config_cmdline() {
|
2023-07-12 04:25:25 +00:00
|
|
|
[(
|
2020-04-06 16:00:38 +00:00
|
|
|
vec![
|
|
|
|
"cloud-hypervisor",
|
|
|
|
"--kernel",
|
|
|
|
"/path/to/kernel",
|
|
|
|
"--cmdline",
|
|
|
|
"arg1=foo arg2=bar",
|
|
|
|
],
|
2019-12-12 17:35:33 +00:00
|
|
|
r#"{
|
2022-08-10 10:24:31 +00:00
|
|
|
"payload": {"kernel": "/path/to/kernel", "cmdline": "arg1=foo arg2=bar"}
|
2019-12-12 17:35:33 +00:00
|
|
|
}"#,
|
|
|
|
true,
|
|
|
|
)]
|
|
|
|
.iter()
|
|
|
|
.for_each(|(cli, openapi, equal)| {
|
|
|
|
compare_vm_config_cli_vs_json(cli, openapi, *equal);
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_valid_vm_config_disks() {
|
2023-07-12 04:25:25 +00:00
|
|
|
[
|
2019-12-12 17:35:33 +00:00
|
|
|
(
|
|
|
|
vec![
|
|
|
|
"cloud-hypervisor",
|
2020-04-06 16:00:38 +00:00
|
|
|
"--kernel",
|
|
|
|
"/path/to/kernel",
|
2019-12-12 17:35:33 +00:00
|
|
|
"--disk",
|
|
|
|
"path=/path/to/disk/1",
|
2023-01-12 18:50:20 +00:00
|
|
|
"--disk",
|
2019-12-12 17:35:33 +00:00
|
|
|
"path=/path/to/disk/2",
|
|
|
|
],
|
|
|
|
r#"{
|
2022-08-10 10:24:31 +00:00
|
|
|
"payload": {"kernel": "/path/to/kernel"},
|
2019-12-12 17:35:33 +00:00
|
|
|
"disks": [
|
|
|
|
{"path": "/path/to/disk/1"},
|
|
|
|
{"path": "/path/to/disk/2"}
|
|
|
|
]
|
|
|
|
}"#,
|
|
|
|
true,
|
|
|
|
),
|
|
|
|
(
|
|
|
|
vec![
|
|
|
|
"cloud-hypervisor",
|
2020-04-06 16:00:38 +00:00
|
|
|
"--kernel",
|
|
|
|
"/path/to/kernel",
|
2019-12-12 17:35:33 +00:00
|
|
|
"--disk",
|
|
|
|
"path=/path/to/disk/1",
|
2023-01-12 18:50:20 +00:00
|
|
|
"--disk",
|
2019-12-12 17:35:33 +00:00
|
|
|
"path=/path/to/disk/2",
|
|
|
|
],
|
|
|
|
r#"{
|
2022-08-10 10:24:31 +00:00
|
|
|
"payload": {"kernel": "/path/to/kernel"},
|
2019-12-12 17:35:33 +00:00
|
|
|
"disks": [
|
|
|
|
{"path": "/path/to/disk/1"}
|
|
|
|
]
|
|
|
|
}"#,
|
|
|
|
false,
|
|
|
|
),
|
2020-01-28 10:38:42 +00:00
|
|
|
(
|
|
|
|
vec![
|
|
|
|
"cloud-hypervisor",
|
2020-04-06 16:00:38 +00:00
|
|
|
"--kernel",
|
|
|
|
"/path/to/kernel",
|
2020-04-24 13:46:48 +00:00
|
|
|
"--memory",
|
|
|
|
"shared=true",
|
2020-01-28 10:38:42 +00:00
|
|
|
"--disk",
|
2020-06-04 19:19:24 +00:00
|
|
|
"vhost_user=true,socket=/tmp/sock1",
|
2020-01-28 10:38:42 +00:00
|
|
|
],
|
|
|
|
r#"{
|
2022-08-10 10:24:31 +00:00
|
|
|
"payload": {"kernel": "/path/to/kernel"},
|
2020-04-24 13:46:48 +00:00
|
|
|
"memory" : { "shared": true, "size": 536870912 },
|
2020-01-28 10:38:42 +00:00
|
|
|
"disks": [
|
2020-11-06 09:44:17 +00:00
|
|
|
{"vhost_user":true, "vhost_socket":"/tmp/sock1"}
|
2020-01-28 10:38:42 +00:00
|
|
|
]
|
|
|
|
}"#,
|
|
|
|
true,
|
|
|
|
),
|
|
|
|
(
|
|
|
|
vec![
|
|
|
|
"cloud-hypervisor",
|
2020-04-06 16:00:38 +00:00
|
|
|
"--kernel",
|
|
|
|
"/path/to/kernel",
|
2020-04-24 13:46:48 +00:00
|
|
|
"--memory",
|
|
|
|
"shared=true",
|
2020-01-28 10:38:42 +00:00
|
|
|
"--disk",
|
2020-06-04 19:19:24 +00:00
|
|
|
"vhost_user=true,socket=/tmp/sock1",
|
2020-01-28 10:38:42 +00:00
|
|
|
],
|
|
|
|
r#"{
|
2022-08-10 10:24:31 +00:00
|
|
|
"payload": {"kernel": "/path/to/kernel"},
|
2020-04-24 13:46:48 +00:00
|
|
|
"memory" : { "shared": true, "size": 536870912 },
|
2020-01-28 10:38:42 +00:00
|
|
|
"disks": [
|
2020-11-06 09:44:17 +00:00
|
|
|
{"vhost_user":true, "vhost_socket":"/tmp/sock1"}
|
2020-01-28 10:38:42 +00:00
|
|
|
]
|
|
|
|
}"#,
|
|
|
|
true,
|
|
|
|
),
|
2019-12-12 17:35:33 +00:00
|
|
|
]
|
|
|
|
.iter()
|
|
|
|
.for_each(|(cli, openapi, equal)| {
|
|
|
|
compare_vm_config_cli_vs_json(cli, openapi, *equal);
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_valid_vm_config_net() {
|
|
|
|
vec![
|
|
|
|
// This test is expected to fail because the default MAC address is
|
|
|
|
// randomly generated. There's no way we can have twice the same
|
|
|
|
// default value.
|
|
|
|
(
|
2020-04-06 16:00:38 +00:00
|
|
|
vec!["cloud-hypervisor", "--kernel", "/path/to/kernel", "--net", "mac="],
|
2019-12-12 17:35:33 +00:00
|
|
|
r#"{
|
2022-08-10 10:24:31 +00:00
|
|
|
"payload": {"kernel": "/path/to/kernel"},
|
2019-12-12 17:35:33 +00:00
|
|
|
"net": []
|
|
|
|
}"#,
|
|
|
|
false,
|
|
|
|
),
|
|
|
|
(
|
2020-05-15 09:00:38 +00:00
|
|
|
vec!["cloud-hypervisor", "--kernel", "/path/to/kernel", "--net", "mac=12:34:56:78:90:ab,host_mac=34:56:78:90:ab:cd"],
|
2019-12-12 17:35:33 +00:00
|
|
|
r#"{
|
2022-08-10 10:24:31 +00:00
|
|
|
"payload": {"kernel": "/path/to/kernel"},
|
2019-12-12 17:35:33 +00:00
|
|
|
"net": [
|
2020-05-15 09:00:38 +00:00
|
|
|
{"mac": "12:34:56:78:90:ab", "host_mac": "34:56:78:90:ab:cd"}
|
2019-12-12 17:35:33 +00:00
|
|
|
]
|
|
|
|
}"#,
|
|
|
|
true,
|
|
|
|
),
|
|
|
|
(
|
|
|
|
vec![
|
2020-04-06 16:00:38 +00:00
|
|
|
"cloud-hypervisor", "--kernel", "/path/to/kernel",
|
2019-12-12 17:35:33 +00:00
|
|
|
"--net",
|
2020-05-15 09:00:38 +00:00
|
|
|
"mac=12:34:56:78:90:ab,host_mac=34:56:78:90:ab:cd,tap=tap0",
|
2019-12-12 17:35:33 +00:00
|
|
|
],
|
|
|
|
r#"{
|
2022-08-10 10:24:31 +00:00
|
|
|
"payload": {"kernel": "/path/to/kernel"},
|
2019-12-12 17:35:33 +00:00
|
|
|
"net": [
|
2020-05-15 09:00:38 +00:00
|
|
|
{"mac": "12:34:56:78:90:ab", "host_mac": "34:56:78:90:ab:cd", "tap": "tap0"}
|
2019-12-12 17:35:33 +00:00
|
|
|
]
|
|
|
|
}"#,
|
|
|
|
true,
|
|
|
|
),
|
|
|
|
(
|
|
|
|
vec![
|
2020-04-06 16:00:38 +00:00
|
|
|
"cloud-hypervisor", "--kernel", "/path/to/kernel",
|
2019-12-12 17:35:33 +00:00
|
|
|
"--net",
|
2020-05-15 09:00:38 +00:00
|
|
|
"mac=12:34:56:78:90:ab,host_mac=34:56:78:90:ab:cd,tap=tap0,ip=1.2.3.4",
|
2019-12-12 17:35:33 +00:00
|
|
|
],
|
|
|
|
r#"{
|
2022-08-10 10:24:31 +00:00
|
|
|
"payload": {"kernel": "/path/to/kernel"},
|
2019-12-12 17:35:33 +00:00
|
|
|
"net": [
|
2020-05-15 09:00:38 +00:00
|
|
|
{"mac": "12:34:56:78:90:ab", "host_mac": "34:56:78:90:ab:cd", "tap": "tap0", "ip": "1.2.3.4"}
|
2019-12-12 17:35:33 +00:00
|
|
|
]
|
|
|
|
}"#,
|
|
|
|
true,
|
|
|
|
),
|
|
|
|
(
|
|
|
|
vec![
|
2020-04-06 16:00:38 +00:00
|
|
|
"cloud-hypervisor", "--kernel", "/path/to/kernel",
|
2019-12-12 17:35:33 +00:00
|
|
|
"--net",
|
2020-05-15 09:00:38 +00:00
|
|
|
"mac=12:34:56:78:90:ab,host_mac=34:56:78:90:ab:cd,tap=tap0,ip=1.2.3.4,mask=5.6.7.8",
|
2019-12-12 17:35:33 +00:00
|
|
|
],
|
|
|
|
r#"{
|
2022-08-10 10:24:31 +00:00
|
|
|
"payload": {"kernel": "/path/to/kernel"},
|
2019-12-12 17:35:33 +00:00
|
|
|
"net": [
|
2020-05-15 09:00:38 +00:00
|
|
|
{"mac": "12:34:56:78:90:ab", "host_mac": "34:56:78:90:ab:cd", "tap": "tap0", "ip": "1.2.3.4", "mask": "5.6.7.8"}
|
2019-12-12 17:35:33 +00:00
|
|
|
]
|
|
|
|
}"#,
|
|
|
|
true,
|
|
|
|
),
|
|
|
|
(
|
|
|
|
vec![
|
2020-04-06 16:00:38 +00:00
|
|
|
"cloud-hypervisor", "--kernel", "/path/to/kernel",
|
2021-04-29 11:10:44 +00:00
|
|
|
"--cpus", "boot=2",
|
2019-12-12 17:35:33 +00:00
|
|
|
"--net",
|
2020-05-15 09:00:38 +00:00
|
|
|
"mac=12:34:56:78:90:ab,host_mac=34:56:78:90:ab:cd,tap=tap0,ip=1.2.3.4,mask=5.6.7.8,num_queues=4",
|
2019-12-12 17:35:33 +00:00
|
|
|
],
|
|
|
|
r#"{
|
2022-08-10 10:24:31 +00:00
|
|
|
"payload": {"kernel": "/path/to/kernel"},
|
2021-04-29 11:10:44 +00:00
|
|
|
"cpus": {"boot_vcpus": 2, "max_vcpus": 2},
|
2019-12-12 17:35:33 +00:00
|
|
|
"net": [
|
2020-05-15 09:00:38 +00:00
|
|
|
{"mac": "12:34:56:78:90:ab", "host_mac": "34:56:78:90:ab:cd", "tap": "tap0", "ip": "1.2.3.4", "mask": "5.6.7.8", "num_queues": 4}
|
2020-01-09 08:32:41 +00:00
|
|
|
]
|
|
|
|
}"#,
|
|
|
|
true,
|
|
|
|
),
|
|
|
|
(
|
|
|
|
vec![
|
2020-04-06 16:00:38 +00:00
|
|
|
"cloud-hypervisor", "--kernel", "/path/to/kernel",
|
2021-04-29 11:10:44 +00:00
|
|
|
"--cpus", "boot=2",
|
2020-01-09 08:32:41 +00:00
|
|
|
"--net",
|
2020-05-15 09:00:38 +00:00
|
|
|
"mac=12:34:56:78:90:ab,host_mac=34:56:78:90:ab:cd,tap=tap0,ip=1.2.3.4,mask=5.6.7.8,num_queues=4,queue_size=128",
|
2020-01-09 08:32:41 +00:00
|
|
|
],
|
|
|
|
r#"{
|
2022-08-10 10:24:31 +00:00
|
|
|
"payload": {"kernel": "/path/to/kernel"},
|
2021-04-29 11:10:44 +00:00
|
|
|
"cpus": {"boot_vcpus": 2, "max_vcpus": 2},
|
2020-01-09 08:32:41 +00:00
|
|
|
"net": [
|
2020-05-15 09:00:38 +00:00
|
|
|
{"mac": "12:34:56:78:90:ab", "host_mac": "34:56:78:90:ab:cd", "tap": "tap0", "ip": "1.2.3.4", "mask": "5.6.7.8", "num_queues": 4, "queue_size": 128}
|
2020-01-09 08:32:41 +00:00
|
|
|
]
|
|
|
|
}"#,
|
|
|
|
true,
|
|
|
|
),
|
|
|
|
(
|
|
|
|
vec![
|
2020-04-06 16:00:38 +00:00
|
|
|
"cloud-hypervisor", "--kernel", "/path/to/kernel",
|
2020-01-09 08:32:41 +00:00
|
|
|
"--net",
|
2020-05-15 09:00:38 +00:00
|
|
|
"mac=12:34:56:78:90:ab,host_mac=34:56:78:90:ab:cd,tap=tap0,ip=1.2.3.4,mask=5.6.7.8,num_queues=2,queue_size=256",
|
2020-01-09 08:32:41 +00:00
|
|
|
],
|
|
|
|
r#"{
|
2022-08-10 10:24:31 +00:00
|
|
|
"payload": {"kernel": "/path/to/kernel"},
|
2020-01-09 08:32:41 +00:00
|
|
|
"net": [
|
2020-05-15 09:00:38 +00:00
|
|
|
{"mac": "12:34:56:78:90:ab", "host_mac": "34:56:78:90:ab:cd", "tap": "tap0", "ip": "1.2.3.4", "mask": "5.6.7.8"}
|
2020-01-09 08:32:41 +00:00
|
|
|
]
|
|
|
|
}"#,
|
|
|
|
true,
|
|
|
|
),
|
|
|
|
(
|
|
|
|
vec![
|
2020-04-06 16:00:38 +00:00
|
|
|
"cloud-hypervisor", "--kernel", "/path/to/kernel",
|
2020-01-09 08:32:41 +00:00
|
|
|
"--net",
|
2020-05-15 09:00:38 +00:00
|
|
|
"mac=12:34:56:78:90:ab,host_mac=34:56:78:90:ab:cd,tap=tap0,ip=1.2.3.4,mask=5.6.7.8",
|
2020-01-09 08:32:41 +00:00
|
|
|
],
|
|
|
|
r#"{
|
2022-08-10 10:24:31 +00:00
|
|
|
"payload": {"kernel": "/path/to/kernel"},
|
2020-01-09 08:32:41 +00:00
|
|
|
"net": [
|
2020-05-15 09:00:38 +00:00
|
|
|
{"mac": "12:34:56:78:90:ab", "host_mac": "34:56:78:90:ab:cd", "tap": "tap0", "ip": "1.2.3.4", "mask": "5.6.7.8", "num_queues": 2, "queue_size": 256}
|
2020-01-09 08:32:41 +00:00
|
|
|
]
|
|
|
|
}"#,
|
|
|
|
true,
|
|
|
|
),
|
2020-06-12 00:58:50 +00:00
|
|
|
#[cfg(target_arch = "x86_64")]
|
2020-01-09 08:32:41 +00:00
|
|
|
(
|
|
|
|
vec![
|
2020-04-06 16:00:38 +00:00
|
|
|
"cloud-hypervisor", "--kernel", "/path/to/kernel",
|
2020-01-09 08:32:41 +00:00
|
|
|
"--net",
|
2020-05-15 09:00:38 +00:00
|
|
|
"mac=12:34:56:78:90:ab,host_mac=34:56:78:90:ab:cd,tap=tap0,ip=1.2.3.4,mask=5.6.7.8,num_queues=2,queue_size=256,iommu=on",
|
2020-01-09 08:32:41 +00:00
|
|
|
],
|
|
|
|
r#"{
|
2022-08-10 10:24:31 +00:00
|
|
|
"payload": {"kernel": "/path/to/kernel"},
|
2020-01-09 08:32:41 +00:00
|
|
|
"net": [
|
2020-05-15 09:00:38 +00:00
|
|
|
{"mac": "12:34:56:78:90:ab", "host_mac": "34:56:78:90:ab:cd", "tap": "tap0", "ip": "1.2.3.4", "mask": "5.6.7.8", "num_queues": 2, "queue_size": 256, "iommu": true}
|
2019-12-12 17:35:33 +00:00
|
|
|
]
|
|
|
|
}"#,
|
|
|
|
false,
|
|
|
|
),
|
2020-06-12 00:58:50 +00:00
|
|
|
#[cfg(target_arch = "x86_64")]
|
2019-12-12 17:35:33 +00:00
|
|
|
(
|
|
|
|
vec![
|
2020-04-06 16:00:38 +00:00
|
|
|
"cloud-hypervisor", "--kernel", "/path/to/kernel",
|
2019-12-12 17:35:33 +00:00
|
|
|
"--net",
|
2020-05-15 09:00:38 +00:00
|
|
|
"mac=12:34:56:78:90:ab,host_mac=34:56:78:90:ab:cd,tap=tap0,ip=1.2.3.4,mask=5.6.7.8,num_queues=2,queue_size=256,iommu=on",
|
2019-12-12 17:35:33 +00:00
|
|
|
],
|
|
|
|
r#"{
|
2022-08-10 10:24:31 +00:00
|
|
|
"payload": {"kernel": "/path/to/kernel"},
|
2019-12-12 17:35:33 +00:00
|
|
|
"net": [
|
2020-05-15 09:00:38 +00:00
|
|
|
{"mac": "12:34:56:78:90:ab", "host_mac": "34:56:78:90:ab:cd", "tap": "tap0", "ip": "1.2.3.4", "mask": "5.6.7.8", "num_queues": 2, "queue_size": 256, "iommu": true}
|
2019-12-12 17:35:33 +00:00
|
|
|
],
|
|
|
|
"iommu": true
|
|
|
|
}"#,
|
|
|
|
true,
|
|
|
|
),
|
|
|
|
(
|
|
|
|
vec![
|
2020-04-06 16:00:38 +00:00
|
|
|
"cloud-hypervisor", "--kernel", "/path/to/kernel",
|
2019-12-12 17:35:33 +00:00
|
|
|
"--net",
|
2020-05-15 09:00:38 +00:00
|
|
|
"mac=12:34:56:78:90:ab,host_mac=34:56:78:90:ab:cd,tap=tap0,ip=1.2.3.4,mask=5.6.7.8,num_queues=2,queue_size=256,iommu=off",
|
2019-12-12 17:35:33 +00:00
|
|
|
],
|
|
|
|
r#"{
|
2022-08-10 10:24:31 +00:00
|
|
|
"payload": {"kernel": "/path/to/kernel"},
|
2019-12-12 17:35:33 +00:00
|
|
|
"net": [
|
2020-05-15 09:00:38 +00:00
|
|
|
{"mac": "12:34:56:78:90:ab", "host_mac": "34:56:78:90:ab:cd", "tap": "tap0", "ip": "1.2.3.4", "mask": "5.6.7.8", "num_queues": 2, "queue_size": 256, "iommu": false}
|
2019-12-12 17:35:33 +00:00
|
|
|
]
|
|
|
|
}"#,
|
|
|
|
true,
|
|
|
|
),
|
2020-01-28 10:38:42 +00:00
|
|
|
(
|
2020-06-04 19:19:24 +00:00
|
|
|
vec!["cloud-hypervisor", "--kernel", "/path/to/kernel", "--memory", "shared=true", "--net", "mac=12:34:56:78:90:ab,host_mac=34:56:78:90:ab:cd,vhost_user=true,socket=/tmp/sock"],
|
2020-01-28 10:38:42 +00:00
|
|
|
r#"{
|
2022-08-10 10:24:31 +00:00
|
|
|
"payload": {"kernel": "/path/to/kernel"},
|
2020-04-24 13:46:48 +00:00
|
|
|
"memory" : { "shared": true, "size": 536870912 },
|
2020-01-28 10:38:42 +00:00
|
|
|
"net": [
|
2020-06-04 19:19:24 +00:00
|
|
|
{"mac": "12:34:56:78:90:ab", "host_mac": "34:56:78:90:ab:cd", "vhost_user": true, "vhost_socket": "/tmp/sock"}
|
2020-01-28 10:38:42 +00:00
|
|
|
]
|
|
|
|
}"#,
|
|
|
|
true,
|
|
|
|
),
|
2019-12-12 17:35:33 +00:00
|
|
|
]
|
|
|
|
.iter()
|
|
|
|
.for_each(|(cli, openapi, equal)| {
|
|
|
|
compare_vm_config_cli_vs_json(cli, openapi, *equal);
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_valid_vm_config_rng() {
|
2023-07-12 04:25:25 +00:00
|
|
|
[(
|
2020-04-06 16:00:38 +00:00
|
|
|
vec![
|
|
|
|
"cloud-hypervisor",
|
|
|
|
"--kernel",
|
|
|
|
"/path/to/kernel",
|
|
|
|
"--rng",
|
|
|
|
"src=/path/to/entropy/source",
|
|
|
|
],
|
2019-12-12 17:35:33 +00:00
|
|
|
r#"{
|
2022-08-10 10:24:31 +00:00
|
|
|
"payload": {"kernel": "/path/to/kernel"},
|
2019-12-12 17:35:33 +00:00
|
|
|
"rng": {"src": "/path/to/entropy/source"}
|
|
|
|
}"#,
|
|
|
|
true,
|
|
|
|
)]
|
|
|
|
.iter()
|
|
|
|
.for_each(|(cli, openapi, equal)| {
|
|
|
|
compare_vm_config_cli_vs_json(cli, openapi, *equal);
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_valid_vm_config_fs() {
|
2023-07-12 04:25:25 +00:00
|
|
|
[(
|
2019-12-12 17:35:33 +00:00
|
|
|
vec![
|
2020-04-06 16:00:38 +00:00
|
|
|
"cloud-hypervisor", "--kernel", "/path/to/kernel",
|
2020-04-24 13:46:48 +00:00
|
|
|
"--memory", "shared=true",
|
2019-12-12 17:35:33 +00:00
|
|
|
"--fs",
|
2020-06-04 19:19:24 +00:00
|
|
|
"tag=virtiofs1,socket=/path/to/sock1",
|
2023-01-12 18:50:20 +00:00
|
|
|
"--fs",
|
2020-06-04 19:19:24 +00:00
|
|
|
"tag=virtiofs2,socket=/path/to/sock2",
|
2019-12-12 17:35:33 +00:00
|
|
|
],
|
|
|
|
r#"{
|
2022-08-10 10:24:31 +00:00
|
|
|
"payload": {"kernel": "/path/to/kernel"},
|
2020-04-24 13:46:48 +00:00
|
|
|
"memory" : { "shared": true, "size": 536870912 },
|
2019-12-12 17:35:33 +00:00
|
|
|
"fs": [
|
2020-06-04 19:19:24 +00:00
|
|
|
{"tag": "virtiofs1", "socket": "/path/to/sock1"},
|
|
|
|
{"tag": "virtiofs2", "socket": "/path/to/sock2"}
|
2019-12-12 17:35:33 +00:00
|
|
|
]
|
|
|
|
}"#,
|
|
|
|
true,
|
|
|
|
),
|
|
|
|
(
|
|
|
|
vec![
|
2020-04-06 16:00:38 +00:00
|
|
|
"cloud-hypervisor", "--kernel", "/path/to/kernel",
|
2020-04-24 13:46:48 +00:00
|
|
|
"--memory", "shared=true",
|
2019-12-12 17:35:33 +00:00
|
|
|
"--fs",
|
2020-06-04 19:19:24 +00:00
|
|
|
"tag=virtiofs1,socket=/path/to/sock1",
|
2023-01-12 18:50:20 +00:00
|
|
|
"--fs",
|
2020-06-04 19:19:24 +00:00
|
|
|
"tag=virtiofs2,socket=/path/to/sock2",
|
2019-12-12 17:35:33 +00:00
|
|
|
],
|
|
|
|
r#"{
|
2022-08-10 10:24:31 +00:00
|
|
|
"payload": {"kernel": "/path/to/kernel"},
|
2020-04-24 13:46:48 +00:00
|
|
|
"memory" : { "shared": true, "size": 536870912 },
|
2019-12-12 17:35:33 +00:00
|
|
|
"fs": [
|
2020-06-04 19:19:24 +00:00
|
|
|
{"tag": "virtiofs1", "socket": "/path/to/sock1"}
|
2019-12-12 17:35:33 +00:00
|
|
|
]
|
|
|
|
}"#,
|
|
|
|
false,
|
|
|
|
),
|
|
|
|
(
|
|
|
|
vec![
|
2020-04-06 16:00:38 +00:00
|
|
|
"cloud-hypervisor", "--kernel", "/path/to/kernel",
|
2021-04-29 11:10:44 +00:00
|
|
|
"--memory", "shared=true", "--cpus", "boot=4",
|
2019-12-12 17:35:33 +00:00
|
|
|
"--fs",
|
2020-06-04 19:19:24 +00:00
|
|
|
"tag=virtiofs1,socket=/path/to/sock1,num_queues=4",
|
2019-12-12 17:35:33 +00:00
|
|
|
],
|
|
|
|
r#"{
|
2022-08-10 10:24:31 +00:00
|
|
|
"payload": {"kernel": "/path/to/kernel"},
|
2020-04-24 13:46:48 +00:00
|
|
|
"memory" : { "shared": true, "size": 536870912 },
|
2021-04-29 11:10:44 +00:00
|
|
|
"cpus": {"boot_vcpus": 4, "max_vcpus": 4},
|
2019-12-12 17:35:33 +00:00
|
|
|
"fs": [
|
2020-06-04 19:19:24 +00:00
|
|
|
{"tag": "virtiofs1", "socket": "/path/to/sock1", "num_queues": 4}
|
2019-12-12 17:35:33 +00:00
|
|
|
]
|
|
|
|
}"#,
|
|
|
|
true,
|
|
|
|
),
|
|
|
|
(
|
|
|
|
vec![
|
2020-04-06 16:00:38 +00:00
|
|
|
"cloud-hypervisor", "--kernel", "/path/to/kernel",
|
2021-04-29 11:10:44 +00:00
|
|
|
"--memory", "shared=true", "--cpus", "boot=4",
|
2019-12-12 17:35:33 +00:00
|
|
|
"--fs",
|
2020-06-04 19:19:24 +00:00
|
|
|
"tag=virtiofs1,socket=/path/to/sock1,num_queues=4,queue_size=128"
|
2019-12-12 17:35:33 +00:00
|
|
|
],
|
|
|
|
r#"{
|
2022-08-10 10:24:31 +00:00
|
|
|
"payload": {"kernel": "/path/to/kernel"},
|
2020-04-24 13:46:48 +00:00
|
|
|
"memory" : { "shared": true, "size": 536870912 },
|
2021-04-29 11:10:44 +00:00
|
|
|
"cpus": {"boot_vcpus": 4, "max_vcpus": 4},
|
2019-12-12 17:35:33 +00:00
|
|
|
"fs": [
|
2020-06-04 19:19:24 +00:00
|
|
|
{"tag": "virtiofs1", "socket": "/path/to/sock1", "num_queues": 4, "queue_size": 128}
|
2019-12-12 17:35:33 +00:00
|
|
|
]
|
|
|
|
}"#,
|
|
|
|
true,
|
2023-07-12 04:25:25 +00:00
|
|
|
)]
|
2019-12-12 17:35:33 +00:00
|
|
|
.iter()
|
|
|
|
.for_each(|(cli, openapi, equal)| {
|
|
|
|
compare_vm_config_cli_vs_json(cli, openapi, *equal);
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_valid_vm_config_pmem() {
|
2023-07-12 04:25:25 +00:00
|
|
|
[
|
2019-12-12 17:35:33 +00:00
|
|
|
(
|
|
|
|
vec![
|
|
|
|
"cloud-hypervisor",
|
2020-04-06 16:00:38 +00:00
|
|
|
"--kernel",
|
|
|
|
"/path/to/kernel",
|
2019-12-12 17:35:33 +00:00
|
|
|
"--pmem",
|
|
|
|
"file=/path/to/img/1,size=1G",
|
2023-01-12 18:50:20 +00:00
|
|
|
"--pmem",
|
2019-12-12 17:35:33 +00:00
|
|
|
"file=/path/to/img/2,size=2G",
|
|
|
|
],
|
|
|
|
r#"{
|
2022-08-10 10:24:31 +00:00
|
|
|
"payload": {"kernel": "/path/to/kernel"},
|
2019-12-12 17:35:33 +00:00
|
|
|
"pmem": [
|
|
|
|
{"file": "/path/to/img/1", "size": 1073741824},
|
|
|
|
{"file": "/path/to/img/2", "size": 2147483648}
|
|
|
|
]
|
|
|
|
}"#,
|
|
|
|
true,
|
|
|
|
),
|
2020-06-12 00:58:50 +00:00
|
|
|
#[cfg(target_arch = "x86_64")]
|
2019-12-12 17:35:33 +00:00
|
|
|
(
|
|
|
|
vec![
|
|
|
|
"cloud-hypervisor",
|
2020-04-06 16:00:38 +00:00
|
|
|
"--kernel",
|
|
|
|
"/path/to/kernel",
|
2019-12-12 17:35:33 +00:00
|
|
|
"--pmem",
|
|
|
|
"file=/path/to/img/1,size=1G,iommu=on",
|
|
|
|
],
|
|
|
|
r#"{
|
2022-08-10 10:24:31 +00:00
|
|
|
"payload": {"kernel": "/path/to/kernel"},
|
2019-12-12 17:35:33 +00:00
|
|
|
"pmem": [
|
|
|
|
{"file": "/path/to/img/1", "size": 1073741824, "iommu": true}
|
|
|
|
],
|
|
|
|
"iommu": true
|
|
|
|
}"#,
|
|
|
|
true,
|
|
|
|
),
|
2020-06-12 00:58:50 +00:00
|
|
|
#[cfg(target_arch = "x86_64")]
|
2019-12-12 17:35:33 +00:00
|
|
|
(
|
|
|
|
vec![
|
|
|
|
"cloud-hypervisor",
|
2020-04-06 16:00:38 +00:00
|
|
|
"--kernel",
|
|
|
|
"/path/to/kernel",
|
2019-12-12 17:35:33 +00:00
|
|
|
"--pmem",
|
|
|
|
"file=/path/to/img/1,size=1G,iommu=on",
|
|
|
|
],
|
|
|
|
r#"{
|
2022-08-10 10:24:31 +00:00
|
|
|
"payload": {"kernel": "/path/to/kernel"},
|
2019-12-12 17:35:33 +00:00
|
|
|
"pmem": [
|
|
|
|
{"file": "/path/to/img/1", "size": 1073741824, "iommu": true}
|
|
|
|
]
|
|
|
|
}"#,
|
|
|
|
false,
|
|
|
|
),
|
|
|
|
]
|
|
|
|
.iter()
|
|
|
|
.for_each(|(cli, openapi, equal)| {
|
|
|
|
compare_vm_config_cli_vs_json(cli, openapi, *equal);
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_valid_vm_config_serial_console() {
|
2023-07-12 04:25:25 +00:00
|
|
|
[
|
2019-12-12 17:35:33 +00:00
|
|
|
(
|
2020-04-06 16:00:38 +00:00
|
|
|
vec!["cloud-hypervisor", "--kernel", "/path/to/kernel"],
|
2019-12-12 17:35:33 +00:00
|
|
|
r#"{
|
2022-08-10 10:24:31 +00:00
|
|
|
"payload": {"kernel": "/path/to/kernel"},
|
2019-12-12 17:35:33 +00:00
|
|
|
"serial": {"mode": "Null"},
|
|
|
|
"console": {"mode": "Tty"}
|
|
|
|
}"#,
|
|
|
|
true,
|
|
|
|
),
|
|
|
|
(
|
2020-04-06 16:00:38 +00:00
|
|
|
vec![
|
|
|
|
"cloud-hypervisor",
|
|
|
|
"--kernel",
|
|
|
|
"/path/to/kernel",
|
|
|
|
"--serial",
|
|
|
|
"null",
|
|
|
|
"--console",
|
|
|
|
"tty",
|
|
|
|
],
|
|
|
|
r#"{
|
2022-08-10 10:24:31 +00:00
|
|
|
"payload": {"kernel": "/path/to/kernel"}
|
2020-04-06 16:00:38 +00:00
|
|
|
}"#,
|
2019-12-12 17:35:33 +00:00
|
|
|
true,
|
|
|
|
),
|
|
|
|
(
|
2020-04-06 16:00:38 +00:00
|
|
|
vec![
|
|
|
|
"cloud-hypervisor",
|
|
|
|
"--kernel",
|
|
|
|
"/path/to/kernel",
|
|
|
|
"--serial",
|
|
|
|
"tty",
|
|
|
|
"--console",
|
|
|
|
"off",
|
|
|
|
],
|
2019-12-12 17:35:33 +00:00
|
|
|
r#"{
|
2022-08-10 10:24:31 +00:00
|
|
|
"payload": {"kernel": "/path/to/kernel"},
|
2019-12-12 17:35:33 +00:00
|
|
|
"serial": {"mode": "Tty"},
|
|
|
|
"console": {"mode": "Off"}
|
|
|
|
}"#,
|
|
|
|
true,
|
|
|
|
),
|
|
|
|
]
|
|
|
|
.iter()
|
|
|
|
.for_each(|(cli, openapi, equal)| {
|
|
|
|
compare_vm_config_cli_vs_json(cli, openapi, *equal);
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2021-01-14 03:03:53 +00:00
|
|
|
#[test]
|
|
|
|
fn test_valid_vm_config_serial_pty_console_pty() {
|
2023-07-12 04:25:25 +00:00
|
|
|
[
|
2021-01-14 03:03:53 +00:00
|
|
|
(
|
|
|
|
vec!["cloud-hypervisor", "--kernel", "/path/to/kernel"],
|
|
|
|
r#"{
|
2022-08-10 10:24:31 +00:00
|
|
|
"payload": {"kernel": "/path/to/kernel"},
|
2021-01-14 03:03:53 +00:00
|
|
|
"serial": {"mode": "Null"},
|
|
|
|
"console": {"mode": "Tty"}
|
|
|
|
}"#,
|
|
|
|
true,
|
|
|
|
),
|
|
|
|
(
|
|
|
|
vec![
|
|
|
|
"cloud-hypervisor",
|
|
|
|
"--kernel",
|
|
|
|
"/path/to/kernel",
|
|
|
|
"--serial",
|
|
|
|
"null",
|
|
|
|
"--console",
|
|
|
|
"tty",
|
|
|
|
],
|
|
|
|
r#"{
|
2022-08-10 10:24:31 +00:00
|
|
|
"payload": {"kernel": "/path/to/kernel"}
|
2021-01-14 03:03:53 +00:00
|
|
|
}"#,
|
|
|
|
true,
|
|
|
|
),
|
|
|
|
(
|
|
|
|
vec![
|
|
|
|
"cloud-hypervisor",
|
|
|
|
"--kernel",
|
|
|
|
"/path/to/kernel",
|
|
|
|
"--serial",
|
|
|
|
"pty",
|
|
|
|
"--console",
|
|
|
|
"pty",
|
|
|
|
],
|
|
|
|
r#"{
|
2022-08-10 10:24:31 +00:00
|
|
|
"payload": {"kernel": "/path/to/kernel"},
|
2021-01-14 03:03:53 +00:00
|
|
|
"serial": {"mode": "Pty"},
|
|
|
|
"console": {"mode": "Pty"}
|
|
|
|
}"#,
|
|
|
|
true,
|
|
|
|
),
|
|
|
|
]
|
|
|
|
.iter()
|
|
|
|
.for_each(|(cli, openapi, equal)| {
|
|
|
|
compare_vm_config_cli_vs_json(cli, openapi, *equal);
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2019-12-12 17:35:33 +00:00
|
|
|
#[test]
|
2020-06-12 00:58:50 +00:00
|
|
|
#[cfg(target_arch = "x86_64")]
|
2019-12-12 17:35:33 +00:00
|
|
|
fn test_valid_vm_config_devices() {
|
|
|
|
vec![
|
|
|
|
(
|
|
|
|
vec![
|
|
|
|
"cloud-hypervisor",
|
2020-04-06 16:00:38 +00:00
|
|
|
"--kernel",
|
|
|
|
"/path/to/kernel",
|
2019-12-12 17:35:33 +00:00
|
|
|
"--device",
|
|
|
|
"path=/path/to/device/1",
|
2023-01-12 18:50:20 +00:00
|
|
|
"--device",
|
2019-12-12 17:35:33 +00:00
|
|
|
"path=/path/to/device/2",
|
|
|
|
],
|
|
|
|
r#"{
|
2022-08-10 10:24:31 +00:00
|
|
|
"payload": {"kernel": "/path/to/kernel"},
|
2019-12-12 17:35:33 +00:00
|
|
|
"devices": [
|
|
|
|
{"path": "/path/to/device/1"},
|
|
|
|
{"path": "/path/to/device/2"}
|
|
|
|
]
|
|
|
|
}"#,
|
|
|
|
true,
|
|
|
|
),
|
|
|
|
(
|
|
|
|
vec![
|
|
|
|
"cloud-hypervisor",
|
2020-04-06 16:00:38 +00:00
|
|
|
"--kernel",
|
|
|
|
"/path/to/kernel",
|
2019-12-12 17:35:33 +00:00
|
|
|
"--device",
|
|
|
|
"path=/path/to/device/1",
|
2023-01-12 18:50:20 +00:00
|
|
|
"--device",
|
2019-12-12 17:35:33 +00:00
|
|
|
"path=/path/to/device/2",
|
|
|
|
],
|
|
|
|
r#"{
|
2022-08-10 10:24:31 +00:00
|
|
|
"payload": {"kernel": "/path/to/kernel"},
|
2019-12-12 17:35:33 +00:00
|
|
|
"devices": [
|
|
|
|
{"path": "/path/to/device/1"}
|
|
|
|
]
|
|
|
|
}"#,
|
|
|
|
false,
|
|
|
|
),
|
|
|
|
(
|
|
|
|
vec![
|
|
|
|
"cloud-hypervisor",
|
2020-04-06 16:00:38 +00:00
|
|
|
"--kernel",
|
|
|
|
"/path/to/kernel",
|
2019-12-12 17:35:33 +00:00
|
|
|
"--device",
|
|
|
|
"path=/path/to/device,iommu=on",
|
|
|
|
],
|
|
|
|
r#"{
|
2022-08-10 10:24:31 +00:00
|
|
|
"payload": {"kernel": "/path/to/kernel"},
|
2019-12-12 17:35:33 +00:00
|
|
|
"devices": [
|
|
|
|
{"path": "/path/to/device", "iommu": true}
|
|
|
|
],
|
|
|
|
"iommu": true
|
|
|
|
}"#,
|
|
|
|
true,
|
|
|
|
),
|
|
|
|
(
|
|
|
|
vec![
|
|
|
|
"cloud-hypervisor",
|
2020-04-06 16:00:38 +00:00
|
|
|
"--kernel",
|
|
|
|
"/path/to/kernel",
|
2019-12-12 17:35:33 +00:00
|
|
|
"--device",
|
|
|
|
"path=/path/to/device,iommu=on",
|
|
|
|
],
|
|
|
|
r#"{
|
2022-08-10 10:24:31 +00:00
|
|
|
"payload": {"kernel": "/path/to/kernel"},
|
2019-12-12 17:35:33 +00:00
|
|
|
"devices": [
|
|
|
|
{"path": "/path/to/device", "iommu": true}
|
|
|
|
]
|
|
|
|
}"#,
|
|
|
|
false,
|
|
|
|
),
|
|
|
|
(
|
|
|
|
vec![
|
|
|
|
"cloud-hypervisor",
|
2020-04-06 16:00:38 +00:00
|
|
|
"--kernel",
|
|
|
|
"/path/to/kernel",
|
2019-12-12 17:35:33 +00:00
|
|
|
"--device",
|
|
|
|
"path=/path/to/device,iommu=off",
|
|
|
|
],
|
|
|
|
r#"{
|
2022-08-10 10:24:31 +00:00
|
|
|
"payload": {"kernel": "/path/to/kernel"},
|
2019-12-12 17:35:33 +00:00
|
|
|
"devices": [
|
|
|
|
{"path": "/path/to/device", "iommu": false}
|
|
|
|
]
|
|
|
|
}"#,
|
|
|
|
true,
|
|
|
|
),
|
|
|
|
]
|
|
|
|
.iter()
|
|
|
|
.for_each(|(cli, openapi, equal)| {
|
|
|
|
compare_vm_config_cli_vs_json(cli, openapi, *equal);
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2022-03-11 09:57:42 +00:00
|
|
|
#[test]
|
|
|
|
fn test_valid_vm_config_vdpa() {
|
2023-07-12 04:25:25 +00:00
|
|
|
[
|
2022-03-11 09:57:42 +00:00
|
|
|
(
|
|
|
|
vec![
|
|
|
|
"cloud-hypervisor",
|
|
|
|
"--kernel",
|
|
|
|
"/path/to/kernel",
|
|
|
|
"--vdpa",
|
|
|
|
"path=/path/to/device/1",
|
2023-01-12 18:50:20 +00:00
|
|
|
"--vdpa",
|
2022-03-11 09:57:42 +00:00
|
|
|
"path=/path/to/device/2,num_queues=2",
|
|
|
|
],
|
|
|
|
r#"{
|
2022-08-10 10:24:31 +00:00
|
|
|
"payload": {"kernel": "/path/to/kernel"},
|
2022-03-11 09:57:42 +00:00
|
|
|
"vdpa": [
|
|
|
|
{"path": "/path/to/device/1", "num_queues": 1},
|
|
|
|
{"path": "/path/to/device/2", "num_queues": 2}
|
|
|
|
]
|
|
|
|
}"#,
|
|
|
|
true,
|
|
|
|
),
|
|
|
|
(
|
|
|
|
vec![
|
|
|
|
"cloud-hypervisor",
|
|
|
|
"--kernel",
|
|
|
|
"/path/to/kernel",
|
|
|
|
"--vdpa",
|
|
|
|
"path=/path/to/device/1",
|
2023-01-12 18:50:20 +00:00
|
|
|
"--vdpa",
|
2022-03-11 09:57:42 +00:00
|
|
|
"path=/path/to/device/2",
|
|
|
|
],
|
|
|
|
r#"{
|
2022-08-10 10:24:31 +00:00
|
|
|
"payload": {"kernel": "/path/to/kernel"},
|
2022-03-11 09:57:42 +00:00
|
|
|
"vdpa": [
|
|
|
|
{"path": "/path/to/device/1"}
|
|
|
|
]
|
|
|
|
}"#,
|
|
|
|
false,
|
|
|
|
),
|
|
|
|
]
|
|
|
|
.iter()
|
|
|
|
.for_each(|(cli, openapi, equal)| {
|
|
|
|
compare_vm_config_cli_vs_json(cli, openapi, *equal);
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2019-12-12 17:35:33 +00:00
|
|
|
#[test]
|
|
|
|
fn test_valid_vm_config_vsock() {
|
2023-07-12 04:25:25 +00:00
|
|
|
[
|
2019-12-12 17:35:33 +00:00
|
|
|
(
|
|
|
|
vec![
|
|
|
|
"cloud-hypervisor",
|
2020-04-06 16:00:38 +00:00
|
|
|
"--kernel",
|
|
|
|
"/path/to/kernel",
|
2019-12-12 17:35:33 +00:00
|
|
|
"--vsock",
|
2020-06-04 19:19:24 +00:00
|
|
|
"cid=123,socket=/path/to/sock/1",
|
2019-12-12 17:35:33 +00:00
|
|
|
],
|
|
|
|
r#"{
|
2022-08-10 10:24:31 +00:00
|
|
|
"payload": {"kernel": "/path/to/kernel"},
|
2020-06-04 19:19:24 +00:00
|
|
|
"vsock": {"cid": 123, "socket": "/path/to/sock/1"}
|
2019-12-12 17:35:33 +00:00
|
|
|
}"#,
|
|
|
|
true,
|
|
|
|
),
|
|
|
|
(
|
|
|
|
vec![
|
|
|
|
"cloud-hypervisor",
|
2020-04-06 16:00:38 +00:00
|
|
|
"--kernel",
|
|
|
|
"/path/to/kernel",
|
2019-12-12 17:35:33 +00:00
|
|
|
"--vsock",
|
2020-06-04 19:19:24 +00:00
|
|
|
"cid=124,socket=/path/to/sock/1",
|
2019-12-12 17:35:33 +00:00
|
|
|
],
|
|
|
|
r#"{
|
2022-08-10 10:24:31 +00:00
|
|
|
"payload": {"kernel": "/path/to/kernel"},
|
2020-06-04 19:19:24 +00:00
|
|
|
"vsock": {"cid": 123, "socket": "/path/to/sock/1"}
|
2019-12-12 17:35:33 +00:00
|
|
|
}"#,
|
|
|
|
false,
|
|
|
|
),
|
2020-06-12 00:58:50 +00:00
|
|
|
#[cfg(target_arch = "x86_64")]
|
2019-12-12 17:35:33 +00:00
|
|
|
(
|
|
|
|
vec![
|
|
|
|
"cloud-hypervisor",
|
2020-04-06 16:00:38 +00:00
|
|
|
"--kernel",
|
|
|
|
"/path/to/kernel",
|
2019-12-12 17:35:33 +00:00
|
|
|
"--vsock",
|
2020-06-04 19:19:24 +00:00
|
|
|
"cid=123,socket=/path/to/sock/1,iommu=on",
|
2019-12-12 17:35:33 +00:00
|
|
|
],
|
|
|
|
r#"{
|
2022-08-10 10:24:31 +00:00
|
|
|
"payload": {"kernel": "/path/to/kernel"},
|
2020-06-04 19:19:24 +00:00
|
|
|
"vsock": {"cid": 123, "socket": "/path/to/sock/1", "iommu": true},
|
2019-12-12 17:35:33 +00:00
|
|
|
"iommu": true
|
|
|
|
}"#,
|
|
|
|
true,
|
|
|
|
),
|
2020-06-12 00:58:50 +00:00
|
|
|
#[cfg(target_arch = "x86_64")]
|
2019-12-12 17:35:33 +00:00
|
|
|
(
|
|
|
|
vec![
|
|
|
|
"cloud-hypervisor",
|
2020-04-06 16:00:38 +00:00
|
|
|
"--kernel",
|
|
|
|
"/path/to/kernel",
|
2019-12-12 17:35:33 +00:00
|
|
|
"--vsock",
|
2020-06-04 19:19:24 +00:00
|
|
|
"cid=123,socket=/path/to/sock/1,iommu=on",
|
2019-12-12 17:35:33 +00:00
|
|
|
],
|
|
|
|
r#"{
|
2022-08-10 10:24:31 +00:00
|
|
|
"payload": {"kernel": "/path/to/kernel"},
|
2020-06-04 19:19:24 +00:00
|
|
|
"vsock": {"cid": 123, "socket": "/path/to/sock/1", "iommu": true}
|
2019-12-12 17:35:33 +00:00
|
|
|
}"#,
|
|
|
|
false,
|
|
|
|
),
|
|
|
|
(
|
|
|
|
vec![
|
|
|
|
"cloud-hypervisor",
|
2020-04-06 16:00:38 +00:00
|
|
|
"--kernel",
|
|
|
|
"/path/to/kernel",
|
2019-12-12 17:35:33 +00:00
|
|
|
"--vsock",
|
2020-06-04 19:19:24 +00:00
|
|
|
"cid=123,socket=/path/to/sock/1,iommu=off",
|
2019-12-12 17:35:33 +00:00
|
|
|
],
|
|
|
|
r#"{
|
2022-08-10 10:24:31 +00:00
|
|
|
"payload": {"kernel": "/path/to/kernel"},
|
2020-06-04 19:19:24 +00:00
|
|
|
"vsock": {"cid": 123, "socket": "/path/to/sock/1", "iommu": false}
|
2019-12-12 17:35:33 +00:00
|
|
|
}"#,
|
|
|
|
true,
|
|
|
|
),
|
|
|
|
]
|
|
|
|
.iter()
|
|
|
|
.for_each(|(cli, openapi, equal)| {
|
|
|
|
compare_vm_config_cli_vs_json(cli, openapi, *equal);
|
|
|
|
});
|
|
|
|
}
|
2022-09-15 04:11:59 +00:00
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_valid_vm_config_tpm_socket() {
|
2023-07-12 04:25:25 +00:00
|
|
|
[(
|
2022-09-15 04:11:59 +00:00
|
|
|
vec![
|
|
|
|
"cloud-hypervisor",
|
|
|
|
"--kernel",
|
|
|
|
"/path/to/kernel",
|
|
|
|
"--tpm",
|
|
|
|
"socket=/path/to/tpm/sock",
|
|
|
|
],
|
|
|
|
r#"{
|
|
|
|
"payload": {"kernel": "/path/to/kernel"},
|
|
|
|
"tpm": {"socket": "/path/to/tpm/sock"}
|
|
|
|
}"#,
|
|
|
|
true,
|
|
|
|
)]
|
|
|
|
.iter()
|
|
|
|
.for_each(|(cli, openapi, equal)| {
|
|
|
|
compare_vm_config_cli_vs_json(cli, openapi, *equal);
|
|
|
|
});
|
|
|
|
}
|
2019-12-12 17:35:33 +00:00
|
|
|
}
|