Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

dbs-cli: several refactor in cmd tool #26

Merged
merged 1 commit into from
Nov 15, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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}]' \
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ditto.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

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
Loading