mirror of
https://github.com/kata-containers/kata-containers.git
synced 2025-08-02 08:17:01 +00:00
runtime-rs: Support hotplugging block device via QMP
This commit introduces block device hotplugging capability using QMP commands. The implementation enables attaching raw block devices to a running VM through the following steps: 1.Block Device Configuration Uses `blockdev-add` QMP command to define a raw block backend with (1) Direct I/O mode (2) Configurable read-only flag (3) Host file/block device path (`/path/to/block`) 2.PCI Device Attachment, Attaches the block device via `device_add` QMP command as a `virtio-blk-pci` device: (1) Dynamically allocates PCI slots using `find_free_slot()` (2) Binds to user-specified PCIe bus (e.g., `pcie.1`) (3) Returns PCI path for further management Fixes #11143 Signed-off-by: alex.lyn <alex.lyn@antgroup.com>
This commit is contained in:
parent
80bd71bfcc
commit
2405301e2e
@ -6,7 +6,7 @@
|
||||
use crate::device::pci_path::PciPath;
|
||||
use crate::qemu::cmdline_generator::{DeviceVirtioNet, Netdev};
|
||||
|
||||
use anyhow::{anyhow, Result};
|
||||
use anyhow::{anyhow, Context, Result};
|
||||
use nix::sys::socket::{sendmsg, ControlMessage, MsgFlags};
|
||||
use std::convert::TryFrom;
|
||||
use std::fmt::{Debug, Error, Formatter};
|
||||
@ -489,6 +489,113 @@ impl Qmp {
|
||||
|
||||
Err(anyhow!("no target device found"))
|
||||
}
|
||||
|
||||
/// hotplug block device:
|
||||
/// {
|
||||
/// "execute": "blockdev-add",
|
||||
/// "arguments": {
|
||||
/// "node-name": "drive-0",
|
||||
/// "file": {"driver": "file", "filename": "/path/to/block"},
|
||||
/// "cache": {"direct": true},
|
||||
/// "read-only": false
|
||||
/// }
|
||||
/// }
|
||||
///
|
||||
/// {
|
||||
/// "execute": "device_add",
|
||||
/// "arguments": {
|
||||
/// "id": "drive-0",
|
||||
/// "driver": "virtio-blk-pci",
|
||||
/// "drive": "drive-0",
|
||||
/// "addr":"0x0",
|
||||
/// "bus": "pcie.1"
|
||||
/// }
|
||||
/// }
|
||||
pub fn hotplug_block_device(
|
||||
&mut self,
|
||||
block_driver: &str,
|
||||
device_id: &str,
|
||||
path_on_host: &str,
|
||||
is_direct: Option<bool>,
|
||||
is_readonly: bool,
|
||||
no_drop: bool,
|
||||
) -> Result<Option<PciPath>> {
|
||||
let (bus, slot) = self.find_free_slot()?;
|
||||
|
||||
// `blockdev-add`
|
||||
let node_name = format!("drive-{}", device_id);
|
||||
self.qmp
|
||||
.execute(&qmp::blockdev_add(qmp::BlockdevOptions::raw {
|
||||
base: qmp::BlockdevOptionsBase {
|
||||
detect_zeroes: None,
|
||||
cache: None,
|
||||
discard: None,
|
||||
force_share: None,
|
||||
auto_read_only: None,
|
||||
node_name: Some(node_name.clone()),
|
||||
read_only: None,
|
||||
},
|
||||
raw: qmp::BlockdevOptionsRaw {
|
||||
base: qmp::BlockdevOptionsGenericFormat {
|
||||
file: qmp::BlockdevRef::definition(Box::new(qmp::BlockdevOptions::file {
|
||||
base: qapi_qmp::BlockdevOptionsBase {
|
||||
auto_read_only: None,
|
||||
cache: if is_direct.is_none() {
|
||||
None
|
||||
} else {
|
||||
Some(qapi_qmp::BlockdevCacheOptions {
|
||||
direct: is_direct,
|
||||
no_flush: None,
|
||||
})
|
||||
},
|
||||
detect_zeroes: None,
|
||||
discard: None,
|
||||
force_share: None,
|
||||
node_name: None,
|
||||
read_only: Some(is_readonly),
|
||||
},
|
||||
file: qapi_qmp::BlockdevOptionsFile {
|
||||
aio: None,
|
||||
aio_max_batch: None,
|
||||
drop_cache: if !no_drop { None } else { Some(no_drop) },
|
||||
locking: None,
|
||||
pr_manager: None,
|
||||
x_check_cache_dropped: None,
|
||||
filename: path_on_host.to_owned(),
|
||||
},
|
||||
})),
|
||||
},
|
||||
offset: None,
|
||||
size: None,
|
||||
},
|
||||
}))
|
||||
.map_err(|e| anyhow!("blockdev_add {:?}", e))
|
||||
.map(|_| ())?;
|
||||
|
||||
// `device_add`
|
||||
let mut blkdev_add_args = Dictionary::new();
|
||||
blkdev_add_args.insert("addr".to_owned(), format!("{:02}", slot).into());
|
||||
blkdev_add_args.insert("drive".to_owned(), node_name.clone().into());
|
||||
self.qmp
|
||||
.execute(&qmp::device_add {
|
||||
bus: Some(bus),
|
||||
id: Some(node_name.clone()),
|
||||
driver: block_driver.to_string(),
|
||||
arguments: blkdev_add_args,
|
||||
})
|
||||
.map_err(|e| anyhow!("device_add {:?}", e))
|
||||
.map(|_| ())?;
|
||||
|
||||
let pci_path = self
|
||||
.get_device_by_qdev_id(&node_name)
|
||||
.context("get device by qdev_id failed")?;
|
||||
info!(
|
||||
sl!(),
|
||||
"hotplug_block_device return pci path: {:?}", &pci_path
|
||||
);
|
||||
|
||||
Ok(Some(pci_path))
|
||||
}
|
||||
}
|
||||
|
||||
fn vcpu_id_from_core_id(core_id: i64) -> String {
|
||||
|
Loading…
Reference in New Issue
Block a user