mirror of
https://github.com/kata-containers/kata-containers.git
synced 2026-07-07 19:06:16 +00:00
runtime-rs: wire guest_extension_images cold-plug
Add a serial_override field to BlockConfig and DeviceVirtioBlk so that extension images get a deterministic QEMU serial (extension-<name>) instead of the auto-generated image-<id>. This lets the guest discover each extension via /dev/disk/by-id/virtio-extension-<name>. Wire up the full cold-plug path for guest_extension_images: - sandbox.rs: iterate boot_info.guest_extension_images, create read-only BlockConfig entries with the correct serial_override, and push them as ResourceConfig::GuestExtensionImage. - resource lib.rs / manager_inner.rs: handle the new GuestExtensionImage variant by delegating to the existing block device path. - cmdline_generator.rs: use serial_override when present for the QEMU serial= parameter; append kata.extension.<name>.verity_params=... to the kernel command line for each extra image. - inner.rs: propagate serial_override from BlockConfig to the cmdline generator's add_block_device(). Signed-off-by: Fabiano Fidêncio <ffidencio@nvidia.com> Assisted-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
committed by
Fabiano Fidêncio
parent
f657d3729a
commit
e96b6c8b17
@@ -141,6 +141,12 @@ pub struct BlockConfig {
|
||||
|
||||
/// Physical sector size in bytes reported to the guest. 0 means use hypervisor default.
|
||||
pub physical_sector_size: u32,
|
||||
|
||||
/// Override the QEMU virtio serial for this device.
|
||||
/// When set, the device is discoverable in the guest via
|
||||
/// `/dev/disk/by-id/virtio-<serial>`.
|
||||
/// If empty, the default `image-{device_id}` serial is used.
|
||||
pub serial_override: String,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Default)]
|
||||
|
||||
@@ -209,6 +209,18 @@ impl Kernel {
|
||||
if config.disable_guest_selinux { 0 } else { 1 }
|
||||
)));
|
||||
|
||||
// Emit one kata.extension.<name>.verity_params entry per configured
|
||||
// extension. This is also the activation signal the guest-side systemd
|
||||
// generator and unit key on, so it must be emitted even when
|
||||
// verity_params is empty (e.g. an unmeasured extension on s390x): an
|
||||
// empty value renders as a bare key, which still activates the mount.
|
||||
for extra in &config.guest_extension_images {
|
||||
kernel_params.append(&mut KernelParams::from_string(&format!(
|
||||
"kata.extension.{}.verity_params={}",
|
||||
extra.name, extra.verity_params
|
||||
)));
|
||||
}
|
||||
|
||||
Ok(Kernel {
|
||||
path: config.boot_info.kernel.clone(),
|
||||
initrd_path: config.boot_info.initrd.clone(),
|
||||
@@ -1083,6 +1095,7 @@ struct DeviceVirtioBlk {
|
||||
share_rw: bool,
|
||||
discard: bool,
|
||||
devno: Option<String>,
|
||||
serial_override: Option<String>,
|
||||
}
|
||||
|
||||
impl DeviceVirtioBlk {
|
||||
@@ -1094,6 +1107,7 @@ impl DeviceVirtioBlk {
|
||||
share_rw: true,
|
||||
discard: false,
|
||||
devno,
|
||||
serial_override: None,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1114,6 +1128,11 @@ impl DeviceVirtioBlk {
|
||||
self.discard = discard;
|
||||
self
|
||||
}
|
||||
|
||||
fn set_serial_override(&mut self, serial: String) -> &mut Self {
|
||||
self.serial_override = Some(serial);
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
#[async_trait]
|
||||
@@ -1135,7 +1154,11 @@ impl ToQemuParams for DeviceVirtioBlk {
|
||||
if self.discard {
|
||||
params.push("discard=on".to_owned());
|
||||
}
|
||||
params.push(format!("serial=image-{}", self.id));
|
||||
let serial = match &self.serial_override {
|
||||
Some(s) => s.clone(),
|
||||
None => format!("image-{}", self.id),
|
||||
};
|
||||
params.push(format!("serial={serial}"));
|
||||
if let Some(devno) = &self.devno {
|
||||
params.push(format!("devno={devno}"));
|
||||
}
|
||||
@@ -2908,6 +2931,7 @@ impl<'a> QemuCmdLine<'a> {
|
||||
is_direct: bool,
|
||||
is_scsi: bool,
|
||||
discard_unmap: bool,
|
||||
serial_override: Option<&str>,
|
||||
) -> Result<()> {
|
||||
let mut backend = BlockBackend::new(device_id, path, is_direct);
|
||||
backend.set_discard_unmap(discard_unmap);
|
||||
@@ -2919,6 +2943,9 @@ impl<'a> QemuCmdLine<'a> {
|
||||
} else {
|
||||
let mut device = DeviceVirtioBlk::new(device_id, bus_type(), devno);
|
||||
device.set_discard(discard_unmap);
|
||||
if let Some(serial) = serial_override {
|
||||
device.set_serial_override(serial.to_string());
|
||||
}
|
||||
self.devices.push(Box::new(device));
|
||||
}
|
||||
|
||||
|
||||
@@ -141,8 +141,13 @@ impl QemuInner {
|
||||
&block_dev.config.path_on_host,
|
||||
block_dev.config.is_readonly,
|
||||
)?,
|
||||
KATA_CCW_DEV_TYPE | KATA_BLK_DEV_TYPE | KATA_SCSI_DEV_TYPE => cmdline
|
||||
.add_block_device(
|
||||
KATA_CCW_DEV_TYPE | KATA_BLK_DEV_TYPE | KATA_SCSI_DEV_TYPE => {
|
||||
let serial = if block_dev.config.serial_override.is_empty() {
|
||||
None
|
||||
} else {
|
||||
Some(block_dev.config.serial_override.as_str())
|
||||
};
|
||||
cmdline.add_block_device(
|
||||
block_dev.device_id.as_str(),
|
||||
&block_dev.config.path_on_host,
|
||||
block_dev
|
||||
@@ -151,7 +156,9 @@ impl QemuInner {
|
||||
.unwrap_or(self.config.blockdev_info.block_device_cache_direct),
|
||||
block_dev.config.driver_option.as_str() == KATA_SCSI_DEV_TYPE,
|
||||
block_dev.config.discard_unmap,
|
||||
)?,
|
||||
serial,
|
||||
)?
|
||||
}
|
||||
unsupported => {
|
||||
info!(sl!(), "unsupported block device driver: {}", unsupported)
|
||||
}
|
||||
|
||||
@@ -37,6 +37,7 @@ pub enum ResourceConfig {
|
||||
Network(NetworkConfig),
|
||||
ShareFs(SharedFsInfo),
|
||||
VmRootfs(BlockConfig),
|
||||
GuestExtensionImage(BlockConfig),
|
||||
HybridVsock(HybridVsockConfig),
|
||||
Vsock(VsockConfig),
|
||||
Protection(ProtectionDeviceConfig),
|
||||
|
||||
@@ -189,6 +189,11 @@ impl ResourceManagerInner {
|
||||
.await
|
||||
.context("do handle device failed.")?;
|
||||
}
|
||||
ResourceConfig::GuestExtensionImage(r) => {
|
||||
do_handle_device(&self.device_manager, &DeviceConfig::BlockCfg(r))
|
||||
.await
|
||||
.context("do handle extra image device failed.")?;
|
||||
}
|
||||
ResourceConfig::HybridVsock(hv) => {
|
||||
do_handle_device(&self.device_manager, &DeviceConfig::HybridVsockCfg(hv))
|
||||
.await
|
||||
|
||||
@@ -56,6 +56,7 @@ use kata_sys_util::protection::{available_guest_protection, GuestProtection};
|
||||
use kata_sys_util::spec::load_oci_spec;
|
||||
use kata_types::capabilities::CapabilityBits;
|
||||
use kata_types::config::hypervisor::Hypervisor as HypervisorConfig;
|
||||
use kata_types::config::hypervisor::{VIRTIO_BLK_CCW, VIRTIO_BLK_PCI};
|
||||
#[cfg(all(
|
||||
feature = "cloud-hypervisor",
|
||||
any(target_arch = "x86_64", target_arch = "aarch64")
|
||||
@@ -250,6 +251,15 @@ impl VirtSandbox {
|
||||
resource_configs.push(vm_rootfs);
|
||||
}
|
||||
|
||||
// prepare extra extension image device configs (e.g. CoCo extension)
|
||||
let extra_configs = self
|
||||
.prepare_guest_extension_images_config()
|
||||
.await
|
||||
.context("failed to prepare extra images device config")?;
|
||||
for block_config in extra_configs {
|
||||
resource_configs.push(ResourceConfig::GuestExtensionImage(block_config));
|
||||
}
|
||||
|
||||
// prepare protection device config
|
||||
let init_data = if let Some(initdata) = self
|
||||
.prepare_initdata_device_config(&self.hypervisor.hypervisor_config().await)
|
||||
@@ -623,6 +633,40 @@ impl VirtSandbox {
|
||||
}))
|
||||
}
|
||||
|
||||
async fn prepare_guest_extension_images_config(&self) -> Result<Vec<BlockConfig>> {
|
||||
let hv_config = self.hypervisor.hypervisor_config().await;
|
||||
let mut configs = Vec::new();
|
||||
|
||||
// Extension images must be cold-plugged as virtio-blk, because the
|
||||
// guest discovers each extension by its deterministic serial
|
||||
// (extension-<name>), and only virtio-blk devices carry that serial.
|
||||
// We therefore always enforce a virtio-blk transport here (the
|
||||
// architecture's virtio-blk-ccw on s390x, virtio-blk-pci elsewhere)
|
||||
// rather than reusing vm_rootfs_driver or block_device_driver: those
|
||||
// may resolve to a non-virtio-blk transport such as virtio-pmem
|
||||
// (NVDIMM, no serial) or virtio-scsi, which would leave the extension
|
||||
// undiscoverable and its mount unit would fail closed.
|
||||
let block_driver = if uses_native_ccw_bus() {
|
||||
VIRTIO_BLK_CCW.to_string()
|
||||
} else {
|
||||
VIRTIO_BLK_PCI.to_string()
|
||||
};
|
||||
for extra in &hv_config.guest_extension_images {
|
||||
if extra.path.is_empty() {
|
||||
continue;
|
||||
}
|
||||
configs.push(BlockConfig {
|
||||
path_on_host: extra.path.clone(),
|
||||
is_readonly: true,
|
||||
driver_option: block_driver.clone(),
|
||||
serial_override: format!("extension-{}", extra.name),
|
||||
..Default::default()
|
||||
});
|
||||
}
|
||||
|
||||
Ok(configs)
|
||||
}
|
||||
|
||||
async fn set_agent_policy(&self) -> Result<()> {
|
||||
// TODO: Exclude policy-related items from the annotations.
|
||||
let toml_config = self.resource_manager.config().await;
|
||||
|
||||
Reference in New Issue
Block a user