From 597ae081876d50e372a4c0f6f1eb7d7d5ac45733 Mon Sep 17 00:00:00 2001 From: Chao Wu Date: Tue, 14 Nov 2023 22:50:53 +0800 Subject: [PATCH] dbs-cli: several refactor in cmd tool 1. Add all creation related args under Create command and all update related args under Update command. 2. catagorize different args type to make more sense, like putting all cpu related commands under CpuArgs instead of putting them everything without order. Signed-off-by: Chao Wu --- Cargo.lock | 6 +- README.md | 40 +++++----- src/api_client.rs | 20 ++--- src/api_server.rs | 16 ++-- src/cli_instance.rs | 68 ++++++++--------- src/main.rs | 39 ++-------- src/parser/args.rs | 179 +++++++++++++++++++++++--------------------- src/parser/mod.rs | 15 ++-- src/utils.rs | 27 +++++++ 9 files changed, 207 insertions(+), 203 deletions(-) create mode 100644 src/utils.rs diff --git a/Cargo.lock b/Cargo.lock index 7c451d1..627e64c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -720,9 +720,9 @@ dependencies = [ [[package]] name = "hermit-abi" -version = "0.3.1" +version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fed44880c466736ef9a5c5b5facefb5ed0785676d0c02d612db14e54f0d84286" +checksum = "d77f7ec81a6d05a3abb01ab6eb7590f6083d08449fe5a1c8b1e620283546ccb7" [[package]] name = "hex" @@ -762,7 +762,7 @@ version = "0.4.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "21b6b32576413a8e69b90e952e4a026476040d81017b80445deda5f2d3921857" dependencies = [ - "hermit-abi 0.3.1", + "hermit-abi 0.3.3", "io-lifetimes", "rustix", "windows-sys", diff --git a/README.md b/README.md index 1885ebd..b77089f 100644 --- a/README.md +++ b/README.md @@ -15,10 +15,10 @@ See all options: A simple example: ```bash -./dbs-cli \ +./dbs-cli create \ --kernel-path ~/path/to/kernel/vmlinux.bin \ --rootfs ~/path/to/rootfs/rootfs.dmg \ - --boot-args "console=ttyS0 console=ttyS1 earlyprintk=ttyS1 tty0 reboot=k debug panic=1 pci=off root=/dev/vda1" create ; + --boot-args "console=ttyS0 console=ttyS1 earlyprintk=ttyS1 tty0 reboot=k debug panic=1 pci=off root=/dev/vda1" ``` Set the log level and log file: @@ -26,11 +26,11 @@ Set the log level and log file: > The log-level argument is case-insensitive: ErrOR and InFO are valid. ```bash -./dbs-cli \ +./dbs-cli create \ --log-file dbs-cli.log --log-level ERROR \ --kernel-path ~/path/to/kernel/vmlinux.bin \ --rootfs ~/path/to/rootfs/bionic.rootfs.ext4 \ - --boot-args "console=ttyS0 console=ttyS1 earlyprintk=ttyS1 tty0 reboot=k debug panic=1 pci=off root=/dev/vda1" create ; + --boot-args "console=ttyS0 console=ttyS1 earlyprintk=ttyS1 tty0 reboot=k debug panic=1 pci=off root=/dev/vda1" ``` > tips: console=ttyS0 is used to connect to the guest console. If serial path is not defined, Dragonball will use stdio to interact with the guest. @@ -44,12 +44,12 @@ Create a vsock console (communication with sock file) > Otherwise, `dbs-cli` will create a vsock console with a sock file, namely the value of `serial-path`. ``` -./dbs-cli \ +./dbs-cli create \ --log-file dbs-cli.log --log-level ERROR \ --kernel-path ~/path/to/kernel/vmlinux.bin \ --rootfs ~/path/to/rootfs/bionic.rootfs.ext4 \ --boot-args "console=ttyS0 console=ttyS1 earlyprintk=ttyS1 tty0 reboot=k debug panic=1 pci=off root=/dev/vda1" \ - --serial-path "/tmp/dbs" creare; + --serial-path "/tmp/dbs" ``` Create a virtio-vsock tunnel for Guest-to-Host communication. @@ -60,12 +60,12 @@ Create a virtio-vsock tunnel for Guest-to-Host communication. > specified with the `--vsock` parameter. ``` -./dbs-cli \ +./dbs-cli create \ --log-file dbs-cli.log --log-level ERROR \ --kernel-path ~/path/to/kernel/vmlinux.bin \ --rootfs ~/path/to/rootfs/bionic.rootfs.ext4 \ --boot-args "console=ttyS0 console=ttyS1 earlyprintk=ttyS1 tty0 reboot=k debug panic=1 pci=off root=/dev/vda1" \ - --vsock /tmp/vsock.sock create; + --vsock /tmp/vsock.sock ``` Create virtio-net devices. @@ -74,13 +74,12 @@ Create virtio-net devices. > format of JSON. ``` -./dbs-cli \ +./dbs-cli create \ --log-file dbs-cli.log --log-level ERROR \ --kernel-path ~/path/to/kernel/vmlinux.bin \ --rootfs ~/path/to/rootfs/bionic.rootfs.ext4 \ --boot-args "console=ttyS0 console=ttyS1 earlyprintk=ttyS1 tty0 reboot=k debug panic=1 pci=off root=/dev/vda1" \ - --virnets "[{\"iface_id\":\"eth0\",\"host_dev_name\":\"tap0\",\"num_queues\":2,\"queue_size\":0,\"guest_mac\":\"43:2D:9C:13:71:48\",\"allow_duplicate_mac\":true}]" \ - create; + --virnets "[{\"iface_id\":\"eth0\",\"host_dev_name\":\"tap0\",\"num_queues\":2,\"queue_size\":0,\"guest_mac\":\"43:2D:9C:13:71:48\",\"allow_duplicate_mac\":true}]" ``` Create virtio-blk devices. @@ -89,13 +88,12 @@ Create virtio-blk devices. > format of JSON. ``` -./dbs-cli \ +./dbs-cli create \ --log-file dbs-cli.log --log-level ERROR \ --kernel-path ~/path/to/kernel/vmlinux.bin \ --rootfs ~/path/to/rootfs/bionic.rootfs.ext4 \ --boot-args "console=ttyS0 console=ttyS1 earlyprintk=ttyS1 tty0 reboot=k debug panic=1 pci=off root=/dev/vda1" \ - --virblks '[{"drive_id":"testblk","device_type":"RawBlock","path_on_host":"/path/to/test.img","is_root_device":false,"is_read_only":false,"is_direct":false,"no_drop":false,"num_queues":1,"queue_size":1024}]' \ - create; + --virblks '[{"drive_id":"testblk","device_type":"RawBlock","path_on_host":"/path/to/test.img","is_root_device":false,"is_read_only":false,"is_direct":false,"no_drop":false,"num_queues":1,"queue_size":1024}]' ``` # 2. Usage @@ -108,7 +106,7 @@ After api socket created, you could use `./dbs-cli --api-sock-path [socket path] Cpu Hotplug via API Server: -`sudo ./dbs-cli --api-sock-path [socket path] --vcpu-resize 2 update` +`sudo ./dbs-cli --api-sock-path [socket path] update --vcpu-resize 2 ` Create hot-plug virtio-net devices via API Server: @@ -117,9 +115,8 @@ Create hot-plug virtio-net devices via API Server: ``` sudo ./dbs-cli \ - --api-sock-path [socket path] - --hotplug-virnets "[{\"iface_id\":\"eth0\",\"host_dev_name\":\"tap0\",\"num_queues\":2,\"queue_size\":0,\"guest_mac\":\"43:2D:9C:13:71:48\",\"allow_duplicate_mac\":true}]" \ - update + --api-sock-path [socket path] update \ + --hotplug-virnets "[{\"iface_id\":\"eth0\",\"host_dev_name\":\"tap0\",\"num_queues\":2, \"queue_size\":0,\"guest_mac\":\"43:2D:9C:13:71:48\",\"allow_duplicate_mac\":true}]" \ ``` Create hot-plug virtio-blk devices via API Server: @@ -129,11 +126,12 @@ Create hot-plug virtio-blk devices via API Server: ``` sudo ./dbs-cli \ - --api-sock-path [socket path] + --api-sock-path [socket path] update \ --hotplug-virblks '[{"drive_id":"testblk","device_type":"RawBlock","path_on_host":"/path/to/test.img","is_root_device":false,"is_read_only":false,"is_direct":false,"no_drop":false,"num_queues":1,"queue_size":1024}]' \ - update ``` +TODO : add document for hot-plug virtio-fs + ## 2. Exit vm > If you want to exit vm, just input `reboot` in vm's console. @@ -145,7 +143,7 @@ If you wish to modify some details or debug to figure out the fault of codes, yo ```bash cargo run -- --kernel-path ~/path/to/kernel/vmlinux.bin \ --rootfs ~/path/to/rootfs/rootfs.dmg \ - --boot-args "console=ttyS0 console=ttyS1 earlyprintk=ttyS1 tty0 reboot=k debug panic=1 pci=off root=/dev/vda1" ; + --boot-args "console=ttyS0 console=ttyS1 earlyprintk=ttyS1 tty0 reboot=k debug panic=1 pci=off root=/dev/vda1" ``` To see some help: diff --git a/src/api_client.rs b/src/api_client.rs index c047414..d8f7810 100644 --- a/src/api_client.rs +++ b/src/api_client.rs @@ -7,24 +7,24 @@ use std::os::unix::net::UnixStream; use anyhow::{Context, Result}; use serde_json::{json, Value}; -use crate::parser::DBSArgs; +use crate::parser::args::UpdateArgs; -pub fn run_api_client(args: DBSArgs) -> Result<()> { - if let Some(vcpu_resize_num) = args.update_args.vcpu_resize { +pub fn run_api_client(args: UpdateArgs, api_sock_path: &str) -> Result<()> { + if let Some(vcpu_resize_num) = args.vcpu_resize { let request = request_cpu_resize(vcpu_resize_num); - send_request(request, &args.api_sock_path)?; + send_request(request, api_sock_path)?; } - if let Some(config) = args.update_args.hotplug_virnets { + if let Some(config) = args.virnets { let request = request_virtio_net(&config); - send_request(request, &args.api_sock_path)?; + send_request(request, api_sock_path)?; } - if let Some(config) = args.update_args.hotplug_virblks { + if let Some(config) = args.virblks { let request = request_virtio_blk(&config); - send_request(request, &args.api_sock_path)?; + send_request(request, api_sock_path)?; } - if let Some(config) = args.update_args.patch_fs { + if let Some(config) = args.patch_fs { let request = request_patch_fs(&config); - send_request(request, &args.api_sock_path)?; + send_request(request, api_sock_path)?; } Ok(()) } diff --git a/src/api_server.rs b/src/api_server.rs index ad43fbe..609a8c3 100644 --- a/src/api_server.rs +++ b/src/api_server.rs @@ -3,24 +3,22 @@ // SPDX-License-Identifier: Apache-2.0 // -use std::sync::{Arc, Mutex}; - use std::io::prelude::*; use std::os::unix::net::{UnixListener, UnixStream}; +use std::sync::{Arc, Mutex}; use anyhow::{anyhow, Context, Result}; +use crossbeam_channel::{Receiver, Sender}; +use dragonball::api::v1::{VmmRequest, VmmResponse}; use dragonball::device_manager::blk_dev_mgr::BlockDeviceConfigInfo; use dragonball::device_manager::fs_dev_mgr::FsMountConfigInfo; use dragonball::device_manager::virtio_net_dev_mgr::VirtioNetDeviceConfigInfo; - -use crate::vmm_comm_trait::VMMComm; -use dragonball::api::v1::{VmmRequest, VmmResponse}; use dragonball::vcpu::VcpuResizeInfo; use serde_json::Value; - -use crossbeam_channel::{Receiver, Sender}; use vmm_sys_util::eventfd::EventFd; +use crate::vmm_comm_trait::VMMComm; + pub struct ApiServer { pub to_vmm: Option>, pub from_vmm: Option>>>, @@ -53,9 +51,9 @@ impl ApiServer { } } - pub fn run_api_server(&mut self, api_sock_path: &str) -> Result<()> { + pub fn run_api_server(&mut self, api_sock_path: String) -> Result<()> { + println!("dbs-cli: api server created in api_sock_path {:?}. Start waiting for connections from the client side.", &api_sock_path); let unix_listener = UnixListener::bind(api_sock_path)?; - println!("dbs-cli: api server created in api_sock_path {api_sock_path:?}. Start waiting for connections from the client side."); // put the server logic in a loop to accept several connections loop { diff --git a/src/cli_instance.rs b/src/cli_instance.rs index 0246318..b00341c 100644 --- a/src/cli_instance.rs +++ b/src/cli_instance.rs @@ -9,7 +9,7 @@ use std::{ sync::{Arc, Mutex, RwLock}, }; -use crate::vmm_comm_trait::VMMComm; +use crate::{parser::args::CreateArgs, vmm_comm_trait::VMMComm}; use anyhow::{anyhow, Result}; use crossbeam_channel::{Receiver, Sender}; use seccompiler::BpfProgram; @@ -25,8 +25,6 @@ use dragonball::{ vm::{CpuTopology, VmConfigInfo}, }; -use crate::parser::DBSArgs; - const DRAGONBALL_VERSION: &str = env!("CARGO_PKG_VERSION"); pub struct CliInstance { @@ -70,33 +68,33 @@ impl CliInstance { } } - pub fn run_vmm_server(&self, args: DBSArgs) -> Result<()> { - if args.boot_args.kernel_path.is_none() || args.boot_args.rootfs_args.rootfs.is_none() { + pub fn run_vmm_server(&self, args: CreateArgs) -> Result<()> { + if args.kernel_path.is_none() || args.rootfs_args.rootfs.is_none() { return Err(anyhow!( "kernel path or rootfs path cannot be None when creating the VM" )); } let mut serial_path: Option = None; - if args.create_args.serial_path != "stdio" { - serial_path = Some(args.create_args.serial_path); + if args.serial_path != "stdio" { + serial_path = Some(args.serial_path); } // configuration let vm_config = VmConfigInfo { - vcpu_count: args.create_args.vcpu, - max_vcpu_count: args.create_args.max_vcpu, - cpu_pm: args.create_args.cpu_pm.clone(), + vcpu_count: args.cpu.vcpu, + max_vcpu_count: args.cpu.max_vcpu, + cpu_pm: args.cpu.cpu_pm.clone(), cpu_topology: CpuTopology { - threads_per_core: args.create_args.cpu_topology.threads_per_core, - cores_per_die: args.create_args.cpu_topology.cores_per_die, - dies_per_socket: args.create_args.cpu_topology.dies_per_socket, - sockets: args.create_args.cpu_topology.sockets, + threads_per_core: args.cpu.cpu_topology.threads_per_core, + cores_per_die: args.cpu.cpu_topology.cores_per_die, + dies_per_socket: args.cpu.cpu_topology.dies_per_socket, + sockets: args.cpu.cpu_topology.sockets, }, - vpmu_feature: args.create_args.vpmu_feature, - mem_type: args.create_args.mem_type.clone(), - mem_file_path: args.create_args.mem_file_path.clone(), - mem_size_mib: args.create_args.mem_size, + vpmu_feature: args.cpu.vpmu_feature, + mem_type: args.mem.mem_type.clone(), + mem_file_path: args.mem.mem_file_path.clone(), + mem_size_mib: args.mem.mem_size, // as in crate `dragonball` serial_path will be assigned with a default value, // we need a special token to enable the stdio console. serial_path: serial_path.clone(), @@ -114,9 +112,9 @@ impl CliInstance { // boot source let boot_source_config = BootSourceConfig { // unwrap is safe because we have checked kernel_path in the beginning of run_vmm_server - kernel_path: args.boot_args.kernel_path.unwrap(), - initrd_path: args.boot_args.initrd_path.clone(), - boot_args: Some(args.boot_args.boot_args.clone()), + kernel_path: args.kernel_path.unwrap(), + initrd_path: args.initrd_path.clone(), + boot_args: Some(args.boot_args.clone()), }; // rootfs @@ -124,9 +122,9 @@ impl CliInstance { block_device_config_info = BlockDeviceConfigInfo { drive_id: String::from("rootfs"), // unwrap is safe because we have checked rootfs path in the beginning of run_vmm_server - path_on_host: PathBuf::from(&args.boot_args.rootfs_args.rootfs.unwrap()), - is_root_device: args.boot_args.rootfs_args.is_root, - is_read_only: args.boot_args.rootfs_args.is_read_only, + path_on_host: PathBuf::from(&args.rootfs_args.rootfs.unwrap()), + is_root_device: args.rootfs_args.is_root, + is_read_only: args.rootfs_args.is_read_only, ..block_device_config_info }; @@ -142,12 +140,12 @@ impl CliInstance { self.insert_block_device(block_device_config_info) .expect("failed to set block device"); - if !args.create_args.vsock.is_empty() { + if !args.vsock.is_empty() { // VSOCK config let mut vsock_config_info = VsockDeviceConfigInfo::default(); vsock_config_info = VsockDeviceConfigInfo { guest_cid: 42, // dummy value - uds_path: Some(args.create_args.vsock), + uds_path: Some(args.vsock), ..vsock_config_info }; @@ -156,28 +154,26 @@ impl CliInstance { .expect("failed to set vsock socket path"); } - if !args.create_args.virnets.is_empty() { - let configs: Vec = - serde_json::from_str(&args.create_args.virnets) - .expect("failed to parse virtio-net devices from JSON"); + if !args.virnets.is_empty() { + let configs: Vec = serde_json::from_str(&args.virnets) + .expect("failed to parse virtio-net devices from JSON"); for config in configs.into_iter() { self.insert_virnet(config) .expect("failed to insert a virtio-net device"); } } - if !args.create_args.virblks.is_empty() { - let configs: Vec = - serde_json::from_str(&args.create_args.virblks) - .expect("failed to parse virtio-blk devices from JSON"); + if !args.virblks.is_empty() { + let configs: Vec = serde_json::from_str(&args.virblks) + .expect("failed to parse virtio-blk devices from JSON"); for config in configs.into_iter() { self.insert_virblk(config) .expect("failed to insert a virtio-blk device"); } } - if !args.create_args.fs.is_empty() { - let fs_config: FsDeviceConfigInfo = serde_json::from_str(&args.create_args.fs) + if !args.fs.is_empty() { + let fs_config: FsDeviceConfigInfo = serde_json::from_str(&args.fs) .expect("failed to parse virtio-fs devices from JSON"); self.insert_fs(fs_config) .expect("failed to insert a virtio-fs device"); diff --git a/src/main.rs b/src/main.rs index 61a185c..dafa520 100644 --- a/src/main.rs +++ b/src/main.rs @@ -2,52 +2,29 @@ extern crate slog_term; -use std::str::FromStr; -use std::sync::Mutex; - use anyhow::Result; use api_client::run_api_client; use clap::Parser; -use slog::Drain; -use slog::*; -use slog_scope::set_global_logger; - use parser::run_with_cli; -use parser::Commands; -use parser::DBSArgs; + +use crate::parser::args::{Commands, DBSArgs}; mod api_client; mod api_server; mod cli_instance; mod parser; +mod utils; mod vmm_comm_trait; fn main() -> Result<()> { let args: DBSArgs = DBSArgs::parse(); match args.command { - Some(Commands::Create) => { - let log_file = &args.log_file; - let log_level = Level::from_str(&args.log_level).unwrap(); - - let file = std::fs::OpenOptions::new() - .truncate(true) - .read(true) - .create(true) - .write(true) - .open(log_file) - .expect("Cannot write to the log file."); - - let root = slog::Logger::root( - Mutex::new(slog_json::Json::default(file).filter_level(log_level)).map(slog::Fuse), - o!("version" => env!("CARGO_PKG_VERSION")), - ); - - let _guard = set_global_logger(root); - slog_stdlog::init().unwrap(); - run_with_cli(args)?; + Some(Commands::Create { create_args }) => { + utils::setup_db_log(&create_args.log_file, &create_args.log_level); + run_with_cli(create_args, &args.api_sock_path)?; } - Some(Commands::Update) => { - run_api_client(args)?; + Some(Commands::Update { update_args }) => { + run_api_client(update_args, &args.api_sock_path)?; } _ => { panic!("Invalid command provided for dbs-cli."); diff --git a/src/parser/args.rs b/src/parser/args.rs index 3aee9de..2d775c9 100644 --- a/src/parser/args.rs +++ b/src/parser/args.rs @@ -12,18 +12,6 @@ pub struct DBSArgs { #[clap(subcommand)] pub command: Option, - #[clap(flatten)] - pub create_args: CreateArgs, - - #[clap(flatten)] - pub boot_args: BootArgs, - - #[clap(long, value_parser, default_value = "dbs-cli.log", display_order = 1)] - pub log_file: String, - - #[clap(long, value_parser, default_value = "Info", display_order = 1)] - pub log_level: String, - #[clap( long, value_parser, @@ -32,20 +20,25 @@ pub struct DBSArgs { display_order = 2 )] pub api_sock_path: String, - - #[clap(flatten)] - pub update_args: UpdateArgs, } +#[allow(clippy::large_enum_variant)] #[derive(Subcommand, Debug, Clone)] pub enum Commands { /// Create Dragonball Instance - Create, + Create { + // create args are for setting up Dragonball CPU/ + #[clap(flatten)] + create_args: CreateArgs, + }, /// Connect to Dragonball Api Server and update the Dragonball VM (Must create a api socket when creating the Dragonball VM) - Update, + Update { + #[clap(flatten)] + update_args: UpdateArgs, + }, } -/// CPU related configurations +/// CPU topology related configurations #[derive(Args, Debug, Serialize, Deserialize, Clone)] pub struct CpuTopologyArgs { #[clap( @@ -120,68 +113,12 @@ pub struct RootfsArgs { #[derive(Args, Debug, Deserialize, Serialize, Clone)] pub struct CreateArgs { /// features of cpu - #[clap( - short = 'C', - long, - value_parser, - default_value_t = 1, - help = "The number of vcpu to start", - display_order = 1 - )] - pub vcpu: u8, - #[clap( - long, - value_parser, - default_value_t = 1, - help = "The max number of vpu can be added", - display_order = 1 - )] - pub max_vcpu: u8, - #[clap( - long, - value_parser, - default_value = "on", - help = "The cpu power management", - display_order = 1 - )] - pub cpu_pm: String, - #[clap( - long, - value_parser, - default_value_t = 0, - help = "vpmu support level", - display_order = 1 - )] - pub vpmu_feature: u8, #[clap(flatten)] - pub cpu_topology: CpuTopologyArgs, + pub cpu: CpuArgs, /// features of mem - #[clap( - long, - value_parser, - default_value = "shmem", - help = "Memory type that can be either hugetlbfs or shmem, default is shmem", - display_order = 2 - )] - pub mem_type: String, - #[clap( - long, - value_parser, - default_value = "", - help = "Memory file path", - display_order = 2 - )] - pub mem_file_path: String, - #[clap( - short, - long, - value_parser, - default_value_t = 128, - help = "The memory size in Mib", - display_order = 2 - )] - pub mem_size: usize, + #[clap(flatten)] + pub mem: MemArgs, // The serial path used to communicate with VM #[clap( @@ -237,12 +174,14 @@ The type of it is an array of BlockDeviceConfigInfo, e.g. display_order = 2 )] pub fs: String, -} -/// Config boot source including rootfs file path -#[derive(Args, Debug, Deserialize, Serialize, Clone)] -#[clap(arg_required_else_help = true)] -pub struct BootArgs { + // feature for log + #[clap(long, value_parser, default_value = "dbs-cli.log", display_order = 1)] + pub log_file: String, + + #[clap(long, value_parser, default_value = "Debug", display_order = 1)] + pub log_level: String, + #[clap( short, long, @@ -277,6 +216,74 @@ pub struct BootArgs { pub rootfs_args: RootfsArgs, } +#[derive(Args, Debug, Serialize, Deserialize, Clone)] +pub struct CpuArgs { + #[clap( + short = 'C', + long, + value_parser, + default_value_t = 1, + help = "The number of vcpu to start", + display_order = 1 + )] + pub vcpu: u8, + #[clap( + long, + value_parser, + default_value_t = 1, + help = "The max number of vpu can be added", + display_order = 1 + )] + pub max_vcpu: u8, + #[clap( + long, + value_parser, + default_value = "on", + help = "The cpu power management", + display_order = 1 + )] + pub cpu_pm: String, + #[clap( + long, + value_parser, + default_value_t = 0, + help = "vpmu support level", + display_order = 1 + )] + pub vpmu_feature: u8, + #[clap(flatten)] + pub cpu_topology: CpuTopologyArgs, +} + +#[derive(Args, Debug, Serialize, Deserialize, Clone)] +pub struct MemArgs { + #[clap( + long, + value_parser, + default_value = "shmem", + help = "Memory type that can be either hugetlbfs or shmem, default is shmem", + display_order = 2 + )] + pub mem_type: String, + #[clap( + long, + value_parser, + default_value = "", + help = "Memory file path", + display_order = 2 + )] + pub mem_file_path: String, + #[clap( + short, + long, + value_parser, + default_value_t = 128, + help = "The memory size in Mib", + display_order = 2 + )] + pub mem_size: usize, +} + #[derive(Args, Debug, Serialize, Deserialize, Clone)] pub struct UpdateArgs { #[clap( @@ -292,20 +299,20 @@ pub struct UpdateArgs { value_parser, help = r#"Insert hotplug virtio-net devices into the Dragonball. The type of it is an array of VirtioNetDeviceConfigInfo, e.g. - --hotplug-virnets '[{"iface_id":"eth0","host_dev_name":"tap0","num_queues":2,"queue_size":0,"allow_duplicate_mac":true}]'"#, + --virnets '[{"iface_id":"eth0","host_dev_name":"tap0","num_queues":2,"queue_size":0,"allow_duplicate_mac":true}]'"#, display_order = 2 )] - pub hotplug_virnets: Option, + pub virnets: Option, #[clap( long, value_parser, help = r#"Insert virtio-blk devices into the Dragonball. The type of it is an array of BlockDeviceConfigInfo, e.g. - --hotplug-virblks '[{"drive_id":"testblk","device_type":"RawBlock","path_on_host":"/path/to/test.img","is_root_device":false,"is_read_only":false,"is_direct":false,"no_drop":false,"num_queues":1,"queue_size":1024}]'"#, + --virblks '[{"drive_id":"testblk","device_type":"RawBlock","path_on_host":"/path/to/test.img","is_root_device":false,"is_read_only":false,"is_direct":false,"no_drop":false,"num_queues":1,"queue_size":1024}]'"#, display_order = 2 )] - pub hotplug_virblks: Option, + pub virblks: Option, #[clap( long, diff --git a/src/parser/mod.rs b/src/parser/mod.rs index d7d2ff6..83e5a3f 100644 --- a/src/parser/mod.rs +++ b/src/parser/mod.rs @@ -10,20 +10,18 @@ use std::{ }; use anyhow::Result; - -pub use args::Commands; -pub use args::DBSArgs; use crossbeam_channel::unbounded; use dragonball::{api::v1::VmmService, Vmm}; use crate::api_server::ApiServer; use crate::cli_instance::CliInstance; +use crate::parser::args::CreateArgs; pub mod args; const KVM_DEVICE: &str = "/dev/kvm"; -pub fn run_with_cli(args: DBSArgs) -> Result { +pub fn run_with_cli(create_args: CreateArgs, api_sock_path: &String) -> Result { let mut cli_instance = CliInstance::new("dbs-cli"); let kvm = OpenOptions::new().read(true).write(true).open(KVM_DEVICE)?; @@ -61,7 +59,7 @@ pub fn run_with_cli(args: DBSArgs) -> Result { ); // clone the arguments for other thread to use - let clone_args = args.clone(); + let clone_args = create_args.clone(); thread::Builder::new() .name("set_cfg".to_owned()) .spawn(move || { @@ -71,15 +69,18 @@ pub fn run_with_cli(args: DBSArgs) -> Result { }) .unwrap(); - if !args.api_sock_path.is_empty() { + if !api_sock_path.is_empty() { + let clone_api_sock_path = api_sock_path.to_string().clone(); thread::Builder::new() .name("api_server".to_owned()) .spawn(move || { api_server - .run_api_server(&args.api_sock_path) + .run_api_server(clone_api_sock_path) .expect("Failed to api server."); }) .unwrap(); + } else { + println!("Warning: api server is not created because --api-sock-path is not provided when creating VM. Update command is not supported."); } Ok(Vmm::run_vmm_event_loop( diff --git a/src/utils.rs b/src/utils.rs new file mode 100644 index 0000000..b8e4f72 --- /dev/null +++ b/src/utils.rs @@ -0,0 +1,27 @@ +use slog::Drain; +use slog::*; +use slog_scope::set_global_logger; + +use std::str::FromStr; +use std::sync::Mutex; + +pub fn setup_db_log(log_file_path: &String, log_level: &str) { + let log_level = Level::from_str(log_level).unwrap(); + + let file = std::fs::OpenOptions::new() + .truncate(true) + .read(true) + .create(true) + .write(true) + .open(log_file_path) + .expect("Cannot write to the log file."); + + let root = slog::Logger::root( + Mutex::new(slog_json::Json::default(file).filter_level(log_level)).map(slog::Fuse), + o!("version" => env!("CARGO_PKG_VERSION")), + ); + + let guard = set_global_logger(root); + guard.cancel_reset(); + slog_stdlog::init().unwrap(); +}