1 В избранное 0 Ответвления 0

OSCHINA-MIRROR/openeuler-stratovirt

Присоединиться к Gitlife
Откройте для себя и примите участие в публичных проектах с открытым исходным кодом с участием более 10 миллионов разработчиков. Приватные репозитории также полностью бесплатны :)
Присоединиться бесплатно
В этом репозитории не указан файл с открытой лицензией (LICENSE). При использовании обратитесь к конкретному описанию проекта и его зависимостям в коде.
Клонировать/Скачать
cmdline.rs 29 КБ
Копировать Редактировать Исходные данные Просмотреть построчно История
Gan Qixin Отправлено год назад 4a3e3c6
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722
// Copyright (c) 2020 Huawei Technologies Co.,Ltd. All rights reserved.
//
// StratoVirt is licensed under Mulan PSL v2.
// You can use this software according to the terms and conditions of the Mulan
// PSL v2.
// You may obtain a copy of Mulan PSL v2 at:
// http://license.coscl.org.cn/MulanPSL2
// THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY
// KIND, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO
// NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
// See the Mulan PSL v2 for more details.
use anyhow::{bail, Context, Result};
use crate::{
config::{parse_trace_options, ChardevType, CmdParser, MachineType, VmConfig},
qmp::qmp_socket::QmpSocketPath,
temp_cleaner::TempCleaner,
};
use util::file::clear_file;
use util::unix::limit_permission;
use util::{
arg_parser::{Arg, ArgMatches, ArgParser},
socket::SocketListener,
};
/// This macro is to run struct $z 's function $s whose arg is $x 's inner member.
/// There is a multi-macro-cast in cases of vec and bool.
///
/// # Examples
///
/// ```text
/// add_args_to_config!(name, vm_cfg, update_name);
/// add_args_to_config!(name, vm_cfg, update_name, vec);
/// add_args_to_config!(name, vm_cfg, update_name, bool);
/// ```
macro_rules! add_args_to_config {
( $x:tt, $z:expr, $s:tt ) => {
if let Some(temp) = &$x {
$z.$s(temp)?;
}
};
( $x:tt, $z:expr, $s:tt, vec ) => {
if let Some(temp) = &$x {
$z.$s(&temp)
}
};
( $x:tt, $z:expr, $s:tt, bool ) => {
if ($x) {
$z.$s();
}
};
}
/// This macro is to run struct $z 's function $s whose arg is $x 's every inner
/// member.
///
/// # Examples
///
/// ```text
/// add_args_to_config_multi!(drive, vm_cfg, update_drive);
/// ```
macro_rules! add_args_to_config_multi {
( $x:tt, $z:expr, $s:tt ) => {
if let Some(temps) = &$x {
for temp in temps {
$z.$s(temp)?;
}
}
};
}
/// This function is to define all commandline arguments.
pub fn create_args_parser<'a>() -> ArgParser<'a> {
let parser = ArgParser::new("StratoVirt")
.version(util::VERSION)
.author("The StratoVirt Project Developers")
.about("A light kvm-based hypervisor.")
.arg(
Arg::with_name("name")
.long("name")
.value_name("[vm_name]")
.help("set the name of the guest.")
.takes_value(true),
)
.arg(
Arg::with_name("machine")
.long("machine")
.value_name("[type=]<name>[,dump_guest_core=on|off][,mem-share=on|off]")
.help("'type' selects emulated machine type and set properties. \
'dump_guest_core' includes guest memory in a core dump. \
'mem-share' sets guest memory is shareable.")
.takes_value(true),
)
.arg(
Arg::with_name("accel")
.long("accel")
.value_name("[accel]")
.help("select accelerator, only 'kvm' is supported now.")
.takes_value(true),
)
.arg(
Arg::with_name("smp")
.long("smp")
.value_name("[cpus=]<n>[,maxcpus=<cpus>][,sockets=<sockets>][,dies=<dies>][,clusters=<clusters>][,cores=<cores>][,threads=<threads>]")
.help("'cpus' sets the number of CPUs to 'n' (default: 1). 'maxcpus' sets number of total CPUs, including online and offline CPUs. \
'sockets' is the number of sockets on the machine. \
'dies' is the number of dies in one socket. \
'clusters' is the number of clusters in one die. \
'cores' is the number of cores in one cluster. \
'threads' is the number of threads in one core")
.takes_value(true),
)
.arg(
Arg::with_name("cpu")
.long("cpu")
.value_name("host[,pmu=on|off][,sve=on|off]")
.help("set CPU model and features.")
.can_no_value(false)
.takes_value(true)
)
.arg(
Arg::with_name("freeze_cpu")
.short("S")
.long("freeze")
.help("freeze CPU at startup")
.takes_value(false)
.required(false),
)
.arg(
Arg::with_name("memory")
.long("m")
.value_name("[size=]<megs>[m|M|g|G]")
.help("configure guest RAM(default unit: MiB).")
.takes_value(true),
)
.arg(
Arg::with_name("mem-path")
.long("mem-path")
.value_name("<filebackend file path>")
.help("configure file path that backs guest memory.")
.takes_value(true),
)
.arg(
Arg::with_name("mem-prealloc")
.long("mem-prealloc")
.help("Prealloc memory for VM")
.takes_value(false)
.required(false),
)
.arg(
Arg::with_name("numa")
.multiple(true)
.long("numa")
.value_name("<parameters>")
.help("\n\t\tset numa node: -numa node,nodeid=<0>,cpus=<0-1>,memdev=<mem0>; \
\n\t\tset numa distance: -numa dist,src=<0>,dst=<1>,val=<20> ")
.takes_values(true),
)
.arg(
Arg::with_name("kernel")
.long("kernel")
.value_name("<kernel_path>")
.help("use uncompressed kernel image")
.takes_value(true),
)
.arg(
Arg::with_name("kernel-cmdline")
.multiple(true)
.long("append")
.value_name("<kernel cmdline parameters>")
.help("use 'cmdline' as kernel command line")
.takes_values(true),
)
.arg(
Arg::with_name("initrd-file")
.long("initrd")
.value_name("<initrd_path>")
.help("use 'initrd-file' as initial ram disk")
.takes_value(true),
)
.arg(
Arg::with_name("qmp")
.long("qmp")
.value_name("<parameters>")
.help("\n\t\tset unix socket path: unix:<socket_path>,server,nowait; \
\n\t\tset tcp socket path: tcp:ip:port,server,nowait")
.takes_value(true)
)
.arg(
Arg::with_name("mod-test")
.long("mod-test")
.value_name("unix:socket_path")
.help("set module test's unixsocket path")
.takes_value(true)
)
.arg(
Arg::with_name("drive")
.multiple(true)
.long("drive")
.value_name("<parameters>")
.help("\n\t\tset block drive image: -drive id=<drive_id>,file=<path_on_host>[,readonly=on|off][,direct=on|off][,throttling.iops-total=<200>]; \
\n\t\tset pflash drive image: -drive file=<pflash_path>,if=pflash,unit=0|1[,readonly=true|false]; \
\n\t\tset scsi drive image: -drive id=<drive-scsi0-0-0-0>,file=<path_on_host>[,readonly=true|false]")
.takes_values(true),
)
.arg(
Arg::with_name("netdev")
.multiple(true)
.long("netdev")
.value_name(
"tap,id=<str>,ifname=<tap_name>[,vhost=on|off][,queue=<N>]",
)
.help("configure a host TAP network with ID 'str'")
.takes_values(true),
)
.arg(
Arg::with_name("chardev")
.multiple(true)
.long("chardev")
.value_name("<parameters>")
.help("\n\t\tadd standard i/o device: -chardev stdio,id=<char_id>; \
\n\t\tadd pseudo-terminal: -chardev pty,id=<char_id>; \
\n\t\tadd file: -chardev file,id=<char_id>,path=<path>; \
\n\t\tadd unix-socket: -chardev socket,id=<char_id>,path=<path>[,server][,nowait]; \
\n\t\tadd tcp-socket: -chardev socket,id=<char_id>,port=<port>[,host=host][,server][,nowait];")
.takes_values(true),
)
.arg(
Arg::with_name("device")
.multiple(true)
.long("device")
.value_name("<parameters>")
.help("\n\t\tadd virtio mmio block: -device virtio-blk-device,id=<blk_id>,drive=<drive_id>[,iothread=<iothread1>][,serial=<serial_num>]; \
\n\t\tadd virtio pci block: -device virtio-blk-pci,id=<blk_id>,drive=<drive_id>,bus=<pcie.0>,addr=<0x3>[,multifunction=on|off][,iothread=<iothread1>][,serial=<serial_num>][,num-queues=<N>][,bootindex=<N>]; \
\n\t\tadd vhost user pci block: -device vhost-user-blk-pci,id=<blk_id>,chardev=<chardev_id>,bus=<pcie.0>,addr=<0x3>[,num-queues=<N>][,bootindex=<N>]; \
\n\t\tadd virtio mmio net: -device virtio-net-device,id=<net_id>,netdev=<netdev_id>[,iothread=<iothread1>][,mac=<12:34:56:78:9A:BC>]; \
\n\t\tadd virtio pci net: -device virtio-net-pci,id=<net_id>,netdev=<netdev_id>,bus=<pcie.0>,addr=<0x2>[,multifunction=on|off][,iothread=<iothread1>][,mac=<12:34:56:78:9A:BC>][,mq=on|off]; \
\n\t\tadd vhost mmio net: -device virtio-net-device,id=<net_id>,netdev=<netdev_id>[,iothread=<iothread1>][,mac=<12:34:56:78:9A:BC>]; \
\n\t\tadd vhost pci net: -device virtio-net-pci,id=<net_id>,netdev=<netdev_id>,bus=<pcie.0>,addr=<0x2>[,multifunction=on|off][,iothread=<iothread1>][,mac=<12:34:56:78:9A:BC>][,mq=on|off]; \
\n\t\tadd virtio mmio console: -device virtio-serial-device[,id=<virtio-serial0>] -device virtconsole,id=console_id,chardev=<virtioconsole1>; \
\n\t\tadd virtio pci console: -device virtio-serial-pci,id=<virtio-serial0>,bus=<pcie.0>,addr=<0x3>[,multifunction=on|off] -device virtconsole,id=<console_id>,chardev=<virtioconsole1>; \
\n\t\tadd vhost mmio vsock: -device vhost-vsock-device,id=<vsock_id>,guest-cid=<N>; \
\n\t\tadd vhost pci vsock: -device vhost-vsock-pci,id=<vsock_id>,guest-cid=<N>,bus=<pcie.0>,addr=<0x3>[,multifunction=on|off]; \
\n\t\tadd virtio mmio balloon: -device virtio-balloon-device[,deflate-on-oom=true|false][,free-page-reporting=true|false]; \
\n\t\tadd virtio pci balloon: -device virtio-balloon-pci,id=<balloon_id>,bus=<pcie.0>,addr=<0x4>[,deflate-on-oom=true|false][,free-page-reporting=true|false][,multifunction=on|off]; \
\n\t\tadd virtio mmio rng: -device virtio-rng-device,rng=<objrng0>,max-bytes=<1234>,period=<1000>; \
\n\t\tadd virtio pci rng: -device virtio-rng-pci,id=<rng_id>,rng=<objrng0>,max-bytes=<1234>,period=<1000>,bus=<pcie.0>,addr=<0x1>[,multifunction=on|off]; \
\n\t\tadd pcie root port: -device pcie-root-port,id=<pcie.1>,port=<0x1>,bus=<pcie.0>,addr=<0x1>[,multifunction=on|off]; \
\n\t\tadd vfio pci: -device vfio-pci,id=<vfio_id>,host=<0000:1a:00.3>,bus=<pcie.0>,addr=<0x03>[,multifunction=on|off]; \
\n\t\tadd usb controller: -device nec-usb-xhci,id=<xhci>,bus=<pcie.0>,addr=<0xa>; \
\n\t\tadd usb keyboard: -device usb-kbd,id=<kbd>; \
\n\t\tadd usb tablet: -device usb-tablet,id=<tablet>; \
\n\t\tadd usb storage: -device usb-storage,id=<storage>,drive=<drive_id>; \
\n\t\tadd scsi controller: -device virtio-scsi-pci,id=<scsi_id>,bus=<pcie.0>,addr=<0x3>[,multifunction=on|off][,iothread=<iothread1>][,num-queues=<N>]; \
\n\t\tadd scsi hard disk: -device scsi-hd,scsi-id=<0>,bus=<scsi0.0>,lun=<0>,drive=<drive-scsi0-0-0-0>,id=<scsi0-0-0-0>; \
\n\t\tadd vhost user fs: -device vhost-user-fs-pci,id=<device_id>,chardev=<chardev_id>,tag=<mount_tag>; \
\n\t\tadd pvpanic: -device pvpanic,id=<pvpanic_pci>,bus=<pcie.0>,addr=<0x7>[,supported-features=<0|1|2|3>];")
.takes_values(true),
)
.arg(
Arg::with_name("serial")
.long("serial")
.value_name("<parameters>")
.help("\n\t\tuse chardev device: -serial chardev:<char_id>; \
\n\t\tuse standard i/o device: -serial stdio; \
\n\t\tuse pseudo-terminal: -serial pty; \
\n\t\tuse file: -serial file,path=<path>; \
\n\t\tuse unix-socket: -serial socket,path=<path>[,server][,nowait]; \
\n\t\tuse tcp-socket: -serial socket,port=<port>[,host=<host>][,server][,nowait]; \
")
.takes_value(true),
)
.arg(
Arg::with_name("display log")
.long("D")
.value_name("[log path]")
.help("output log to logfile (default stderr)")
.takes_value(true)
.can_no_value(true),
)
.arg(
Arg::with_name("pidfile")
.long("pidfile")
.value_name("<pidfile path>")
.help("write PID to 'file'")
.takes_value(true),
)
.arg(
Arg::with_name("daemonize")
.long("daemonize")
.value_name("")
.help("daemonize StratoVirt after initializing")
.takes_value(false)
.required(false),
)
.arg(
Arg::with_name("disable-seccomp")
.long("disable-seccomp")
.value_name("")
.help("not use seccomp sandbox for StratoVirt")
.takes_value(false)
.required(false),
)
.arg(
Arg::with_name("incoming")
.long("incoming")
.value_name("<parameters>")
.help("\n\t\tdo the migration using tcp socket: -incoming tcp:<ip>:<port>; \
\n\t\tdo the migration using unix socket: -incoming unix:<socket path>; \
\n\t\tdo the virtual machine snapshot: -incoming file:<file path>")
.takes_value(true),
)
.arg(
Arg::with_name("object")
.multiple(true)
.long("object")
.value_name("<parameters>")
.help("\n\t\tadd memory backend ram object: -object memory-backend-ram,size=<size>,id=<memid>[,policy=<bind>]
[,host-nodes=<0>][,mem-prealloc=<true|false>][,dump-guest-core=<true|false>][,share=<on|off>]; \
\n\t\tadd memory backend file object: -object memory-backend-file,size=<size>,id=<memid>[,host-nodes=<0-1>] \
[,policy=bind][,mem-path=<path/to/file>][,dump-guest-core=<true|false>][,mem-prealloc=<true|false>][,share=<on|off>] \
\n\t\tadd memory backend memfd object: -object memory-backend-memfd,size=<size>,id=<memid>[,host-nodes=0-1][,policy=bind] \
[,mem-prealloc=<true|false>][,dump-guest-core=<true|false>][,share=<on|off>]; \
\n\t\tadd iothread object: -object iothread,id=<iothread_id>; \
\n\t\tadd rng object: -object rng-random,id=<rng_id>,filename=<file_path>; \
\n\t\tadd vnc tls object: -object tls-creds-x509,id=<vnc_id>,dir=</etc/pki/vnc>; \
\n\t\tadd authz object: -object authz-simple,id=<authz_id>,identity=<username>")
.takes_values(true),
)
.arg(
Arg::with_name("mon")
.long("mon")
.value_name("chardev=<chardev_id>,id=<mon_id>[,mode=control]")
.help("-mon is another way to create qmp channel. To use it, the chardev should be specified")
.takes_value(true),
)
.arg(
Arg::with_name("overcommit")
.long("overcommit")
.value_name("[mem-lock=off]")
.hidden(true)
.can_no_value(true)
.takes_value(true),
)
.arg(
Arg::with_name("uuid")
.long("uuid")
.value_name("[uuid]")
.hidden(true)
.can_no_value(true)
.takes_value(true),
)
.arg(
Arg::with_name("no-user-config")
.long("no-user-config")
.hidden(true)
.can_no_value(true)
.takes_value(true),
)
.arg(
Arg::with_name("nodefaults")
.long("nodefaults")
.hidden(true)
.can_no_value(true)
.takes_value(true),
)
.arg(
Arg::with_name("sandbox")
.long("sandbox")
.value_name("[on,obsolete=deny]")
.hidden(true)
.can_no_value(true)
.takes_value(true),
)
.arg(
Arg::with_name("msg")
.long("msg")
.value_name("[timestamp=on]")
.hidden(true)
.can_no_value(true)
.takes_value(true),
)
.arg(
Arg::with_name("rtc")
.long("rtc")
.value_name("[base=utc]")
.hidden(true)
.can_no_value(true)
.takes_value(true),
)
.arg(
Arg::with_name("no-shutdown")
.long("no-shutdown")
.hidden(true)
.can_no_value(true)
.takes_value(true),
)
.arg(
Arg::with_name("battery")
.long("battery")
.value_name("")
.help("enable battery and power adapter devices")
.takes_value(false)
.required(false),
)
.arg(
Arg::with_name("boot")
.long("boot")
.value_name("[strict=on]")
.hidden(true)
.can_no_value(true)
.takes_value(true),
)
.arg(
Arg::with_name("nographic")
.long("nographic")
.hidden(true)
.can_no_value(true)
.takes_value(true),
)
.arg(
Arg::with_name("realtime")
.long("realtime")
.value_name("[malock=off]")
.hidden(true)
.can_no_value(true)
.takes_value(true),
)
.arg(
Arg::with_name("display")
.long("display")
.value_name("[none]")
.hidden(true)
.can_no_value(true)
.takes_value(true),
)
.arg(
Arg::with_name("usb")
.long("usb")
.hidden(true)
.can_no_value(true)
.takes_value(true),
)
.arg(
Arg::with_name("trace")
.multiple(false)
.long("trace")
.value_name("file=<file>")
.help("specify the file lists trace state to enable")
.takes_value(true),
)
.arg(
Arg::with_name("global")
.multiple(true)
.long("global")
.value_name("[key=<value>]")
.help("set global config")
.takes_values(true)
.required(false),
)
.arg(
Arg::with_name("smbios")
.multiple(true)
.long("smbios")
.value_name("<parameters>")
.help("\n\t\tadd type0 table: -smbios type=0[,vendor=str][,version=str][,date=str]; \
\n\t\tadd type1 table: -smbios type=1[,manufacturer=str][,version=str][,product=str][,serial=str][,uuid=str][,sku=str][,family=str]; \
\n\t\tadd type2 table: -smbios type=2[,manufacturer=str][,product=str][,version=str][,serial=str][,asset=str][,location=str]; \
\n\t\tadd type3 table: -smbios type=3[,manufacturer=str][,version=str][,serial=str][,asset=str][,sku=str]; \
\n\t\tadd type4 table: -smbios type=4[,sock_pfx=str][,manufacturer=str][,version=str][,serial=str][,asset=str][,part=str][,max-speed=%d][,current-speed=%d]; \
\n\t\tadd type17 table: -smbios type=17[,loc_pfx=str][,bank=str][,manufacturer=str][,serial=str][,asset=str][,part=str][,speed=%d]")
.takes_values(true),
);
#[cfg(feature = "usb_camera")]
let parser = parser.arg(
Arg::with_name("cameradev")
.multiple(true)
.long("cameradev")
.value_name("<parameters>")
.help("set cameradev: -cameradev v4l2,id=<testCam>,path=</dev/video0>")
.takes_values(true),
);
#[cfg(feature = "gtk")]
let parser = parser.arg(
Arg::with_name("display")
.multiple(false)
.long("display")
.value_name("gtk")
.help("set display for virtual machine: currently only supports gtk")
.takes_value(true),
);
#[cfg(feature = "vnc")]
let parser = parser.arg(
Arg::with_name("vnc")
.multiple(false)
.long("vnc")
.value_name("ip:port")
.help("specify the ip and port for vnc")
.takes_value(true),
);
#[cfg(feature = "windows_emu_pid")]
let parser = parser.arg(
Arg::with_name("windows_emu_pid")
.multiple(false)
.long("windows_emu_pid")
.value_name("pid")
.help("watch on the external windows emu pid")
.takes_value(true),
);
parser
}
/// Create `VmConfig` from `ArgMatches`'s arg.
///
/// When accepted cmdline arguments, `StratoVirt` will parse useful arguments and
/// transform them to VM's configuration structure -- `VmConfig`.
///
/// # Arguments
///
/// - * `args` - The structure accepted input cmdline arguments.
///
/// # Errors
///
/// Input arguments is illegal for `VmConfig` or `VmConfig`'s health check
/// failed -- with this unhealthy `VmConfig`, VM will not boot successfully.
pub fn create_vmconfig(args: &ArgMatches) -> Result<VmConfig> {
// Parse config-file json.
// VmConfig can be transformed by json file which described VmConfig
// directly.
let mut vm_cfg = VmConfig::default();
// Parse cmdline args which need to set in VmConfig
add_args_to_config!((args.value_of("name")), vm_cfg, add_name);
add_args_to_config!((args.value_of("machine")), vm_cfg, add_machine);
add_args_to_config!((args.value_of("accel")), vm_cfg, add_accel);
add_args_to_config!((args.value_of("memory")), vm_cfg, add_memory);
add_args_to_config!((args.value_of("mem-path")), vm_cfg, add_mem_path);
add_args_to_config!((args.value_of("smp")), vm_cfg, add_cpu);
add_args_to_config!((args.value_of("cpu")), vm_cfg, add_cpu_feature);
add_args_to_config!((args.value_of("kernel")), vm_cfg, add_kernel);
add_args_to_config!((args.value_of("initrd-file")), vm_cfg, add_initrd);
add_args_to_config!((args.value_of("serial")), vm_cfg, add_serial);
add_args_to_config!((args.value_of("incoming")), vm_cfg, add_incoming);
#[cfg(feature = "vnc")]
add_args_to_config!((args.value_of("vnc")), vm_cfg, add_vnc);
#[cfg(any(feature = "gtk", feature = "ohui_srv"))]
add_args_to_config!((args.value_of("display")), vm_cfg, add_display);
#[cfg(feature = "windows_emu_pid")]
add_args_to_config!(
(args.value_of("windows_emu_pid")),
vm_cfg,
add_windows_emu_pid
);
add_args_to_config!(
(args.is_present("no-shutdown")),
vm_cfg,
add_no_shutdown,
bool
);
add_args_to_config!((args.is_present("battery")), vm_cfg, add_battery, bool);
add_args_to_config!(
(args.is_present("mem-prealloc")),
vm_cfg,
enable_mem_prealloc,
bool
);
add_args_to_config!(
(args.values_of("kernel-cmdline")),
vm_cfg,
add_kernel_cmdline,
vec
);
add_args_to_config_multi!((args.values_of("drive")), vm_cfg, add_drive);
add_args_to_config_multi!((args.values_of("object")), vm_cfg, add_object);
add_args_to_config_multi!((args.values_of("netdev")), vm_cfg, add_netdev);
add_args_to_config_multi!((args.values_of("chardev")), vm_cfg, add_chardev);
add_args_to_config_multi!((args.values_of("device")), vm_cfg, add_device);
add_args_to_config_multi!((args.values_of("global")), vm_cfg, add_global_config);
add_args_to_config_multi!((args.values_of("numa")), vm_cfg, add_numa);
#[cfg(feature = "usb_camera")]
add_args_to_config_multi!((args.values_of("cameradev")), vm_cfg, add_camera_backend);
add_args_to_config_multi!((args.values_of("smbios")), vm_cfg, add_smbios);
if let Some(opt) = args.value_of("trace") {
parse_trace_options(&opt)?;
}
// Check the mini-set for Vm to start is ok
if vm_cfg.machine_config.mach_type != MachineType::None {
vm_cfg
.check_vmconfig(args.is_present("daemonize"))
.with_context(|| "Precheck failed, VmConfig is unhealthy, stop running")?;
}
Ok(vm_cfg)
}
/// This function is to parse qmp socket path and type.
///
/// # Arguments
///
/// * `args` - The structure accepted input cmdline arguments.
///
/// # Errors
///
/// The value of `qmp` is illegel.
pub fn check_api_channel(
args: &ArgMatches,
vm_config: &mut VmConfig,
) -> Result<Vec<SocketListener>> {
let mut sock_paths = Vec::new();
if let Some(qmp_config) = args.value_of("qmp") {
let mut cmd_parser = CmdParser::new("qmp");
cmd_parser.push("").push("server").push("nowait");
cmd_parser.parse(&qmp_config)?;
if let Some(uri) = cmd_parser.get_value::<String>("")? {
let sock_path =
QmpSocketPath::new(uri).with_context(|| "Failed to parse qmp socket path")?;
sock_paths.push(sock_path);
} else {
bail!("No uri found for qmp");
}
if cmd_parser.get_value::<String>("server")?.is_none() {
bail!("Argument \'server\' is needed for qmp");
}
if cmd_parser.get_value::<String>("nowait")?.is_none() {
bail!("Argument \'nowait\' is needed for qmp");
}
}
if let Some(mon_config) = args.value_of("mon") {
let mut cmd_parser = CmdParser::new("monitor");
cmd_parser.push("id").push("mode").push("chardev");
cmd_parser.parse(&mon_config)?;
let chardev = cmd_parser
.get_value::<String>("chardev")?
.with_context(|| "Argument \'chardev\' is missing for \'mon\'")?;
if let Some(mode) = cmd_parser.get_value::<String>("mode")? {
if mode != *"control" {
bail!("Invalid \'mode\' parameter: {:?} for monitor", &mode);
}
} else {
bail!("Argument \'mode\' of \'mon\' should be set to \'control\'.");
}
if let Some(cfg) = vm_config.chardev.remove(&chardev) {
if let ChardevType::UnixSocket {
path,
server,
nowait,
} = cfg.backend
{
if !server || !nowait {
bail!(
"Argument \'server\' and \'nowait\' are both required for chardev \'{}\'",
path
);
}
sock_paths.push(QmpSocketPath::Unix { path });
} else if let ChardevType::TcpSocket {
host,
port,
server,
nowait,
} = cfg.backend
{
if !server || !nowait {
bail!(
"Argument \'server\' and \'nowait\' are both required for chardev \'{}:{}\'",
host, port
);
}
sock_paths.push(QmpSocketPath::Tcp { host, port });
} else {
bail!("Only chardev of unix-socket type can be used for monitor");
}
} else {
bail!("No chardev found: {}", &chardev);
}
}
if sock_paths.is_empty() {
bail!("Please use \'-qmp\' or \'-mon\' to give a qmp path for Unix socket");
}
let mut listeners = Vec::new();
for sock_path in sock_paths {
listeners.push(bind_socket(&sock_path).with_context(|| {
format!(
"Failed to bind socket for path: {:?}",
sock_path.to_string()
)
})?)
}
Ok(listeners)
}
fn bind_socket(path: &QmpSocketPath) -> Result<SocketListener> {
match path {
QmpSocketPath::Tcp { host, port } => {
let listener = SocketListener::bind_by_tcp(host, *port)
.with_context(|| format!("Failed to bind tcp socket {}:{}", &host, &port))?;
Ok(listener)
}
QmpSocketPath::Unix { path } => {
clear_file(path.clone())?;
let listener = SocketListener::bind_by_uds(path)
.with_context(|| format!("Failed to bind socket file {}", &path))?;
// Add file to temporary pool, so it could be cleaned when vm exits.
TempCleaner::add_path(path.clone());
limit_permission(path)
.with_context(|| format!("Failed to limit permission for socket file {}", &path))?;
Ok(listener)
}
}
}

Опубликовать ( 0 )

Вы можете оставить комментарий после Вход в систему

1
https://gitlife.ru/oschina-mirror/openeuler-stratovirt.git
git@gitlife.ru:oschina-mirror/openeuler-stratovirt.git
oschina-mirror
openeuler-stratovirt
openeuler-stratovirt
v2.4.0