Skip to content

Commit

Permalink
dbs-cli: several refactor in cmd tool
Browse files Browse the repository at this point in the history
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 <[email protected]>
  • Loading branch information
studychao committed Nov 15, 2023
1 parent baa00ce commit 597ae08
Show file tree
Hide file tree
Showing 9 changed files with 207 additions and 203 deletions.
6 changes: 3 additions & 3 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

40 changes: 19 additions & 21 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,22 +15,22 @@ 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:

> 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.
Expand All @@ -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.
Expand All @@ -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.
Expand All @@ -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.
Expand All @@ -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
Expand All @@ -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:

Expand All @@ -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:
Expand All @@ -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.
Expand All @@ -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:
Expand Down
20 changes: 10 additions & 10 deletions src/api_client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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(())
}
Expand Down
16 changes: 7 additions & 9 deletions src/api_server.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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<Sender<VmmRequest>>,
pub from_vmm: Option<Arc<Mutex<Receiver<VmmResponse>>>>,
Expand Down Expand Up @@ -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 {
Expand Down
68 changes: 32 additions & 36 deletions src/cli_instance.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -25,8 +25,6 @@ use dragonball::{
vm::{CpuTopology, VmConfigInfo},
};

use crate::parser::DBSArgs;

const DRAGONBALL_VERSION: &str = env!("CARGO_PKG_VERSION");

pub struct CliInstance {
Expand Down Expand Up @@ -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<String> = 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(),
Expand All @@ -114,19 +112,19 @@ 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
let mut block_device_config_info = BlockDeviceConfigInfo::default();
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
};

Expand All @@ -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
};

Expand All @@ -156,28 +154,26 @@ impl CliInstance {
.expect("failed to set vsock socket path");
}

if !args.create_args.virnets.is_empty() {
let configs: Vec<VirtioNetDeviceConfigInfo> =
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<VirtioNetDeviceConfigInfo> = 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<BlockDeviceConfigInfo> =
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<BlockDeviceConfigInfo> = 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");
Expand Down
Loading

0 comments on commit 597ae08

Please sign in to comment.