mirror of
https://github.com/kata-containers/kata-containers.git
synced 2026-03-14 00:32:10 +00:00
Compare commits
14 Commits
sprt/disab
...
disable-gu
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b87b4dc3be | ||
|
|
11dfe0ffac | ||
|
|
701e67cfd6 | ||
|
|
d50f103a13 | ||
|
|
bd2428e19f | ||
|
|
13b8dda322 | ||
|
|
36ca7990aa | ||
|
|
9894e14e99 | ||
|
|
7357373dff | ||
|
|
56254ecdff | ||
|
|
be8a112316 | ||
|
|
ed415fa91a | ||
|
|
4a37f4c673 | ||
|
|
0db136cfa9 |
8
Cargo.lock
generated
8
Cargo.lock
generated
@@ -3945,9 +3945,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "rkyv"
|
||||
version = "0.7.46"
|
||||
version = "0.7.45"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2297bf9c81a3f0dc96bc9521370b88f054168c29826a75e89c55ff196e7ed6a1"
|
||||
checksum = "9008cd6385b9e161d8229e1f6549dd23c3d022f132a2ea37ac3a10ac4935779b"
|
||||
dependencies = [
|
||||
"bitvec",
|
||||
"bytecheck",
|
||||
@@ -3963,9 +3963,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "rkyv_derive"
|
||||
version = "0.7.46"
|
||||
version = "0.7.45"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "84d7b42d4b8d06048d3ac8db0eb31bcb942cbeb709f0b5f2b2ebde398d3038f5"
|
||||
checksum = "503d1d27590a2b0a3a4ca4c94755aa2875657196ecbf401a42eff41d7de532c0"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
|
||||
8
src/agent/Cargo.lock
generated
8
src/agent/Cargo.lock
generated
@@ -3488,9 +3488,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "rkyv"
|
||||
version = "0.7.46"
|
||||
version = "0.7.45"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2297bf9c81a3f0dc96bc9521370b88f054168c29826a75e89c55ff196e7ed6a1"
|
||||
checksum = "9008cd6385b9e161d8229e1f6549dd23c3d022f132a2ea37ac3a10ac4935779b"
|
||||
dependencies = [
|
||||
"bitvec",
|
||||
"bytecheck",
|
||||
@@ -3506,9 +3506,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "rkyv_derive"
|
||||
version = "0.7.46"
|
||||
version = "0.7.45"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "84d7b42d4b8d06048d3ac8db0eb31bcb942cbeb709f0b5f2b2ebde398d3038f5"
|
||||
checksum = "503d1d27590a2b0a3a4ca4c94755aa2875657196ecbf401a42eff41d7de532c0"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
|
||||
@@ -857,7 +857,7 @@ fn mount_from(
|
||||
dest.as_str(),
|
||||
Some(mount_typ.as_str()),
|
||||
flags,
|
||||
Some(d.as_str()).filter(|s| !s.is_empty()),
|
||||
Some(d.as_str()),
|
||||
)
|
||||
.inspect_err(|e| log_child!(cfd_log, "mount error: {:?}", e))?;
|
||||
|
||||
|
||||
@@ -180,7 +180,7 @@ DEFNETQUEUES := 1
|
||||
DEFENABLEANNOTATIONS := [\"enable_iommu\", \"virtio_fs_extra_args\", \"kernel_params\", \"kernel_verity_params\", \"default_vcpus\", \"default_memory\"]
|
||||
DEFENABLEANNOTATIONS_COCO := [\"enable_iommu\", \"virtio_fs_extra_args\", \"kernel_params\", \"kernel_verity_params\", \"default_vcpus\", \"default_memory\", \"cc_init_data\"]
|
||||
DEFDISABLEGUESTSECCOMP := true
|
||||
DEFDISABLEGUESTEMPTYDIR := false
|
||||
DEFDISABLEGUESTEMPTYDIR := true
|
||||
##VAR DEFAULTEXPFEATURES=[features] Default experimental features enabled
|
||||
DEFAULTEXPFEATURES := []
|
||||
DEFDISABLESELINUX := false
|
||||
@@ -298,7 +298,7 @@ ifneq (,$(CLHCMD))
|
||||
KERNELTYPE_CLH = uncompressed
|
||||
KERNEL_NAME_CLH = $(call MAKE_KERNEL_NAME,$(KERNELTYPE_CLH))
|
||||
KERNELPATH_CLH = $(KERNELDIR)/$(KERNEL_NAME_CLH)
|
||||
VMROOTFSDRIVER_CLH := virtio-blk-pci
|
||||
VMROOTFSDRIVER_CLH := virtio-pmem
|
||||
|
||||
DEFSANDBOXCGROUPONLY_CLH := true
|
||||
DEFSTATICRESOURCEMGMT_CLH := false
|
||||
|
||||
@@ -22,8 +22,6 @@ rootfs_type = @DEFROOTFSTYPE@
|
||||
|
||||
# Block storage driver to be used for the VM rootfs is backed
|
||||
# by a block device.
|
||||
#
|
||||
# virtio-pmem is not supported with Cloud Hypervisor.
|
||||
vm_rootfs_driver = "@VMROOTFSDRIVER_CLH@"
|
||||
|
||||
# Path to the firmware.
|
||||
|
||||
@@ -118,11 +118,13 @@ impl TryFrom<NamedHypervisorConfig> for VmConfig {
|
||||
|
||||
// Note how CH handles the different image types:
|
||||
//
|
||||
// - A standard image is specified in PmemConfig.
|
||||
// - An initrd/initramfs is specified in PayloadConfig.
|
||||
// - An image is specified in DiskConfig.
|
||||
// Note: pmem is not used as it's not properly supported by Cloud Hypervisor.
|
||||
// - A confidential guest image is specified by a DiskConfig.
|
||||
// - If TDX is enabled, the firmware (`td-shim` [1]) must be
|
||||
// specified in PayloadConfig.
|
||||
// - A confidential guest initrd is specified by a PayloadConfig with
|
||||
// firmware.
|
||||
//
|
||||
// [1] - https://github.com/confidential-containers/td-shim
|
||||
let boot_info = cfg.boot_info;
|
||||
@@ -138,6 +140,14 @@ impl TryFrom<NamedHypervisorConfig> for VmConfig {
|
||||
return Err(VmConfigError::NoBootFile);
|
||||
}
|
||||
|
||||
let pmem = if use_initrd || guest_protection_is_tdx(guest_protection_to_use.clone()) {
|
||||
None
|
||||
} else {
|
||||
let pmem = PmemConfig::try_from(&boot_info).map_err(VmConfigError::PmemError)?;
|
||||
|
||||
Some(vec![pmem])
|
||||
};
|
||||
|
||||
let payload = Some(
|
||||
PayloadConfig::try_from((
|
||||
boot_info.clone(),
|
||||
@@ -149,7 +159,7 @@ impl TryFrom<NamedHypervisorConfig> for VmConfig {
|
||||
|
||||
let mut disks: Vec<DiskConfig> = vec![];
|
||||
|
||||
if use_image {
|
||||
if use_image && guest_protection_is_tdx(guest_protection_to_use.clone()) {
|
||||
let disk = DiskConfig::try_from(boot_info).map_err(VmConfigError::DiskError)?;
|
||||
|
||||
disks.push(disk);
|
||||
@@ -189,6 +199,7 @@ impl TryFrom<NamedHypervisorConfig> for VmConfig {
|
||||
fs,
|
||||
net,
|
||||
devices: host_devices,
|
||||
pmem,
|
||||
disks,
|
||||
vsock: Some(vsock),
|
||||
rng,
|
||||
@@ -1645,6 +1656,7 @@ mod tests {
|
||||
let (memory_info_confidential_guest, mem_config_confidential_guest) =
|
||||
make_memory_objects(79, usable_max_mem_bytes, true);
|
||||
|
||||
let (_, pmem_config_with_image) = make_bootinfo_pmemconfig_objects(image);
|
||||
let (machine_info, rng_config) = make_machineinfo_rngconfig_objects(entropy_source);
|
||||
|
||||
let payload_firmware = None;
|
||||
@@ -1652,7 +1664,6 @@ mod tests {
|
||||
let (boot_info_with_initrd, payload_config_with_initrd) =
|
||||
make_bootinfo_payloadconfig_objects(kernel, initramfs, payload_firmware, None);
|
||||
|
||||
let (_, disk_config_with_image) = make_bootinfo_diskconfig_objects(image);
|
||||
let (_, disk_config_confidential_guest_image) = make_bootinfo_diskconfig_objects(image);
|
||||
|
||||
let boot_info_tdx_image = BootInfo {
|
||||
@@ -1751,7 +1762,7 @@ mod tests {
|
||||
vsock: Some(valid_vsock.clone()),
|
||||
|
||||
// rootfs image specific
|
||||
disks: Some(vec![disk_config_with_image]),
|
||||
pmem: Some(vec![pmem_config_with_image]),
|
||||
|
||||
payload: Some(PayloadConfig {
|
||||
kernel: Some(PathBuf::from(kernel)),
|
||||
|
||||
@@ -123,12 +123,7 @@ impl CloudHypervisorInner {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn set_hypervisor_config(&mut self, mut config: HypervisorConfig) {
|
||||
// virtio-pmem is not supported for Cloud Hypervisor.
|
||||
if config.boot_info.vm_rootfs_driver == crate::VM_ROOTFS_DRIVER_PMEM {
|
||||
config.boot_info.vm_rootfs_driver = crate::VM_ROOTFS_DRIVER_BLK.to_string();
|
||||
}
|
||||
|
||||
pub fn set_hypervisor_config(&mut self, config: HypervisorConfig) {
|
||||
self.config = config;
|
||||
}
|
||||
|
||||
|
||||
@@ -15,6 +15,7 @@ use crate::utils::vm_cleanup;
|
||||
use crate::utils::{bytes_to_megs, get_jailer_root, get_sandbox_path, megs_to_bytes};
|
||||
use crate::MemoryConfig;
|
||||
use crate::VM_ROOTFS_DRIVER_BLK;
|
||||
use crate::VM_ROOTFS_DRIVER_PMEM;
|
||||
use crate::{VcpuThreadIds, VmmState};
|
||||
use anyhow::{anyhow, Context, Result};
|
||||
use ch_config::ch_api::cloud_hypervisor_vm_netdev_add_with_fds;
|
||||
@@ -129,8 +130,12 @@ impl CloudHypervisorInner {
|
||||
let confidential_guest = cfg.security_info.confidential_guest;
|
||||
|
||||
// Note that the configuration option hypervisor.block_device_driver is not used.
|
||||
// NVDIMM is not supported for Cloud Hypervisor.
|
||||
let rootfs_driver = VM_ROOTFS_DRIVER_BLK;
|
||||
let rootfs_driver = if confidential_guest {
|
||||
// PMEM is not available with TDX.
|
||||
VM_ROOTFS_DRIVER_BLK
|
||||
} else {
|
||||
VM_ROOTFS_DRIVER_PMEM
|
||||
};
|
||||
|
||||
let rootfs_type = match cfg.boot_info.rootfs_type.is_empty() {
|
||||
true => DEFAULT_CH_ROOTFS_TYPE,
|
||||
@@ -150,7 +155,6 @@ impl CloudHypervisorInner {
|
||||
&cfg.boot_info.kernel_verity_params,
|
||||
rootfs_driver,
|
||||
rootfs_type,
|
||||
true,
|
||||
)?;
|
||||
|
||||
let mut console_params = if enable_debug {
|
||||
|
||||
@@ -150,7 +150,6 @@ impl DragonballInner {
|
||||
&self.config.boot_info.kernel_verity_params,
|
||||
&rootfs_driver,
|
||||
&self.config.boot_info.rootfs_type,
|
||||
true,
|
||||
)?;
|
||||
kernel_params.append(&mut rootfs_params);
|
||||
}
|
||||
|
||||
@@ -90,7 +90,6 @@ impl FcInner {
|
||||
&self.config.boot_info.kernel_verity_params,
|
||||
&self.config.blockdev_info.block_device_driver,
|
||||
&self.config.boot_info.rootfs_type,
|
||||
true,
|
||||
)?;
|
||||
kernel_params.append(&mut rootfs_params);
|
||||
kernel_params.append(&mut KernelParams::from_string(
|
||||
|
||||
@@ -10,8 +10,8 @@ use crate::{
|
||||
VM_ROOTFS_DRIVER_BLK, VM_ROOTFS_DRIVER_BLK_CCW, VM_ROOTFS_DRIVER_MMIO, VM_ROOTFS_DRIVER_PMEM,
|
||||
VM_ROOTFS_ROOT_BLK, VM_ROOTFS_ROOT_PMEM,
|
||||
};
|
||||
use kata_types::config::hypervisor::{parse_kernel_verity_params, VERITY_BLOCK_SIZE_BYTES};
|
||||
use kata_types::config::LOG_VPORT_OPTION;
|
||||
use kata_types::config::hypervisor::{parse_kernel_verity_params, VERITY_BLOCK_SIZE_BYTES};
|
||||
use kata_types::fs::{
|
||||
VM_ROOTFS_FILESYSTEM_EROFS, VM_ROOTFS_FILESYSTEM_EXT4, VM_ROOTFS_FILESYSTEM_XFS,
|
||||
};
|
||||
@@ -66,7 +66,8 @@ struct KernelVerityConfig {
|
||||
}
|
||||
|
||||
fn new_kernel_verity_params(params_string: &str) -> Result<Option<KernelVerityConfig>> {
|
||||
let cfg = parse_kernel_verity_params(params_string).map_err(|err| anyhow!(err.to_string()))?;
|
||||
let cfg = parse_kernel_verity_params(params_string)
|
||||
.map_err(|err| anyhow!(err.to_string()))?;
|
||||
|
||||
Ok(cfg.map(|params| KernelVerityConfig {
|
||||
root_hash: params.root_hash,
|
||||
@@ -144,7 +145,6 @@ impl KernelParams {
|
||||
kernel_verity_params: &str,
|
||||
rootfs_driver: &str,
|
||||
rootfs_type: &str,
|
||||
use_dax: bool,
|
||||
) -> Result<Self> {
|
||||
let mut params = vec![];
|
||||
|
||||
@@ -153,29 +153,16 @@ impl KernelParams {
|
||||
params.push(Param::new("root", VM_ROOTFS_ROOT_PMEM));
|
||||
match rootfs_type {
|
||||
VM_ROOTFS_FILESYSTEM_EXT4 => {
|
||||
if use_dax {
|
||||
params.push(Param::new(
|
||||
"rootflags",
|
||||
"dax,data=ordered,errors=remount-ro ro",
|
||||
));
|
||||
} else {
|
||||
params
|
||||
.push(Param::new("rootflags", "data=ordered,errors=remount-ro ro"));
|
||||
}
|
||||
params.push(Param::new(
|
||||
"rootflags",
|
||||
"dax,data=ordered,errors=remount-ro ro",
|
||||
));
|
||||
}
|
||||
VM_ROOTFS_FILESYSTEM_XFS => {
|
||||
if use_dax {
|
||||
params.push(Param::new("rootflags", "dax ro"));
|
||||
} else {
|
||||
params.push(Param::new("rootflags", "ro"));
|
||||
}
|
||||
params.push(Param::new("rootflags", "dax ro"));
|
||||
}
|
||||
VM_ROOTFS_FILESYSTEM_EROFS => {
|
||||
if use_dax {
|
||||
params.push(Param::new("rootflags", "dax ro"));
|
||||
} else {
|
||||
params.push(Param::new("rootflags", "ro"));
|
||||
}
|
||||
params.push(Param::new("rootflags", "dax ro"));
|
||||
}
|
||||
_ => {
|
||||
return Err(anyhow!("Unsupported rootfs type {}", rootfs_type));
|
||||
@@ -359,7 +346,6 @@ mod tests {
|
||||
struct TestData<'a> {
|
||||
rootfs_driver: &'a str,
|
||||
rootfs_type: &'a str,
|
||||
use_dax: bool,
|
||||
expect_params: KernelParams,
|
||||
result: Result<()>,
|
||||
}
|
||||
@@ -367,11 +353,10 @@ mod tests {
|
||||
#[test]
|
||||
fn test_rootfs_kernel_params() {
|
||||
let tests = &[
|
||||
// EXT4 with DAX
|
||||
// EXT4
|
||||
TestData {
|
||||
rootfs_driver: VM_ROOTFS_DRIVER_PMEM,
|
||||
rootfs_type: VM_ROOTFS_FILESYSTEM_EXT4,
|
||||
use_dax: true,
|
||||
expect_params: KernelParams {
|
||||
params: [
|
||||
Param::new("root", VM_ROOTFS_ROOT_PMEM),
|
||||
@@ -385,7 +370,6 @@ mod tests {
|
||||
TestData {
|
||||
rootfs_driver: VM_ROOTFS_DRIVER_BLK,
|
||||
rootfs_type: VM_ROOTFS_FILESYSTEM_EXT4,
|
||||
use_dax: true,
|
||||
expect_params: KernelParams {
|
||||
params: [
|
||||
Param::new("root", VM_ROOTFS_ROOT_BLK),
|
||||
@@ -396,15 +380,14 @@ mod tests {
|
||||
},
|
||||
result: Ok(()),
|
||||
},
|
||||
// XFS without DAX
|
||||
// XFS
|
||||
TestData {
|
||||
rootfs_driver: VM_ROOTFS_DRIVER_PMEM,
|
||||
rootfs_type: VM_ROOTFS_FILESYSTEM_XFS,
|
||||
use_dax: false,
|
||||
expect_params: KernelParams {
|
||||
params: [
|
||||
Param::new("root", VM_ROOTFS_ROOT_PMEM),
|
||||
Param::new("rootflags", "ro"),
|
||||
Param::new("rootflags", "dax ro"),
|
||||
Param::new("rootfstype", VM_ROOTFS_FILESYSTEM_XFS),
|
||||
]
|
||||
.to_vec(),
|
||||
@@ -414,7 +397,6 @@ mod tests {
|
||||
TestData {
|
||||
rootfs_driver: VM_ROOTFS_DRIVER_BLK,
|
||||
rootfs_type: VM_ROOTFS_FILESYSTEM_XFS,
|
||||
use_dax: true,
|
||||
expect_params: KernelParams {
|
||||
params: [
|
||||
Param::new("root", VM_ROOTFS_ROOT_BLK),
|
||||
@@ -425,11 +407,10 @@ mod tests {
|
||||
},
|
||||
result: Ok(()),
|
||||
},
|
||||
// EROFS with DAX
|
||||
// EROFS
|
||||
TestData {
|
||||
rootfs_driver: VM_ROOTFS_DRIVER_PMEM,
|
||||
rootfs_type: VM_ROOTFS_FILESYSTEM_EROFS,
|
||||
use_dax: true,
|
||||
expect_params: KernelParams {
|
||||
params: [
|
||||
Param::new("root", VM_ROOTFS_ROOT_PMEM),
|
||||
@@ -443,7 +424,6 @@ mod tests {
|
||||
TestData {
|
||||
rootfs_driver: VM_ROOTFS_DRIVER_BLK,
|
||||
rootfs_type: VM_ROOTFS_FILESYSTEM_EROFS,
|
||||
use_dax: true,
|
||||
expect_params: KernelParams {
|
||||
params: [
|
||||
Param::new("root", VM_ROOTFS_ROOT_BLK),
|
||||
@@ -458,7 +438,6 @@ mod tests {
|
||||
TestData {
|
||||
rootfs_driver: "foo",
|
||||
rootfs_type: VM_ROOTFS_FILESYSTEM_EXT4,
|
||||
use_dax: true,
|
||||
expect_params: KernelParams {
|
||||
params: [
|
||||
Param::new("root", VM_ROOTFS_ROOT_BLK),
|
||||
@@ -473,7 +452,6 @@ mod tests {
|
||||
TestData {
|
||||
rootfs_driver: VM_ROOTFS_DRIVER_BLK,
|
||||
rootfs_type: "foo",
|
||||
use_dax: true,
|
||||
expect_params: KernelParams {
|
||||
params: [
|
||||
Param::new("root", VM_ROOTFS_ROOT_BLK),
|
||||
@@ -488,12 +466,8 @@ mod tests {
|
||||
|
||||
for (i, t) in tests.iter().enumerate() {
|
||||
let msg = format!("test[{i}]: {t:?}");
|
||||
let result = KernelParams::new_rootfs_kernel_params(
|
||||
"",
|
||||
t.rootfs_driver,
|
||||
t.rootfs_type,
|
||||
t.use_dax,
|
||||
);
|
||||
let result =
|
||||
KernelParams::new_rootfs_kernel_params("", t.rootfs_driver, t.rootfs_type);
|
||||
let msg = format!("{msg}, result: {result:?}");
|
||||
if t.result.is_ok() {
|
||||
assert!(result.is_ok(), "{}", msg);
|
||||
@@ -512,7 +486,6 @@ mod tests {
|
||||
"root_hash=abc,salt=def,data_blocks=1,data_block_size=4096,hash_block_size=4096",
|
||||
VM_ROOTFS_DRIVER_BLK,
|
||||
VM_ROOTFS_FILESYSTEM_EXT4,
|
||||
false,
|
||||
)?;
|
||||
let params_string = params.to_string()?;
|
||||
assert!(params_string.contains("dm-mod.create="));
|
||||
@@ -523,7 +496,6 @@ mod tests {
|
||||
"root_hash=abc,data_blocks=1,data_block_size=4096,hash_block_size=4096",
|
||||
VM_ROOTFS_DRIVER_BLK,
|
||||
VM_ROOTFS_FILESYSTEM_EXT4,
|
||||
false,
|
||||
)
|
||||
.err()
|
||||
.expect("expected missing salt error");
|
||||
@@ -533,7 +505,6 @@ mod tests {
|
||||
"root_hash=abc,salt=def,data_block_size=4096,hash_block_size=4096",
|
||||
VM_ROOTFS_DRIVER_BLK,
|
||||
VM_ROOTFS_FILESYSTEM_EXT4,
|
||||
false,
|
||||
)
|
||||
.err()
|
||||
.expect("expected missing data_blocks error");
|
||||
@@ -543,7 +514,6 @@ mod tests {
|
||||
"root_hash=abc,salt=def,data_blocks=foo,data_block_size=4096,hash_block_size=4096",
|
||||
VM_ROOTFS_DRIVER_BLK,
|
||||
VM_ROOTFS_FILESYSTEM_EXT4,
|
||||
false,
|
||||
)
|
||||
.err()
|
||||
.expect("expected invalid data_blocks error");
|
||||
@@ -553,7 +523,6 @@ mod tests {
|
||||
"root_hash=abc,salt=def,data_blocks=1,data_block_size=4096,hash_block_size=4096,badfield",
|
||||
VM_ROOTFS_DRIVER_BLK,
|
||||
VM_ROOTFS_FILESYSTEM_EXT4,
|
||||
false,
|
||||
)
|
||||
.err()
|
||||
.expect("expected invalid entry error");
|
||||
|
||||
@@ -179,17 +179,10 @@ impl Kernel {
|
||||
let mut kernel_params = KernelParams::new(config.debug_info.enable_debug);
|
||||
|
||||
if config.boot_info.initrd.is_empty() {
|
||||
// DAX is disabled on ARM due to a kernel panic in caches_clean_inval_pou.
|
||||
#[cfg(target_arch = "aarch64")]
|
||||
let use_dax = false;
|
||||
#[cfg(not(target_arch = "aarch64"))]
|
||||
let use_dax = true;
|
||||
|
||||
let mut rootfs_params = KernelParams::new_rootfs_kernel_params(
|
||||
&config.boot_info.kernel_verity_params,
|
||||
&config.boot_info.vm_rootfs_driver,
|
||||
&config.boot_info.rootfs_type,
|
||||
use_dax,
|
||||
)
|
||||
.context("adding rootfs/verity params failed")?;
|
||||
kernel_params.append(&mut rootfs_params);
|
||||
|
||||
@@ -220,7 +220,7 @@ DEFBRIDGES := 1
|
||||
DEFENABLEANNOTATIONS := [\"enable_iommu\", \"virtio_fs_extra_args\", \"kernel_params\", \"kernel_verity_params\"]
|
||||
DEFENABLEANNOTATIONS_COCO := [\"enable_iommu\", \"virtio_fs_extra_args\", \"kernel_params\", \"kernel_verity_params\", \"default_vcpus\", \"default_memory\", \"cc_init_data\"]
|
||||
DEFDISABLEGUESTSECCOMP := true
|
||||
DEFDISABLEGUESTEMPTYDIR := false
|
||||
DEFDISABLEGUESTEMPTYDIR := true
|
||||
#Default experimental features enabled
|
||||
DEFAULTEXPFEATURES := []
|
||||
|
||||
@@ -288,7 +288,6 @@ DEFSTATICRESOURCEMGMT_NV = true
|
||||
|
||||
DEFDISABLEIMAGENVDIMM ?= false
|
||||
DEFDISABLEIMAGENVDIMM_NV = true
|
||||
DEFDISABLEIMAGENVDIMM_CLH ?= true
|
||||
|
||||
DEFBINDMOUNTS := []
|
||||
|
||||
@@ -789,7 +788,6 @@ USER_VARS += DEFVFIOMODE_SE
|
||||
USER_VARS += BUILDFLAGS
|
||||
USER_VARS += DEFDISABLEIMAGENVDIMM
|
||||
USER_VARS += DEFDISABLEIMAGENVDIMM_NV
|
||||
USER_VARS += DEFDISABLEIMAGENVDIMM_CLH
|
||||
USER_VARS += DEFCCAMEASUREMENTALGO
|
||||
USER_VARS += DEFSHAREDFS_QEMU_CCA_VIRTIOFS
|
||||
USER_VARS += DEFPODRESOURCEAPISOCK
|
||||
|
||||
@@ -348,15 +348,6 @@ func TestCheckHostIsVMContainerCapable(t *testing.T) {
|
||||
|
||||
defer func() {
|
||||
os.Remove(denylistModuleConf)
|
||||
// reload removed modules
|
||||
for mod := range archRequiredKernelModules {
|
||||
cmd := exec.Command(modProbeCmd, mod)
|
||||
if output, err := cmd.CombinedOutput(); err == nil {
|
||||
kataLog.WithField("output", string(output)).Info("module loaded")
|
||||
} else {
|
||||
kataLog.WithField("output", string(output)).Warn("failed to load module")
|
||||
}
|
||||
}
|
||||
}()
|
||||
|
||||
// remove the modules to force a failure
|
||||
|
||||
@@ -222,8 +222,8 @@ hypervisor_loglevel = 1
|
||||
# If false and nvdimm is supported, use nvdimm device to plug guest image.
|
||||
# Otherwise virtio-block device is used.
|
||||
#
|
||||
# nvdimm is not supported with Cloud Hypervisor or when `confidential_guest = true`.
|
||||
disable_image_nvdimm = @DEFDISABLEIMAGENVDIMM_CLH@
|
||||
# nvdimm is not supported when `confidential_guest = true`.
|
||||
disable_image_nvdimm = @DEFDISABLEIMAGENVDIMM@
|
||||
|
||||
# Enable hot-plugging of VFIO devices to a root-port.
|
||||
# The default setting is "no-port"
|
||||
|
||||
@@ -8,7 +8,6 @@
|
||||
package resourcecontrol
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
@@ -51,7 +50,7 @@ type LinuxCgroup struct {
|
||||
sync.Mutex
|
||||
}
|
||||
|
||||
func sandboxDevices() ([]specs.LinuxDeviceCgroup, error) {
|
||||
func sandboxDevices() []specs.LinuxDeviceCgroup {
|
||||
devices := []specs.LinuxDeviceCgroup{}
|
||||
|
||||
defaultDevices := []string{
|
||||
@@ -69,33 +68,14 @@ func sandboxDevices() ([]specs.LinuxDeviceCgroup, error) {
|
||||
// In order to run Virtual Machines and create virtqueues, hypervisors
|
||||
// need access to certain character devices in the host, like kvm and vhost-net.
|
||||
hypervisorDevices := []string{
|
||||
"/dev/kvm", // To run virtual machines with KVM
|
||||
"/dev/mshv", // To run virtual machines with Hyper-V
|
||||
}
|
||||
virtualDevices := []string{
|
||||
"/dev/kvm", // To run virtual machines with KVM
|
||||
"/dev/mshv", // To run virtual machines with Hyper-V
|
||||
"/dev/vhost-net", // To create virtqueues
|
||||
"/dev/vfio/vfio", // To access VFIO devices
|
||||
"/dev/vhost-vsock", // To interact with vsock if
|
||||
}
|
||||
|
||||
hypervisorDeviceAdded := false
|
||||
for _, hypervisor := range hypervisorDevices {
|
||||
hypervisorDevice, err := DeviceToLinuxDevice(hypervisor)
|
||||
if err != nil {
|
||||
if !os.IsNotExist(err) {
|
||||
controllerLogger.WithField("source", "cgroups").Warnf("Failed to add %s to the devices cgroup: %v", hypervisor, err)
|
||||
}
|
||||
continue
|
||||
}
|
||||
devices = append(devices, hypervisorDevice)
|
||||
hypervisorDeviceAdded = true
|
||||
controllerLogger.WithField("source", "cgroups").Infof("Adding %s to the devices cgroup", hypervisor)
|
||||
break
|
||||
}
|
||||
if !hypervisorDeviceAdded {
|
||||
return []specs.LinuxDeviceCgroup{}, errors.New("failed to add any hypervisor device to devices cgroup")
|
||||
}
|
||||
defaultDevices = append(defaultDevices, virtualDevices...)
|
||||
defaultDevices = append(defaultDevices, hypervisorDevices...)
|
||||
|
||||
for _, device := range defaultDevices {
|
||||
ldevice, err := DeviceToLinuxDevice(device)
|
||||
@@ -148,7 +128,7 @@ func sandboxDevices() ([]specs.LinuxDeviceCgroup, error) {
|
||||
|
||||
devices = append(devices, wildcardDevices...)
|
||||
|
||||
return devices, nil
|
||||
return devices
|
||||
}
|
||||
|
||||
func NewResourceController(path string, resources *specs.LinuxResources) (ResourceController, error) {
|
||||
@@ -188,11 +168,7 @@ func NewResourceController(path string, resources *specs.LinuxResources) (Resour
|
||||
|
||||
func NewSandboxResourceController(path string, resources *specs.LinuxResources, sandboxCgroupOnly bool) (ResourceController, error) {
|
||||
sandboxResources := *resources
|
||||
sandboxDevices, err := sandboxDevices()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
sandboxResources.Devices = append(sandboxResources.Devices, sandboxDevices...)
|
||||
sandboxResources.Devices = append(sandboxResources.Devices, sandboxDevices()...)
|
||||
|
||||
// Currently we know to handle systemd cgroup path only when it's the only cgroup (no overhead group), hence,
|
||||
// if sandboxCgroupOnly is not true we treat it as cgroupfs path as it used to be, although it may be incorrect.
|
||||
|
||||
@@ -131,11 +131,6 @@ func newTestSandboxConfigKataAgent() SandboxConfig {
|
||||
}
|
||||
|
||||
func TestCreateSandboxNoopAgentSuccessful(t *testing.T) {
|
||||
// GITHUB_RUNNER_CI_NON_VIRT is set to true in .github/workflows/build-checks.yaml file for ARM64 runners because the self hosted runners do not support Virtualization
|
||||
if os.Getenv("GITHUB_RUNNER_CI_NON_VIRT") == "true" {
|
||||
t.Skip("Skipping the test as the GitHub self hosted runners for ARM64 do not support Virtualization")
|
||||
}
|
||||
|
||||
assert := assert.New(t)
|
||||
if tc.NotValid(ktu.NeedRoot()) {
|
||||
t.Skip(testDisabledAsNonRoot)
|
||||
@@ -164,11 +159,6 @@ func TestCreateSandboxNoopAgentSuccessful(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestCreateSandboxKataAgentSuccessful(t *testing.T) {
|
||||
// GITHUB_RUNNER_CI_NON_VIRT is set to true in .github/workflows/build-checks.yaml file for ARM64 runners because the self hosted runners do not support Virtualization
|
||||
if os.Getenv("GITHUB_RUNNER_CI_NON_VIRT") == "true" {
|
||||
t.Skip("Skipping the test as the GitHub self hosted runners for ARM64 do not support Virtualization")
|
||||
}
|
||||
|
||||
assert := assert.New(t)
|
||||
if tc.NotValid(ktu.NeedRoot()) {
|
||||
t.Skip(testDisabledAsNonRoot)
|
||||
@@ -262,11 +252,6 @@ func createAndStartSandbox(ctx context.Context, config SandboxConfig) (sandbox V
|
||||
}
|
||||
|
||||
func TestReleaseSandbox(t *testing.T) {
|
||||
// GITHUB_RUNNER_CI_NON_VIRT is set to true in .github/workflows/build-checks.yaml file for ARM64 runners because the self hosted runners do not support Virtualization
|
||||
if os.Getenv("GITHUB_RUNNER_CI_NON_VIRT") == "true" {
|
||||
t.Skip("Skipping the test as the GitHub self hosted runners for ARM64 do not support Virtualization")
|
||||
}
|
||||
|
||||
if tc.NotValid(ktu.NeedRoot()) {
|
||||
t.Skip(testDisabledAsNonRoot)
|
||||
}
|
||||
@@ -284,11 +269,6 @@ func TestReleaseSandbox(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestCleanupContainer(t *testing.T) {
|
||||
// GITHUB_RUNNER_CI_NON_VIRT is set to true in .github/workflows/build-checks.yaml file for ARM64 runners because the self hosted runners do not support Virtualization
|
||||
if os.Getenv("GITHUB_RUNNER_CI_NON_VIRT") == "true" {
|
||||
t.Skip("Skipping the test as the GitHub self hosted runners for ARM64 do not support Virtualization")
|
||||
}
|
||||
|
||||
if tc.NotValid(ktu.NeedRoot()) {
|
||||
t.Skip(testDisabledAsNonRoot)
|
||||
}
|
||||
|
||||
@@ -332,9 +332,6 @@ func (clh *cloudHypervisor) getClhStopSandboxTimeout() time.Duration {
|
||||
func (clh *cloudHypervisor) setConfig(config *HypervisorConfig) error {
|
||||
clh.config = *config
|
||||
|
||||
// We don't support NVDIMM with Cloud Hypervisor.
|
||||
clh.config.DisableImageNvdimm = true
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -587,8 +584,8 @@ func (clh *cloudHypervisor) CreateVM(ctx context.Context, id string, network Net
|
||||
// Set initial amount of cpu's for the virtual machine
|
||||
clh.vmconfig.Cpus = chclient.NewCpusConfig(int32(clh.config.NumVCPUs()), int32(clh.config.DefaultMaxVCPUs))
|
||||
|
||||
disableNvdimm := true
|
||||
enableDax := false
|
||||
disableNvdimm := (clh.config.DisableImageNvdimm || clh.config.ConfidentialGuest)
|
||||
enableDax := !disableNvdimm
|
||||
|
||||
params, err := getNonUserDefinedKernelParams(hypervisorConfig.RootfsType, disableNvdimm, enableDax, clh.config.Debug, clh.config.ConfidentialGuest, clh.config.IOMMU, hypervisorConfig.KernelVerityParams)
|
||||
if err != nil {
|
||||
@@ -610,19 +607,31 @@ func (clh *cloudHypervisor) CreateVM(ctx context.Context, id string, network Net
|
||||
}
|
||||
|
||||
if assetType == types.ImageAsset {
|
||||
disk := chclient.NewDiskConfig()
|
||||
disk.Path = &assetPath
|
||||
disk.SetReadonly(true)
|
||||
if clh.config.DisableImageNvdimm || clh.config.ConfidentialGuest {
|
||||
disk := chclient.NewDiskConfig()
|
||||
disk.Path = &assetPath
|
||||
disk.SetReadonly(true)
|
||||
|
||||
diskRateLimiterConfig := clh.getDiskRateLimiterConfig()
|
||||
if diskRateLimiterConfig != nil {
|
||||
disk.SetRateLimiterConfig(*diskRateLimiterConfig)
|
||||
}
|
||||
diskRateLimiterConfig := clh.getDiskRateLimiterConfig()
|
||||
if diskRateLimiterConfig != nil {
|
||||
disk.SetRateLimiterConfig(*diskRateLimiterConfig)
|
||||
}
|
||||
|
||||
if clh.vmconfig.Disks != nil {
|
||||
*clh.vmconfig.Disks = append(*clh.vmconfig.Disks, *disk)
|
||||
if clh.vmconfig.Disks != nil {
|
||||
*clh.vmconfig.Disks = append(*clh.vmconfig.Disks, *disk)
|
||||
} else {
|
||||
clh.vmconfig.Disks = &[]chclient.DiskConfig{*disk}
|
||||
}
|
||||
} else {
|
||||
clh.vmconfig.Disks = &[]chclient.DiskConfig{*disk}
|
||||
pmem := chclient.NewPmemConfig(assetPath)
|
||||
*pmem.DiscardWrites = true
|
||||
pmem.SetIommu(clh.config.IOMMU)
|
||||
|
||||
if clh.vmconfig.Pmem != nil {
|
||||
*clh.vmconfig.Pmem = append(*clh.vmconfig.Pmem, *pmem)
|
||||
} else {
|
||||
clh.vmconfig.Pmem = &[]chclient.PmemConfig{*pmem}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// assetType == types.InitrdAsset
|
||||
|
||||
@@ -69,7 +69,6 @@ func newClhConfig() (HypervisorConfig, error) {
|
||||
NetRateLimiterOpsMaxRate: int64(0),
|
||||
NetRateLimiterOpsOneTimeBurst: int64(0),
|
||||
HotPlugVFIO: config.NoPort,
|
||||
DisableImageNvdimm: true,
|
||||
}, nil
|
||||
}
|
||||
|
||||
|
||||
@@ -83,9 +83,13 @@ type FilesystemShare struct {
|
||||
configVolRegex *regexp.Regexp
|
||||
// Regex to match only the timestamped directory inside the k8's volume mount
|
||||
timestampDirRegex *regexp.Regexp
|
||||
// The same volume mount can be shared by multiple containers in the same sandbox (pod)
|
||||
srcDstMap map[string][]string
|
||||
srcDstMapLock sync.Mutex
|
||||
// srcDstMap tracks file-level source to destination mappings for configmap/secret watching
|
||||
srcDstMap map[string][]string
|
||||
srcDstMapLock sync.Mutex
|
||||
// srcGuestMap caches volume source path to guest path, enabling multiple containers
|
||||
// in the same pod to share the same volume mount
|
||||
srcGuestMap map[string]string
|
||||
srcGuestMapLock sync.Mutex
|
||||
eventLoopStarted bool
|
||||
eventLoopStartedLock sync.Mutex
|
||||
watcherDoneChannel chan bool
|
||||
@@ -108,6 +112,7 @@ func NewFilesystemShare(s *Sandbox) (*FilesystemShare, error) {
|
||||
sandbox: s,
|
||||
watcherDoneChannel: make(chan bool),
|
||||
srcDstMap: make(map[string][]string),
|
||||
srcGuestMap: make(map[string]string),
|
||||
watcher: watcher,
|
||||
configVolRegex: configVolRegex,
|
||||
timestampDirRegex: timestampDirRegex,
|
||||
@@ -309,6 +314,13 @@ func (f *FilesystemShare) ShareFile(ctx context.Context, c *Container, m *Mount)
|
||||
// bind mount it in the shared directory.
|
||||
caps := f.sandbox.hypervisor.Capabilities(ctx)
|
||||
if !caps.IsFsSharingSupported() {
|
||||
f.srcGuestMapLock.Lock()
|
||||
if guestPath, ok := f.srcGuestMap[m.Source]; ok {
|
||||
f.srcGuestMapLock.Unlock()
|
||||
return &SharedFile{guestPath: guestPath}, nil
|
||||
}
|
||||
f.srcGuestMapLock.Unlock()
|
||||
|
||||
f.Logger().Debug("filesystem sharing is not supported, files will be copied")
|
||||
|
||||
var ignored bool
|
||||
@@ -418,6 +430,11 @@ func (f *FilesystemShare) ShareFile(ctx context.Context, c *Container, m *Mount)
|
||||
m.HostPath = mountDest
|
||||
}
|
||||
|
||||
// Cache the guestPath for this volume source so other containers can share it
|
||||
f.srcGuestMapLock.Lock()
|
||||
defer f.srcGuestMapLock.Unlock()
|
||||
f.srcGuestMap[m.Source] = guestPath
|
||||
|
||||
return &SharedFile{
|
||||
guestPath: guestPath,
|
||||
}, nil
|
||||
@@ -442,6 +459,10 @@ func (f *FilesystemShare) UnshareFile(ctx context.Context, c *Container, m *Moun
|
||||
}
|
||||
}
|
||||
|
||||
f.srcGuestMapLock.Lock()
|
||||
delete(f.srcGuestMap, m.Source)
|
||||
f.srcGuestMapLock.Unlock()
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
|
||||
@@ -1098,10 +1098,8 @@ func (q *qemu) LogAndWait(qemuCmd *exec.Cmd, reader io.ReadCloser) {
|
||||
q.Logger().WithField("qemuPid", pid).Error(text)
|
||||
}
|
||||
}
|
||||
q.Logger().WithField("qemuPid", pid).Infof("Stop logging QEMU")
|
||||
if err := qemuCmd.Wait(); err != nil {
|
||||
q.Logger().WithField("qemuPid", pid).WithField("error", err).Warn("QEMU exited with an error")
|
||||
}
|
||||
q.Logger().Infof("Stop logging QEMU (qemuPid=%d)", pid)
|
||||
qemuCmd.Wait()
|
||||
}
|
||||
|
||||
// StartVM will start the Sandbox's VM.
|
||||
|
||||
@@ -332,38 +332,6 @@ func TestQemuArchBaseAppendImage(t *testing.T) {
|
||||
assert.Equal(expectedOut, devices)
|
||||
}
|
||||
|
||||
func TestQemuArchBaseAppendNvdimmImage(t *testing.T) {
|
||||
var devices []govmmQemu.Device
|
||||
assert := assert.New(t)
|
||||
qemuArchBase := newQemuArchBase()
|
||||
|
||||
image, err := os.CreateTemp("", "img")
|
||||
assert.NoError(err)
|
||||
defer image.Close()
|
||||
defer os.Remove(image.Name())
|
||||
|
||||
imageStat, err := image.Stat()
|
||||
assert.NoError(err)
|
||||
|
||||
devices, err = qemuArchBase.appendNvdimmImage(devices, image.Name())
|
||||
assert.NoError(err)
|
||||
assert.Len(devices, 1)
|
||||
|
||||
expectedOut := []govmmQemu.Device{
|
||||
govmmQemu.Object{
|
||||
Driver: govmmQemu.NVDIMM,
|
||||
Type: govmmQemu.MemoryBackendFile,
|
||||
DeviceID: "nv0",
|
||||
ID: "mem0",
|
||||
MemPath: image.Name(),
|
||||
Size: (uint64)(imageStat.Size()),
|
||||
ReadOnly: true,
|
||||
},
|
||||
}
|
||||
|
||||
assert.Equal(expectedOut, devices)
|
||||
}
|
||||
|
||||
func TestQemuArchBaseAppendBridges(t *testing.T) {
|
||||
var devices []govmmQemu.Device
|
||||
assert := assert.New(t)
|
||||
|
||||
@@ -10,6 +10,7 @@ package virtcontainers
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"os"
|
||||
"time"
|
||||
|
||||
govmmQemu "github.com/kata-containers/kata-containers/src/runtime/pkg/govmm/qemu"
|
||||
@@ -68,10 +69,9 @@ func newQemuArch(config HypervisorConfig) (qemuArch, error) {
|
||||
kernelParamsDebug: kernelParamsDebug,
|
||||
kernelParams: kernelParams,
|
||||
disableNvdimm: config.DisableImageNvdimm,
|
||||
// DAX is disabled on ARM due to a kernel panic in caches_clean_inval_pou.
|
||||
dax: false,
|
||||
protection: noneProtection,
|
||||
legacySerial: config.LegacySerial,
|
||||
dax: true,
|
||||
protection: noneProtection,
|
||||
legacySerial: config.LegacySerial,
|
||||
},
|
||||
measurementAlgo: config.MeasurementAlgo,
|
||||
}
|
||||
@@ -109,6 +109,35 @@ func (q *qemuArm64) appendImage(ctx context.Context, devices []govmmQemu.Device,
|
||||
return q.appendBlockImage(ctx, devices, path)
|
||||
}
|
||||
|
||||
// There is no nvdimm/readonly feature in qemu 5.1 which is used by arm64 for now,
|
||||
// so we temporarily add this specific implementation for arm64 here until
|
||||
// the qemu used by arm64 is capable for that feature
|
||||
func (q *qemuArm64) appendNvdimmImage(devices []govmmQemu.Device, path string) ([]govmmQemu.Device, error) {
|
||||
imageFile, err := os.Open(path)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer imageFile.Close()
|
||||
|
||||
imageStat, err := imageFile.Stat()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
object := govmmQemu.Object{
|
||||
Driver: govmmQemu.NVDIMM,
|
||||
Type: govmmQemu.MemoryBackendFile,
|
||||
DeviceID: "nv0",
|
||||
ID: "mem0",
|
||||
MemPath: path,
|
||||
Size: (uint64)(imageStat.Size()),
|
||||
}
|
||||
|
||||
devices = append(devices, object)
|
||||
|
||||
return devices, nil
|
||||
}
|
||||
|
||||
func (q *qemuArm64) setIgnoreSharedMemoryMigrationCaps(_ context.Context, _ *govmmQemu.QMP) error {
|
||||
// x-ignore-shared not support in arm64 for now
|
||||
return nil
|
||||
|
||||
@@ -130,6 +130,39 @@ func TestQemuArm64AppendImage(t *testing.T) {
|
||||
assert.Equal(expectedOut, devices)
|
||||
}
|
||||
|
||||
func TestQemuArm64AppendNvdimmImage(t *testing.T) {
|
||||
var devices []govmmQemu.Device
|
||||
assert := assert.New(t)
|
||||
|
||||
f, err := os.CreateTemp("", "img")
|
||||
assert.NoError(err)
|
||||
defer func() { _ = f.Close() }()
|
||||
defer func() { _ = os.Remove(f.Name()) }()
|
||||
|
||||
imageStat, err := f.Stat()
|
||||
assert.NoError(err)
|
||||
|
||||
cfg := qemuConfig(QemuVirt)
|
||||
cfg.ImagePath = f.Name()
|
||||
arm64, err := newQemuArch(cfg)
|
||||
assert.NoError(err)
|
||||
|
||||
expectedOut := []govmmQemu.Device{
|
||||
govmmQemu.Object{
|
||||
Driver: govmmQemu.NVDIMM,
|
||||
Type: govmmQemu.MemoryBackendFile,
|
||||
DeviceID: "nv0",
|
||||
ID: "mem0",
|
||||
MemPath: f.Name(),
|
||||
Size: (uint64)(imageStat.Size()),
|
||||
},
|
||||
}
|
||||
|
||||
devices, err = arm64.appendNvdimmImage(devices, f.Name())
|
||||
assert.NoError(err)
|
||||
assert.Equal(expectedOut, devices)
|
||||
}
|
||||
|
||||
func TestQemuArm64WithInitrd(t *testing.T) {
|
||||
assert := assert.New(t)
|
||||
|
||||
|
||||
@@ -50,11 +50,6 @@ func testCreateSandbox(t *testing.T, id string,
|
||||
nconfig NetworkConfig, containers []ContainerConfig,
|
||||
volumes []types.Volume) (*Sandbox, error) {
|
||||
|
||||
// GITHUB_RUNNER_CI_NON_VIRT is set to true in .github/workflows/build-checks.yaml file for ARM64 runners because the self hosted runners do not support Virtualization
|
||||
if os.Getenv("GITHUB_RUNNER_CI_NON_VIRT") == "true" {
|
||||
t.Skip("Skipping the test as the GitHub self hosted runners for ARM64 do not support Virtualization")
|
||||
}
|
||||
|
||||
if tc.NotValid(ktu.NeedRoot()) {
|
||||
t.Skip(testDisabledAsNonRoot)
|
||||
}
|
||||
@@ -1312,10 +1307,6 @@ func checkSandboxRemains() error {
|
||||
}
|
||||
|
||||
func TestSandboxCreationFromConfigRollbackFromCreateSandbox(t *testing.T) {
|
||||
// GITHUB_RUNNER_CI_NON_VIRT is set to true in .github/workflows/build-checks.yaml file for ARM64 runners because the self hosted runners do not support Virtualization
|
||||
if os.Getenv("GITHUB_RUNNER_CI_NON_VIRT") == "true" {
|
||||
t.Skip("Skipping the test as the GitHub self hosted runners for ARM64 do not support Virtualization")
|
||||
}
|
||||
defer cleanUp()
|
||||
assert := assert.New(t)
|
||||
ctx := context.Background()
|
||||
@@ -1407,10 +1398,6 @@ func TestSandboxExperimentalFeature(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestSandbox_Cgroups(t *testing.T) {
|
||||
// GITHUB_RUNNER_CI_NON_VIRT is set to true in .github/workflows/build-checks.yaml file for ARM64 runners because the self hosted runners do not support Virtualization
|
||||
if os.Getenv("GITHUB_RUNNER_CI_NON_VIRT") == "true" {
|
||||
t.Skip("Skipping the test as the GitHub self hosted runners for ARM64 do not support Virtualization")
|
||||
}
|
||||
sandboxContainer := ContainerConfig{}
|
||||
sandboxContainer.Annotations = make(map[string]string)
|
||||
sandboxContainer.Annotations[annotations.ContainerTypeKey] = string(PodSandbox)
|
||||
|
||||
8
src/tools/agent-ctl/Cargo.lock
generated
8
src/tools/agent-ctl/Cargo.lock
generated
@@ -4544,9 +4544,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "rkyv"
|
||||
version = "0.7.46"
|
||||
version = "0.7.43"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2297bf9c81a3f0dc96bc9521370b88f054168c29826a75e89c55ff196e7ed6a1"
|
||||
checksum = "527a97cdfef66f65998b5f3b637c26f5a5ec09cc52a3f9932313ac645f4190f5"
|
||||
dependencies = [
|
||||
"bitvec",
|
||||
"bytecheck",
|
||||
@@ -4562,9 +4562,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "rkyv_derive"
|
||||
version = "0.7.46"
|
||||
version = "0.7.43"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "84d7b42d4b8d06048d3ac8db0eb31bcb942cbeb709f0b5f2b2ebde398d3038f5"
|
||||
checksum = "b5c462a1328c8e67e4d6dbad1eb0355dd43e8ab432c6e227a43657f16ade5033"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
|
||||
8
src/tools/genpolicy/Cargo.lock
generated
8
src/tools/genpolicy/Cargo.lock
generated
@@ -2449,9 +2449,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "rkyv"
|
||||
version = "0.7.46"
|
||||
version = "0.7.45"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2297bf9c81a3f0dc96bc9521370b88f054168c29826a75e89c55ff196e7ed6a1"
|
||||
checksum = "9008cd6385b9e161d8229e1f6549dd23c3d022f132a2ea37ac3a10ac4935779b"
|
||||
dependencies = [
|
||||
"bitvec",
|
||||
"bytecheck",
|
||||
@@ -2467,9 +2467,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "rkyv_derive"
|
||||
version = "0.7.46"
|
||||
version = "0.7.45"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "84d7b42d4b8d06048d3ac8db0eb31bcb942cbeb709f0b5f2b2ebde398d3038f5"
|
||||
checksum = "503d1d27590a2b0a3a4ca4c94755aa2875657196ecbf401a42eff41d7de532c0"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
|
||||
@@ -152,17 +152,6 @@
|
||||
}
|
||||
},
|
||||
"volumes": {
|
||||
"emptyDir": {
|
||||
"mount_type": "local",
|
||||
"mount_source": "^$(cpath)/$(sandbox-id)/rootfs/local/",
|
||||
"mount_point": "^$(cpath)/$(sandbox-id)/rootfs/local/",
|
||||
"driver": "local",
|
||||
"source": "local",
|
||||
"fstype": "local",
|
||||
"options": [
|
||||
"mode=0777"
|
||||
]
|
||||
},
|
||||
"emptyDir_memory": {
|
||||
"mount_type": "bind",
|
||||
"mount_source": "^/run/kata-containers/sandbox/ephemeral/",
|
||||
|
||||
@@ -1160,7 +1160,7 @@ mount_source_allows(p_mount, i_mount, bundle_id, sandbox_id) if {
|
||||
regex3 := replace(regex2, "$(cpath)", policy_data.common.cpath)
|
||||
print("mount_source_allows 2: regex3 =", regex3)
|
||||
|
||||
regex4 := replace(regex3, "$(sandbox-id)", sandbox_id)
|
||||
regex4 := replace(regex3, "$(bundle-id)", "[a-z0-9]{64}")
|
||||
print("mount_source_allows 2: regex4 =", regex4)
|
||||
regex.match(regex4, i_mount.source)
|
||||
|
||||
|
||||
@@ -105,7 +105,6 @@ pub fn get_mount_and_storage(
|
||||
storages: &mut Vec<agent::Storage>,
|
||||
yaml_volume: &volume::Volume,
|
||||
yaml_mount: &pod::VolumeMount,
|
||||
pod_security_context: &Option<pod::PodSecurityContext>,
|
||||
) {
|
||||
debug!(
|
||||
"get_mount_and_storage: adding mount and storage for: {:?}",
|
||||
@@ -113,27 +112,18 @@ pub fn get_mount_and_storage(
|
||||
);
|
||||
|
||||
if let Some(emptyDir) = &yaml_volume.emptyDir {
|
||||
let settings_volumes = &settings.volumes;
|
||||
let mut volume: Option<&settings::EmptyDirVolume> = None;
|
||||
|
||||
if let Some(medium) = &emptyDir.medium {
|
||||
if medium == "Memory" {
|
||||
volume = Some(&settings_volumes.emptyDir_memory);
|
||||
}
|
||||
let is_tmpfs = emptyDir.medium.as_ref().is_some_and(|m| m == "Memory");
|
||||
if is_tmpfs {
|
||||
get_memory_empty_dir_mount_and_storage(settings, p_mounts, storages, yaml_mount);
|
||||
} else {
|
||||
let access = if yaml_mount.readOnly == Some(true) {
|
||||
debug!("setting read only access for emptyDir mount");
|
||||
"ro"
|
||||
} else {
|
||||
"rw"
|
||||
};
|
||||
get_shared_bind_mount(yaml_mount, p_mounts, "rprivate", access);
|
||||
}
|
||||
|
||||
if volume.is_none() {
|
||||
volume = Some(&settings_volumes.emptyDir);
|
||||
}
|
||||
|
||||
get_empty_dir_mount_and_storage(
|
||||
settings,
|
||||
p_mounts,
|
||||
storages,
|
||||
yaml_mount,
|
||||
volume.unwrap(),
|
||||
pod_security_context,
|
||||
);
|
||||
} else if yaml_volume.persistentVolumeClaim.is_some() || yaml_volume.azureFile.is_some() {
|
||||
get_shared_bind_mount(yaml_mount, p_mounts, "rprivate", "rw");
|
||||
} else if yaml_volume.hostPath.is_some() {
|
||||
@@ -149,50 +139,25 @@ pub fn get_mount_and_storage(
|
||||
}
|
||||
}
|
||||
|
||||
fn get_empty_dir_mount_and_storage(
|
||||
fn get_memory_empty_dir_mount_and_storage(
|
||||
settings: &settings::Settings,
|
||||
p_mounts: &mut Vec<policy::KataMount>,
|
||||
storages: &mut Vec<agent::Storage>,
|
||||
yaml_mount: &pod::VolumeMount,
|
||||
settings_empty_dir: &settings::EmptyDirVolume,
|
||||
pod_security_context: &Option<pod::PodSecurityContext>,
|
||||
) {
|
||||
debug!("Settings emptyDir: {:?}", settings_empty_dir);
|
||||
let settings_empty_dir = &settings.volumes.emptyDir_memory;
|
||||
debug!("Settings emptyDir_memory: {:?}", settings_empty_dir);
|
||||
|
||||
if yaml_mount.subPathExpr.is_none() {
|
||||
let mut options = settings_empty_dir.options.clone();
|
||||
if let Some(gid) = pod_security_context.as_ref().and_then(|sc| sc.fsGroup) {
|
||||
// This matches the runtime behavior of only setting the fsgid if the mountpoint GID is not 0.
|
||||
// https://github.com/kata-containers/kata-containers/blob/b69da5f3ba8385c5833b31db41a846a203812675/src/runtime/virtcontainers/kata_agent.go#L1602-L1607
|
||||
if gid != 0 {
|
||||
options.push(format!("fsgid={gid}"));
|
||||
}
|
||||
}
|
||||
storages.push(agent::Storage {
|
||||
driver: settings_empty_dir.driver.clone(),
|
||||
driver_options: Vec::new(),
|
||||
source: settings_empty_dir.source.clone(),
|
||||
fstype: settings_empty_dir.fstype.clone(),
|
||||
options,
|
||||
mount_point: format!("{}{}$", &settings_empty_dir.mount_point, &yaml_mount.name),
|
||||
fs_group: protobuf::MessageField::none(),
|
||||
special_fields: ::protobuf::SpecialFields::new(),
|
||||
});
|
||||
}
|
||||
|
||||
let source = if yaml_mount.subPathExpr.is_some() {
|
||||
let file_name = Path::new(&yaml_mount.mountPath).file_name().unwrap();
|
||||
let name = OsString::from(file_name).into_string().unwrap();
|
||||
format!("{}{name}$", &settings.volumes.configMap.mount_source)
|
||||
} else {
|
||||
format!("{}{}$", &settings_empty_dir.mount_source, &yaml_mount.name)
|
||||
};
|
||||
|
||||
let mount_type = if yaml_mount.subPathExpr.is_some() {
|
||||
"bind"
|
||||
} else {
|
||||
&settings_empty_dir.mount_type
|
||||
};
|
||||
storages.push(agent::Storage {
|
||||
driver: settings_empty_dir.driver.clone(),
|
||||
driver_options: Vec::new(),
|
||||
source: settings_empty_dir.source.clone(),
|
||||
fstype: settings_empty_dir.fstype.clone(),
|
||||
options: settings_empty_dir.options.clone(),
|
||||
mount_point: format!("{}{}$", &settings_empty_dir.mount_point, &yaml_mount.name),
|
||||
fs_group: protobuf::MessageField::none(),
|
||||
special_fields: ::protobuf::SpecialFields::new(),
|
||||
});
|
||||
|
||||
let access = match yaml_mount.readOnly {
|
||||
Some(true) => {
|
||||
@@ -204,8 +169,8 @@ fn get_empty_dir_mount_and_storage(
|
||||
|
||||
p_mounts.push(policy::KataMount {
|
||||
destination: yaml_mount.mountPath.to_string(),
|
||||
type_: mount_type.to_string(),
|
||||
source,
|
||||
type_: settings_empty_dir.mount_type.clone(),
|
||||
source: format!("{}{}$", &settings_empty_dir.mount_source, &yaml_mount.name),
|
||||
options: vec![
|
||||
"rbind".to_string(),
|
||||
"rprivate".to_string(),
|
||||
@@ -318,13 +283,7 @@ fn get_shared_bind_mount(
|
||||
propagation: &str,
|
||||
access: &str,
|
||||
) {
|
||||
// The Kata Shim filepath.Base() to extract the last element of this path, in
|
||||
// https://github.com/kata-containers/kata-containers/blob/5e46f814dd79ab6b34588a83825260413839735a/src/runtime/virtcontainers/fs_share_linux.go#L305
|
||||
// In Rust, Path::file_name() has a similar behavior.
|
||||
let path = Path::new(&yaml_mount.mountPath);
|
||||
let mount_path = path.file_name().unwrap().to_str().unwrap();
|
||||
|
||||
let source = format!("$(sfprefix){mount_path}$");
|
||||
let source = "$(sfprefix)[a-zA-Z0-9_.-]+$".to_string();
|
||||
|
||||
let dest = yaml_mount.mountPath.clone();
|
||||
let type_ = "bind".to_string();
|
||||
|
||||
@@ -31,7 +31,6 @@ pub struct Settings {
|
||||
/// Volume settings loaded from genpolicy-settings.json.
|
||||
#[derive(Clone, Debug, Serialize, Deserialize)]
|
||||
pub struct Volumes {
|
||||
pub emptyDir: EmptyDirVolume,
|
||||
pub emptyDir_memory: EmptyDirVolume,
|
||||
pub configMap: ConfigMapVolume,
|
||||
pub image_volume: ImageVolume,
|
||||
|
||||
@@ -304,7 +304,6 @@ pub fn get_container_mounts_and_storages(
|
||||
storages,
|
||||
volume,
|
||||
volume_mount,
|
||||
&podSpec.securityContext,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
8
src/tools/kata-ctl/Cargo.lock
generated
8
src/tools/kata-ctl/Cargo.lock
generated
@@ -3349,9 +3349,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "rkyv"
|
||||
version = "0.7.46"
|
||||
version = "0.7.44"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2297bf9c81a3f0dc96bc9521370b88f054168c29826a75e89c55ff196e7ed6a1"
|
||||
checksum = "5cba464629b3394fc4dbc6f940ff8f5b4ff5c7aef40f29166fd4ad12acbc99c0"
|
||||
dependencies = [
|
||||
"bitvec",
|
||||
"bytecheck",
|
||||
@@ -3367,9 +3367,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "rkyv_derive"
|
||||
version = "0.7.46"
|
||||
version = "0.7.44"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "84d7b42d4b8d06048d3ac8db0eb31bcb942cbeb709f0b5f2b2ebde398d3038f5"
|
||||
checksum = "a7dddfff8de25e6f62b9d64e6e432bf1c6736c57d20323e15ee10435fbda7c65"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
|
||||
@@ -52,10 +52,7 @@ mem/B # For terms like "virtio-mem"
|
||||
memdisk/B
|
||||
MDEV/AB
|
||||
NEMU/AB
|
||||
NFD/AB # Node Feature Discovery
|
||||
NIC/AB
|
||||
nodeSelector/B # Kubernetes RuntimeClass scheduling field
|
||||
nodeSelectors/B
|
||||
nv/AB # NVIDIA abbreviation (lowercase)
|
||||
NVDIMM/AB
|
||||
OCI/AB
|
||||
@@ -77,20 +74,15 @@ QEMU/AB
|
||||
RBAC/AB
|
||||
RDMA/AB
|
||||
RNG/AB
|
||||
RuntimeClass/B # Kubernetes resource (node.k8s.io)
|
||||
RuntimeClasses/B
|
||||
SaaS/B # Software as a Service
|
||||
SCSI/AB
|
||||
SDK/AB
|
||||
seccomp # secure computing mode
|
||||
SHA/AB
|
||||
SEL/AB # IBM Secure Execution for Linux
|
||||
SPDX/AB
|
||||
SRIOV/AB
|
||||
SEV-SNP/B # AMD Secure Encrypted Virtualization - Secure Nested Paging
|
||||
SVG/AB
|
||||
TBD/AB
|
||||
TEE/AB # Trusted Execution Environment
|
||||
TOC/AB
|
||||
TOML/AB
|
||||
TTY/AB
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
417
|
||||
409
|
||||
ACPI/AB
|
||||
ACS/AB
|
||||
API/AB
|
||||
@@ -93,7 +93,6 @@ Mellanox/B
|
||||
Minikube/B
|
||||
MonitorTest/A
|
||||
NEMU/AB
|
||||
NFD/AB
|
||||
NIC/AB
|
||||
NVDIMM/AB
|
||||
NVIDIA/A
|
||||
@@ -135,14 +134,10 @@ RBAC/AB
|
||||
RDMA/AB
|
||||
RHEL/B
|
||||
RNG/AB
|
||||
RuntimeClass/B
|
||||
RuntimeClasses/B
|
||||
Rustlang/B
|
||||
SCSI/AB
|
||||
SDK/AB
|
||||
SEL/AB
|
||||
SELinux/B
|
||||
SEV-SNP/B
|
||||
SHA/AB
|
||||
SLES/B
|
||||
SPDX/AB
|
||||
@@ -158,7 +153,6 @@ Submodule/A
|
||||
Sysbench/B
|
||||
TBD/AB
|
||||
TDX
|
||||
TEE/AB
|
||||
TOC/AB
|
||||
TOML/AB
|
||||
TTY/AB
|
||||
@@ -312,8 +306,6 @@ nack/AB
|
||||
namespace/ABCD
|
||||
netlink
|
||||
netns/AB
|
||||
nodeSelector/B
|
||||
nodeSelectors/B
|
||||
nv/AB
|
||||
nvidia/A
|
||||
onwards
|
||||
|
||||
@@ -9,6 +9,8 @@ source "${tests_dir}/common.bash"
|
||||
kubernetes_dir="${tests_dir}/integration/kubernetes"
|
||||
helm_chart_dir="${repo_root_dir}/tools/packaging/kata-deploy/helm-chart/kata-deploy"
|
||||
|
||||
AZ_REGION="${AZ_REGION:-eastus}"
|
||||
AZ_NODEPOOL_TAGS="${AZ_NODEPOOL_TAGS:-}"
|
||||
GENPOLICY_PULL_METHOD="${GENPOLICY_PULL_METHOD:-oci-distribution}"
|
||||
GH_PR_NUMBER="${GH_PR_NUMBER:-}"
|
||||
HELM_DEFAULT_INSTALLATION="${HELM_DEFAULT_INSTALLATION:-false}"
|
||||
@@ -111,7 +113,7 @@ function create_cluster() {
|
||||
"GENPOLICY_PULL_METHOD=${GENPOLICY_PULL_METHOD:0:1}")
|
||||
|
||||
az group create \
|
||||
-l eastus \
|
||||
-l "${AZ_REGION}" \
|
||||
-n "${rg}"
|
||||
|
||||
# Required by e.g. AKS App Routing for KBS installation.
|
||||
@@ -129,7 +131,8 @@ function create_cluster() {
|
||||
--node-count 1 \
|
||||
--generate-ssh-keys \
|
||||
--tags "${tags[@]}" \
|
||||
$([[ "${KATA_HOST_OS}" = "cbl-mariner" ]] && echo "--os-sku AzureLinux --workload-runtime KataVmIsolation")
|
||||
$([[ "${KATA_HOST_OS}" = "cbl-mariner" ]] && echo "--os-sku AzureLinux --workload-runtime KataVmIsolation") \
|
||||
$([ -n "${AZ_NODEPOOL_TAGS}" ] && echo "--nodepool-tags "${AZ_NODEPOOL_TAGS}"")
|
||||
}
|
||||
|
||||
function install_bats() {
|
||||
|
||||
@@ -175,7 +175,7 @@ function deploy_kata() {
|
||||
|
||||
ANNOTATIONS="default_vcpus"
|
||||
if [[ "${KATA_HOST_OS}" = "cbl-mariner" ]]; then
|
||||
ANNOTATIONS="image kernel default_vcpus cc_init_data"
|
||||
ANNOTATIONS="image kernel default_vcpus disable_image_nvdimm cc_init_data"
|
||||
fi
|
||||
if [[ "${KATA_HYPERVISOR}" = "qemu" ]]; then
|
||||
ANNOTATIONS="image initrd kernel default_vcpus"
|
||||
|
||||
@@ -12,7 +12,7 @@ load "${BATS_TEST_DIRNAME}/tests_common.sh"
|
||||
setup() {
|
||||
[ "$(uname -m)" == "aarch64" ] && skip "See: https://github.com/kata-containers/kata-containers/issues/10928"
|
||||
[[ "${KATA_HYPERVISOR}" == qemu-coco-dev* ]] && skip "Requires CPU hotplug which disabled by static_sandbox_resource_mgmt"
|
||||
[[ "${KATA_HYPERVISOR}" == "qemu-tdx" ]] && skip "See: https://github.com/kata-containers/kata-containers/issues/12492"
|
||||
[[ "${KATA_HYPERVISOR}" == qemu-tdx ]] && skip "See: https://github.com/kata-containers/kata-containers/issues/12492"
|
||||
|
||||
setup_common || die "setup_common failed"
|
||||
|
||||
@@ -53,7 +53,6 @@ setup() {
|
||||
teardown() {
|
||||
[ "$(uname -m)" == "aarch64" ] && skip "See: https://github.com/kata-containers/kata-containers/issues/10928"
|
||||
[[ "${KATA_HYPERVISOR}" == qemu-coco-dev* ]] && skip "Requires CPU hotplug which disabled by static_sandbox_resource_mgmt"
|
||||
[[ "${KATA_HYPERVISOR}" == "qemu-tdx" ]] && skip "See: https://github.com/kata-containers/kata-containers/issues/12492"
|
||||
|
||||
for pod in "${pods[@]}"; do
|
||||
kubectl logs ${pod}
|
||||
|
||||
@@ -99,31 +99,23 @@ add_annotations_to_yaml() {
|
||||
esac
|
||||
}
|
||||
|
||||
add_cbl_mariner_annotation_to_yaml() {
|
||||
local -r yaml_file="$1"
|
||||
|
||||
local -r mariner_annotation_kernel="io.katacontainers.config.hypervisor.kernel"
|
||||
local -r mariner_kernel_path="/usr/share/cloud-hypervisor/vmlinux.bin"
|
||||
|
||||
local -r mariner_annotation_image="io.katacontainers.config.hypervisor.image"
|
||||
local -r mariner_image_path="/opt/kata/share/kata-containers/kata-containers-mariner.img"
|
||||
|
||||
add_annotations_to_yaml "${yaml_file}" "${mariner_annotation_kernel}" "${mariner_kernel_path}"
|
||||
add_annotations_to_yaml "${yaml_file}" "${mariner_annotation_image}" "${mariner_image_path}"
|
||||
}
|
||||
|
||||
add_cbl_mariner_specific_annotations() {
|
||||
if [[ "${KATA_HOST_OS}" = "cbl-mariner" ]]; then
|
||||
info "Adding annotations for cbl-mariner"
|
||||
info "Add kernel and image path and annotations for cbl-mariner"
|
||||
local mariner_annotation_kernel="io.katacontainers.config.hypervisor.kernel"
|
||||
local mariner_kernel_path="/usr/share/cloud-hypervisor/vmlinux.bin"
|
||||
|
||||
local mariner_annotation_image="io.katacontainers.config.hypervisor.image"
|
||||
local mariner_image_path="/opt/kata/share/kata-containers/kata-containers-mariner.img"
|
||||
|
||||
local mariner_annotation_disable_image_nvdimm="io.katacontainers.config.hypervisor.disable_image_nvdimm"
|
||||
local mariner_disable_image_nvdimm=true
|
||||
|
||||
for K8S_TEST_YAML in runtimeclass_workloads_work/*.yaml
|
||||
do
|
||||
add_cbl_mariner_annotation_to_yaml "${K8S_TEST_YAML}"
|
||||
done
|
||||
|
||||
for K8S_TEST_YAML in runtimeclass_workloads_work/openvpn/*.yaml
|
||||
do
|
||||
add_cbl_mariner_annotation_to_yaml "${K8S_TEST_YAML}"
|
||||
add_annotations_to_yaml "${K8S_TEST_YAML}" "${mariner_annotation_kernel}" "${mariner_kernel_path}"
|
||||
add_annotations_to_yaml "${K8S_TEST_YAML}" "${mariner_annotation_image}" "${mariner_image_path}"
|
||||
add_annotations_to_yaml "${K8S_TEST_YAML}" "${mariner_annotation_disable_image_nvdimm}" "${mariner_disable_image_nvdimm}"
|
||||
done
|
||||
fi
|
||||
}
|
||||
|
||||
@@ -37,6 +37,8 @@ K8S_TEST_DIR="${kubernetes_dir:-"${BATS_TEST_DIRNAME}"}"
|
||||
|
||||
AUTO_GENERATE_POLICY="${AUTO_GENERATE_POLICY:-}"
|
||||
GENPOLICY_PULL_METHOD="${GENPOLICY_PULL_METHOD:-}"
|
||||
GENPOLICY_BINARY="${GENPOLICY_BINARY:-"/opt/kata/bin/genpolicy"}"
|
||||
GENPOLICY_SETTINGS_DIR="${GENPOLICY_SETTINGS_DIR:-"/opt/kata/share/defaults/kata-containers"}"
|
||||
KATA_HYPERVISOR="${KATA_HYPERVISOR:-}"
|
||||
KATA_HOST_OS="${KATA_HOST_OS:-}"
|
||||
|
||||
@@ -191,12 +193,11 @@ adapt_common_policy_settings() {
|
||||
# and change these settings to use Kata CI cluster's default namespace.
|
||||
create_common_genpolicy_settings() {
|
||||
declare -r genpolicy_settings_dir="$1"
|
||||
declare -r default_genpolicy_settings_dir="/opt/kata/share/defaults/kata-containers"
|
||||
|
||||
auto_generate_policy_enabled || return 0
|
||||
|
||||
cp "${default_genpolicy_settings_dir}/genpolicy-settings.json" "${genpolicy_settings_dir}"
|
||||
cp "${default_genpolicy_settings_dir}/rules.rego" "${genpolicy_settings_dir}"
|
||||
cp "${GENPOLICY_SETTINGS_DIR}/genpolicy-settings.json" "${genpolicy_settings_dir}"
|
||||
cp "${GENPOLICY_SETTINGS_DIR}/rules.rego" "${genpolicy_settings_dir}"
|
||||
|
||||
adapt_common_policy_settings "${genpolicy_settings_dir}"
|
||||
}
|
||||
@@ -247,7 +248,7 @@ auto_generate_policy_no_added_flags() {
|
||||
declare -r additional_flags="${4:-""}"
|
||||
|
||||
auto_generate_policy_enabled || return 0
|
||||
local genpolicy_command="RUST_LOG=info /opt/kata/bin/genpolicy -u -y ${yaml_file}"
|
||||
local genpolicy_command="RUST_LOG=info ${GENPOLICY_BINARY} -u -y ${yaml_file}"
|
||||
genpolicy_command+=" -p ${settings_dir}/rules.rego"
|
||||
genpolicy_command+=" -j ${settings_dir}/genpolicy-settings.json"
|
||||
|
||||
|
||||
@@ -291,45 +291,15 @@ fn remove_custom_runtime_configs(config: &Config) -> Result<()> {
|
||||
|
||||
/// Note: The src parameter is kept to allow for unit testing with temporary directories,
|
||||
/// even though in production it always uses /opt/kata-artifacts/opt/kata
|
||||
///
|
||||
/// Symlinks in the source tree are preserved at the destination (recreated as symlinks
|
||||
/// instead of copying the target file). Absolute targets under the source root are
|
||||
/// rewritten to the destination root so they remain valid.
|
||||
fn copy_artifacts(src: &str, dst: &str) -> Result<()> {
|
||||
let src_path = Path::new(src);
|
||||
for entry in WalkDir::new(src).follow_links(false) {
|
||||
for entry in WalkDir::new(src) {
|
||||
let entry = entry?;
|
||||
let src_path_entry = entry.path();
|
||||
let relative_path = src_path_entry.strip_prefix(src)?;
|
||||
let src_path = entry.path();
|
||||
let relative_path = src_path.strip_prefix(src)?;
|
||||
let dst_path = Path::new(dst).join(relative_path);
|
||||
|
||||
if entry.file_type().is_dir() {
|
||||
fs::create_dir_all(&dst_path)?;
|
||||
} else if entry.file_type().is_symlink() {
|
||||
// Preserve symlinks: create a symlink at destination instead of copying the target
|
||||
let link_target = fs::read_link(src_path_entry)
|
||||
.with_context(|| format!("Failed to read symlink: {:?}", src_path_entry))?;
|
||||
let new_target: std::path::PathBuf = if link_target.is_absolute() {
|
||||
// Rewrite absolute targets that point inside the source tree
|
||||
if let Ok(rel) = link_target.strip_prefix(src_path) {
|
||||
Path::new(dst).join(rel)
|
||||
} else {
|
||||
link_target.into()
|
||||
}
|
||||
} else {
|
||||
link_target.into()
|
||||
};
|
||||
|
||||
if let Some(parent) = dst_path.parent() {
|
||||
fs::create_dir_all(parent)?;
|
||||
}
|
||||
match fs::remove_file(&dst_path) {
|
||||
Ok(()) => {}
|
||||
Err(e) if e.kind() == std::io::ErrorKind::NotFound => {}
|
||||
Err(e) => return Err(e.into()),
|
||||
}
|
||||
std::os::unix::fs::symlink(&new_target, &dst_path)
|
||||
.with_context(|| format!("Failed to create symlink {:?} -> {:?}", dst_path, new_target))?;
|
||||
} else {
|
||||
if let Some(parent) = dst_path.parent() {
|
||||
fs::create_dir_all(parent)?;
|
||||
@@ -347,7 +317,7 @@ fn copy_artifacts(src: &str, dst: &str) -> Result<()> {
|
||||
Err(e) => return Err(e.into()), // Other errors should be propagated
|
||||
}
|
||||
|
||||
fs::copy(src_path_entry, &dst_path)?;
|
||||
fs::copy(src_path, &dst_path)?;
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
@@ -918,54 +888,65 @@ async fn configure_mariner(config: &Config) -> Result<()> {
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use rstest::rstest;
|
||||
|
||||
#[rstest]
|
||||
#[case("qemu", "qemu")]
|
||||
#[case("qemu-tdx", "qemu")]
|
||||
#[case("qemu-snp", "qemu")]
|
||||
#[case("qemu-se", "qemu")]
|
||||
#[case("qemu-coco-dev", "qemu")]
|
||||
#[case("qemu-cca", "qemu")]
|
||||
#[case("qemu-nvidia-gpu", "qemu")]
|
||||
#[case("qemu-nvidia-gpu-tdx", "qemu")]
|
||||
#[case("qemu-nvidia-gpu-snp", "qemu")]
|
||||
#[case("qemu-runtime-rs", "qemu")]
|
||||
#[case("qemu-coco-dev-runtime-rs", "qemu")]
|
||||
#[case("qemu-se-runtime-rs", "qemu")]
|
||||
#[case("qemu-snp-runtime-rs", "qemu")]
|
||||
#[case("qemu-tdx-runtime-rs", "qemu")]
|
||||
fn test_get_hypervisor_name_qemu_variants(#[case] shim: &str, #[case] expected: &str) {
|
||||
assert_eq!(get_hypervisor_name(shim).unwrap(), expected);
|
||||
#[test]
|
||||
fn test_get_hypervisor_name_qemu_variants() {
|
||||
// Test all QEMU variants
|
||||
assert_eq!(get_hypervisor_name("qemu").unwrap(), "qemu");
|
||||
assert_eq!(get_hypervisor_name("qemu-tdx").unwrap(), "qemu");
|
||||
assert_eq!(get_hypervisor_name("qemu-snp").unwrap(), "qemu");
|
||||
assert_eq!(get_hypervisor_name("qemu-se").unwrap(), "qemu");
|
||||
assert_eq!(get_hypervisor_name("qemu-coco-dev").unwrap(), "qemu");
|
||||
assert_eq!(get_hypervisor_name("qemu-cca").unwrap(), "qemu");
|
||||
assert_eq!(get_hypervisor_name("qemu-nvidia-gpu").unwrap(), "qemu");
|
||||
assert_eq!(get_hypervisor_name("qemu-nvidia-gpu-tdx").unwrap(), "qemu");
|
||||
assert_eq!(get_hypervisor_name("qemu-nvidia-gpu-snp").unwrap(), "qemu");
|
||||
assert_eq!(get_hypervisor_name("qemu-runtime-rs").unwrap(), "qemu");
|
||||
assert_eq!(
|
||||
get_hypervisor_name("qemu-coco-dev-runtime-rs").unwrap(),
|
||||
"qemu"
|
||||
);
|
||||
assert_eq!(get_hypervisor_name("qemu-se-runtime-rs").unwrap(), "qemu");
|
||||
assert_eq!(get_hypervisor_name("qemu-snp-runtime-rs").unwrap(), "qemu");
|
||||
assert_eq!(get_hypervisor_name("qemu-tdx-runtime-rs").unwrap(), "qemu");
|
||||
}
|
||||
|
||||
#[rstest]
|
||||
#[case("clh", "clh")]
|
||||
#[case("cloud-hypervisor", "cloud-hypervisor")]
|
||||
#[case("dragonball", "dragonball")]
|
||||
#[case("fc", "firecracker")]
|
||||
#[case("firecracker", "firecracker")]
|
||||
#[case("remote", "remote")]
|
||||
fn test_get_hypervisor_name_other_hypervisors(#[case] shim: &str, #[case] expected: &str) {
|
||||
assert_eq!(get_hypervisor_name(shim).unwrap(), expected);
|
||||
#[test]
|
||||
fn test_get_hypervisor_name_other_hypervisors() {
|
||||
// Test other hypervisors
|
||||
assert_eq!(get_hypervisor_name("clh").unwrap(), "clh");
|
||||
assert_eq!(
|
||||
get_hypervisor_name("cloud-hypervisor").unwrap(),
|
||||
"cloud-hypervisor"
|
||||
);
|
||||
assert_eq!(get_hypervisor_name("dragonball").unwrap(), "dragonball");
|
||||
assert_eq!(get_hypervisor_name("fc").unwrap(), "firecracker");
|
||||
assert_eq!(get_hypervisor_name("firecracker").unwrap(), "firecracker");
|
||||
assert_eq!(get_hypervisor_name("remote").unwrap(), "remote");
|
||||
}
|
||||
|
||||
#[rstest]
|
||||
#[case("")]
|
||||
#[case("unknown-shim")]
|
||||
#[case("custom")]
|
||||
fn test_get_hypervisor_name_unknown(#[case] shim: &str) {
|
||||
let result = get_hypervisor_name(shim);
|
||||
#[test]
|
||||
fn test_get_hypervisor_name_unknown() {
|
||||
// Test unknown shim returns error with clear message
|
||||
let result = get_hypervisor_name("unknown-shim");
|
||||
assert!(result.is_err(), "Unknown shim should return an error");
|
||||
let err_msg = result.unwrap_err().to_string();
|
||||
assert!(
|
||||
err_msg.contains(&format!("Unknown shim '{}'", shim)),
|
||||
err_msg.contains("Unknown shim 'unknown-shim'"),
|
||||
"Error message should mention the unknown shim"
|
||||
);
|
||||
assert!(
|
||||
err_msg.contains("Valid shims are:"),
|
||||
"Error message should list valid shims"
|
||||
);
|
||||
|
||||
let result = get_hypervisor_name("custom");
|
||||
assert!(result.is_err(), "Custom shim should return an error");
|
||||
let err_msg = result.unwrap_err().to_string();
|
||||
assert!(
|
||||
err_msg.contains("Unknown shim 'custom'"),
|
||||
"Error message should mention the custom shim"
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -1042,36 +1023,10 @@ mod tests {
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_copy_artifacts_preserves_symlinks() {
|
||||
let src_dir = tempfile::tempdir().unwrap();
|
||||
let dst_dir = tempfile::tempdir().unwrap();
|
||||
|
||||
// Create a real file and a symlink pointing to it
|
||||
let real_file = src_dir.path().join("real-file.txt");
|
||||
fs::write(&real_file, "actual content").unwrap();
|
||||
let link_path = src_dir.path().join("link-to-real");
|
||||
std::os::unix::fs::symlink(&real_file, &link_path).unwrap();
|
||||
|
||||
copy_artifacts(
|
||||
src_dir.path().to_str().unwrap(),
|
||||
dst_dir.path().to_str().unwrap(),
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
let dst_link = dst_dir.path().join("link-to-real");
|
||||
let dst_real = dst_dir.path().join("real-file.txt");
|
||||
assert!(dst_real.exists(), "real file should be copied");
|
||||
assert!(dst_link.is_symlink(), "destination should be a symlink");
|
||||
assert_eq!(
|
||||
fs::read_link(&dst_link).unwrap(),
|
||||
dst_real,
|
||||
"symlink should point to the real file in the same tree"
|
||||
);
|
||||
assert_eq!(
|
||||
fs::read_to_string(&dst_link).unwrap(),
|
||||
"actual content",
|
||||
"following the symlink should yield the real content"
|
||||
);
|
||||
fn test_get_hypervisor_name_empty() {
|
||||
let result = get_hypervisor_name("");
|
||||
assert!(result.is_err());
|
||||
let err_msg = result.unwrap_err().to_string();
|
||||
assert!(err_msg.contains("Unknown shim"));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -25,33 +25,19 @@ struct ContainerdRuntimeParams {
|
||||
snapshotter: Option<String>,
|
||||
}
|
||||
|
||||
/// Plugin ID for CRI runtime in containerd config v3 (version = 3).
|
||||
const CONTAINERD_V3_RUNTIME_PLUGIN_ID: &str = "\"io.containerd.cri.v1.runtime\"";
|
||||
/// Plugin ID for CRI in containerd config v2 (version = 2).
|
||||
const CONTAINERD_V2_CRI_PLUGIN_ID: &str = "\"io.containerd.grpc.v1.cri\"";
|
||||
/// Legacy plugin key when config has no version (pre-v2).
|
||||
const CONTAINERD_LEGACY_CRI_PLUGIN_ID: &str = "cri";
|
||||
/// Plugin ID for CRI images in containerd config v3 (version = 3).
|
||||
const CONTAINERD_CRI_IMAGES_PLUGIN_ID: &str = "\"io.containerd.cri.v1.images\"";
|
||||
|
||||
fn get_containerd_pluginid(config_file: &str) -> Result<&'static str> {
|
||||
let content = fs::read_to_string(config_file)
|
||||
.with_context(|| format!("Failed to read containerd config file: {}", config_file))?;
|
||||
|
||||
if content.contains("version = 3") {
|
||||
Ok(CONTAINERD_V3_RUNTIME_PLUGIN_ID)
|
||||
Ok("\"io.containerd.cri.v1.runtime\"")
|
||||
} else if content.contains("version = 2") {
|
||||
Ok(CONTAINERD_V2_CRI_PLUGIN_ID)
|
||||
Ok("\"io.containerd.grpc.v1.cri\"")
|
||||
} else {
|
||||
Ok(CONTAINERD_LEGACY_CRI_PLUGIN_ID)
|
||||
Ok("cri")
|
||||
}
|
||||
}
|
||||
|
||||
/// True when the containerd config is v3 (version = 3), i.e. we use the split CRI plugins.
|
||||
fn is_containerd_v3_config(pluginid: &str) -> bool {
|
||||
pluginid == CONTAINERD_V3_RUNTIME_PLUGIN_ID
|
||||
}
|
||||
|
||||
fn get_containerd_output_path(paths: &ContainerdPaths) -> PathBuf {
|
||||
if paths.use_drop_in {
|
||||
if paths.drop_in_file.starts_with("/etc/containerd/") {
|
||||
@@ -109,26 +95,6 @@ fn write_containerd_runtime_config(
|
||||
&format!("{runtime_table}.snapshotter"),
|
||||
snapshotter,
|
||||
)?;
|
||||
// In containerd config v3 the CRI plugin is split into runtime and images,
|
||||
// and setting the snapshotter only on the runtime plugin is not enough for image
|
||||
// pull/prepare.
|
||||
//
|
||||
// The images plugin must have runtime_platforms.<runtime>.snapshotter so it
|
||||
// uses the correct snapshotter per runtime (e.g. nydus, erofs).
|
||||
//
|
||||
// A PR on the containerd side is open so we can rely on the runtime plugin
|
||||
// snapshotter alone: https://github.com/containerd/containerd/pull/12836
|
||||
if is_containerd_v3_config(pluginid) {
|
||||
toml_utils::set_toml_value(
|
||||
config_file,
|
||||
&format!(
|
||||
".plugins.{}.runtime_platforms.\"{}\".snapshotter",
|
||||
CONTAINERD_CRI_IMAGES_PLUGIN_ID,
|
||||
params.runtime_name
|
||||
),
|
||||
snapshotter,
|
||||
)?;
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
@@ -266,7 +232,6 @@ pub async fn configure_custom_containerd_runtime(
|
||||
};
|
||||
|
||||
write_containerd_runtime_config(&configuration_file, pluginid, ¶ms)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -569,167 +534,102 @@ pub fn snapshotter_handler_mapping_validation_check(config: &Config) -> Result<(
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use crate::utils::toml as toml_utils;
|
||||
use rstest::rstest;
|
||||
use std::path::Path;
|
||||
use tempfile::NamedTempFile;
|
||||
|
||||
fn make_params(
|
||||
runtime_name: &str,
|
||||
snapshotter: Option<&str>,
|
||||
) -> ContainerdRuntimeParams {
|
||||
ContainerdRuntimeParams {
|
||||
runtime_name: runtime_name.to_string(),
|
||||
runtime_path: "\"/opt/kata/bin/kata-runtime\"".to_string(),
|
||||
config_path: "\"/opt/kata/share/defaults/kata-containers/configuration-qemu.toml\""
|
||||
.to_string(),
|
||||
pod_annotations: "[\"io.katacontainers.*\"]",
|
||||
snapshotter: snapshotter.map(|s| s.to_string()),
|
||||
}
|
||||
#[test]
|
||||
fn test_check_containerd_snapshotter_version_support_1_6_with_mapping() {
|
||||
// Version 1.6 with snapshotter mapping should fail
|
||||
let result = check_containerd_snapshotter_version_support("containerd://1.6.28", true);
|
||||
assert!(result.is_err());
|
||||
assert!(result
|
||||
.unwrap_err()
|
||||
.to_string()
|
||||
.contains("kata-deploy only supports snapshotter configuration with containerd 1.7 or newer"));
|
||||
}
|
||||
|
||||
/// CRI images runtime_platforms snapshotter is set only for v3 config when a snapshotter is configured.
|
||||
#[rstest]
|
||||
#[case(CONTAINERD_V3_RUNTIME_PLUGIN_ID, Some("\"nydus\""), "kata-qemu", true)]
|
||||
#[case(CONTAINERD_V2_CRI_PLUGIN_ID, Some("\"nydus\""), "kata-qemu", false)]
|
||||
#[case(CONTAINERD_V3_RUNTIME_PLUGIN_ID, None, "kata-qemu", false)]
|
||||
#[case(CONTAINERD_V3_RUNTIME_PLUGIN_ID, Some("\"erofs\""), "kata-clh", true)]
|
||||
fn test_write_containerd_runtime_config_cri_images_runtime_platforms_snapshotter(
|
||||
#[case] pluginid: &str,
|
||||
#[case] snapshotter: Option<&str>,
|
||||
#[case] runtime_name: &str,
|
||||
#[case] expect_runtime_platforms_set: bool,
|
||||
) {
|
||||
let file = NamedTempFile::new().unwrap();
|
||||
let path = file.path();
|
||||
std::fs::write(path, "").unwrap();
|
||||
#[test]
|
||||
fn test_check_containerd_snapshotter_version_support_1_6_without_mapping() {
|
||||
// Version 1.6 without snapshotter mapping should pass (no mapping means no check needed)
|
||||
let result = check_containerd_snapshotter_version_support("containerd://1.6.28", false);
|
||||
assert!(result.is_ok());
|
||||
}
|
||||
|
||||
let params = make_params(runtime_name, snapshotter);
|
||||
write_containerd_runtime_config(path, pluginid, ¶ms).unwrap();
|
||||
#[test]
|
||||
fn test_check_containerd_snapshotter_version_support_1_7_with_mapping() {
|
||||
// Version 1.7 with snapshotter mapping should pass
|
||||
let result = check_containerd_snapshotter_version_support("containerd://1.7.15", true);
|
||||
assert!(result.is_ok());
|
||||
}
|
||||
|
||||
let images_snapshotter_path = format!(
|
||||
".plugins.\"io.containerd.cri.v1.images\".runtime_platforms.\"{}\".snapshotter",
|
||||
runtime_name
|
||||
);
|
||||
let result = toml_utils::get_toml_value(Path::new(path), &images_snapshotter_path);
|
||||
#[test]
|
||||
fn test_check_containerd_snapshotter_version_support_2_0_with_mapping() {
|
||||
// Version 2.0 with snapshotter mapping should pass
|
||||
let result = check_containerd_snapshotter_version_support("containerd://2.0.0", true);
|
||||
assert!(result.is_ok());
|
||||
}
|
||||
|
||||
if expect_runtime_platforms_set {
|
||||
let value = result.unwrap_or_else(|e| {
|
||||
panic!(
|
||||
"expected CRI images runtime_platforms.{} snapshotter to be set: {}",
|
||||
runtime_name, e
|
||||
)
|
||||
});
|
||||
assert_eq!(
|
||||
value,
|
||||
snapshotter.unwrap().trim_matches('"'),
|
||||
"runtime_platforms snapshotter value"
|
||||
);
|
||||
} else {
|
||||
#[test]
|
||||
fn test_check_containerd_snapshotter_version_support_without_prefix() {
|
||||
// Version without containerd:// prefix should still work
|
||||
let result = check_containerd_snapshotter_version_support("1.6.28", true);
|
||||
assert!(result.is_err());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_check_containerd_snapshotter_version_support_1_6_variants() {
|
||||
// Test various 1.6.x versions
|
||||
assert!(check_containerd_snapshotter_version_support("containerd://1.6.0", true).is_err());
|
||||
assert!(check_containerd_snapshotter_version_support("containerd://1.6.28", true).is_err());
|
||||
assert!(check_containerd_snapshotter_version_support("containerd://1.6.999", true).is_err());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_check_containerd_snapshotter_version_support_1_7_variants() {
|
||||
// Test various 1.7+ versions should pass
|
||||
assert!(check_containerd_snapshotter_version_support("containerd://1.7.0", true).is_ok());
|
||||
assert!(check_containerd_snapshotter_version_support("containerd://1.7.15", true).is_ok());
|
||||
assert!(check_containerd_snapshotter_version_support("containerd://1.8.0", true).is_ok());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_check_containerd_erofs_version_support() {
|
||||
// Versions that should pass (2.2.0+)
|
||||
let passing_versions = [
|
||||
"containerd://2.2.0",
|
||||
"containerd://2.2.0-rc.1",
|
||||
"containerd://2.2.1",
|
||||
"containerd://2.3.0",
|
||||
"containerd://3.0.0",
|
||||
"containerd://2.3.0-beta.0",
|
||||
"2.2.0", // without prefix
|
||||
];
|
||||
for version in passing_versions {
|
||||
assert!(
|
||||
result.is_err(),
|
||||
"expected CRI images runtime_platforms.{} snapshotter not to be set for pluginid={:?} snapshotter={:?}",
|
||||
runtime_name,
|
||||
pluginid,
|
||||
snapshotter
|
||||
check_containerd_erofs_version_support(version).is_ok(),
|
||||
"Expected {} to pass",
|
||||
version
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/// Written containerd config (e.g. drop-in) must not start with blank lines when written to an initially empty file.
|
||||
#[rstest]
|
||||
#[case(CONTAINERD_V3_RUNTIME_PLUGIN_ID)]
|
||||
#[case(CONTAINERD_V2_CRI_PLUGIN_ID)]
|
||||
fn test_write_containerd_runtime_config_empty_file_no_leading_newlines(
|
||||
#[case] pluginid: &str,
|
||||
) {
|
||||
let file = NamedTempFile::new().unwrap();
|
||||
let path = file.path();
|
||||
std::fs::write(path, "").unwrap();
|
||||
|
||||
let params = make_params("kata-qemu", Some("\"nydus\""));
|
||||
write_containerd_runtime_config(path, pluginid, ¶ms).unwrap();
|
||||
|
||||
let content = std::fs::read_to_string(path).unwrap();
|
||||
assert!(
|
||||
!content.starts_with('\n'),
|
||||
"containerd config must not start with newline(s), got {} leading newlines (pluginid={})",
|
||||
content.chars().take_while(|&c| c == '\n').count(),
|
||||
pluginid
|
||||
);
|
||||
assert!(
|
||||
content.trim_start().starts_with('['),
|
||||
"config should start with a TOML table"
|
||||
);
|
||||
}
|
||||
|
||||
#[rstest]
|
||||
#[case("containerd://1.6.28", true, false, Some("kata-deploy only supports snapshotter configuration with containerd 1.7 or newer"))]
|
||||
#[case("containerd://1.6.28", false, true, None)]
|
||||
#[case("containerd://1.6.0", true, false, None)]
|
||||
#[case("containerd://1.6.999", true, false, None)]
|
||||
#[case("containerd://1.7.0", true, true, None)]
|
||||
#[case("containerd://1.7.15", true, true, None)]
|
||||
#[case("containerd://1.8.0", true, true, None)]
|
||||
#[case("containerd://2.0.0", true, true, None)]
|
||||
#[case("1.6.28", true, false, None)]
|
||||
fn test_check_containerd_snapshotter_version_support(
|
||||
#[case] version: &str,
|
||||
#[case] has_mapping: bool,
|
||||
#[case] expect_ok: bool,
|
||||
#[case] expected_error_substring: Option<&str>,
|
||||
) {
|
||||
let result = check_containerd_snapshotter_version_support(version, has_mapping);
|
||||
if expect_ok {
|
||||
assert!(result.is_ok(), "expected ok for version={} has_mapping={}", version, has_mapping);
|
||||
} else {
|
||||
assert!(result.is_err(), "expected err for version={} has_mapping={}", version, has_mapping);
|
||||
if let Some(sub) = expected_error_substring {
|
||||
assert!(
|
||||
result.unwrap_err().to_string().contains(sub),
|
||||
"error should contain {:?}",
|
||||
sub
|
||||
);
|
||||
}
|
||||
// Versions that should fail (< 2.2.0)
|
||||
let failing_versions = [
|
||||
("containerd://2.1.0", "containerd must be 2.2.0 or newer"),
|
||||
("containerd://2.1.5-rc.1", "containerd must be 2.2.0 or newer"),
|
||||
("containerd://2.0.0", "containerd must be 2.2.0 or newer"),
|
||||
("containerd://1.7.0", "containerd must be 2.2.0 or newer"),
|
||||
("containerd://1.6.28", "containerd must be 2.2.0 or newer"),
|
||||
("2.1.0", "containerd must be 2.2.0 or newer"), // without prefix
|
||||
("invalid", "Invalid containerd version format"),
|
||||
("containerd://abc.2.0", "Failed to parse major version"),
|
||||
];
|
||||
for (version, expected_error) in failing_versions {
|
||||
let result = check_containerd_erofs_version_support(version);
|
||||
assert!(result.is_err(), "Expected {} to fail", version);
|
||||
assert!(
|
||||
result.unwrap_err().to_string().contains(expected_error),
|
||||
"Expected error for {} to contain '{}'",
|
||||
version,
|
||||
expected_error
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
#[rstest]
|
||||
#[case("containerd://2.2.0")]
|
||||
#[case("containerd://2.2.0-rc.1")]
|
||||
#[case("containerd://2.2.1")]
|
||||
#[case("containerd://2.3.0")]
|
||||
#[case("containerd://3.0.0")]
|
||||
#[case("containerd://2.3.0-beta.0")]
|
||||
#[case("2.2.0")]
|
||||
fn test_check_containerd_erofs_version_support_passing(#[case] version: &str) {
|
||||
assert!(
|
||||
check_containerd_erofs_version_support(version).is_ok(),
|
||||
"Expected {} to pass",
|
||||
version
|
||||
);
|
||||
}
|
||||
|
||||
#[rstest]
|
||||
#[case("containerd://2.1.0", "containerd must be 2.2.0 or newer")]
|
||||
#[case("containerd://2.1.5-rc.1", "containerd must be 2.2.0 or newer")]
|
||||
#[case("containerd://2.0.0", "containerd must be 2.2.0 or newer")]
|
||||
#[case("containerd://1.7.0", "containerd must be 2.2.0 or newer")]
|
||||
#[case("containerd://1.6.28", "containerd must be 2.2.0 or newer")]
|
||||
#[case("2.1.0", "containerd must be 2.2.0 or newer")]
|
||||
#[case("invalid", "Invalid containerd version format")]
|
||||
#[case("containerd://abc.2.0", "Failed to parse major version")]
|
||||
fn test_check_containerd_erofs_version_support_failing(
|
||||
#[case] version: &str,
|
||||
#[case] expected_error: &str,
|
||||
) {
|
||||
let result = check_containerd_erofs_version_support(version);
|
||||
assert!(result.is_err(), "Expected {} to fail", version);
|
||||
assert!(
|
||||
result.unwrap_err().to_string().contains(expected_error),
|
||||
"Expected error for {} to contain '{}'",
|
||||
version,
|
||||
expected_error
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -65,23 +65,17 @@ fn split_non_toml_header(content: &str) -> (&str, &str) {
|
||||
|
||||
/// Write a TOML file with an optional non-TOML header (e.g. K3s template line).
|
||||
/// Ensures the header ends with a newline before the TOML body.
|
||||
/// Trims leading newlines from the serialized document to avoid many blank lines
|
||||
/// when the file was initially empty (e.g. containerd drop-in).
|
||||
fn write_toml_with_header(
|
||||
file_path: &Path,
|
||||
header: &str,
|
||||
doc: &DocumentMut,
|
||||
) -> Result<()> {
|
||||
let normalized_header = if header.is_empty() {
|
||||
String::new()
|
||||
} else if header.ends_with('\n') {
|
||||
let normalized_header = if header.ends_with('\n') {
|
||||
header.to_string()
|
||||
} else {
|
||||
format!("{header}\n")
|
||||
};
|
||||
let body = doc.to_string();
|
||||
let body_trimmed = body.trim_start_matches('\n');
|
||||
std::fs::write(file_path, format!("{}{}", normalized_header, body_trimmed))
|
||||
std::fs::write(file_path, format!("{}{}", normalized_header, doc.to_string()))
|
||||
.with_context(|| format!("Failed to write TOML file: {file_path:?}"))?;
|
||||
Ok(())
|
||||
}
|
||||
@@ -615,37 +609,6 @@ mod tests {
|
||||
assert!(content.contains("runtime_type"));
|
||||
}
|
||||
|
||||
#[rstest]
|
||||
#[case("", "")]
|
||||
#[case("{{ template \"base\" . }}\n", "{{ template \"base\" . }}\n")]
|
||||
fn test_set_toml_value_empty_file_no_leading_newlines(
|
||||
#[case] initial_content: &str,
|
||||
#[case] expected_prefix: &str,
|
||||
) {
|
||||
let file = NamedTempFile::new().unwrap();
|
||||
let path = file.path();
|
||||
std::fs::write(path, initial_content).unwrap();
|
||||
|
||||
set_toml_value(
|
||||
path,
|
||||
".plugins.\"io.containerd.cri.v1.runtime\".containerd.runtimes.kata-qemu.runtime_type",
|
||||
"\"io.containerd.kata-qemu.v2\"",
|
||||
)
|
||||
.unwrap();
|
||||
let content = std::fs::read_to_string(path).unwrap();
|
||||
assert!(content.starts_with(expected_prefix), "header/prefix must be preserved");
|
||||
let body_start = content.strip_prefix(expected_prefix).unwrap();
|
||||
assert!(
|
||||
!body_start.starts_with('\n'),
|
||||
"written TOML body must not start with newline(s) after header, got {} leading newlines",
|
||||
body_start.chars().take_while(|&c| c == '\n').count()
|
||||
);
|
||||
assert!(
|
||||
body_start.trim_start().starts_with('['),
|
||||
"body should start with a TOML table"
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_get_toml_value() {
|
||||
let file = NamedTempFile::new().unwrap();
|
||||
@@ -778,22 +741,24 @@ mod tests {
|
||||
assert_eq!(agent_debug, "false");
|
||||
}
|
||||
|
||||
#[rstest]
|
||||
#[case("test.string_value", "test_string", "test_string")]
|
||||
#[case("test.bool_value", "true", "true")]
|
||||
#[case("test.int_value", "42", "42")]
|
||||
fn test_toml_value_types(
|
||||
#[case] path: &str,
|
||||
#[case] value: &str,
|
||||
#[case] expected: &str,
|
||||
) {
|
||||
#[test]
|
||||
fn test_toml_value_types() {
|
||||
let file = NamedTempFile::new().unwrap();
|
||||
let file_path = file.path();
|
||||
std::fs::write(file_path, "").unwrap();
|
||||
let path = file.path();
|
||||
std::fs::write(path, "").unwrap();
|
||||
|
||||
set_toml_value(file_path, path, value).unwrap();
|
||||
let got = get_toml_value(file_path, path).unwrap();
|
||||
assert_eq!(got, expected);
|
||||
// Test different value types
|
||||
set_toml_value(path, "test.string_value", "test_string").unwrap();
|
||||
set_toml_value(path, "test.bool_value", "true").unwrap();
|
||||
set_toml_value(path, "test.int_value", "42").unwrap();
|
||||
|
||||
let string_val = get_toml_value(path, "test.string_value").unwrap();
|
||||
let bool_val = get_toml_value(path, "test.bool_value").unwrap();
|
||||
let int_val = get_toml_value(path, "test.int_value").unwrap();
|
||||
|
||||
assert_eq!(string_val, "test_string");
|
||||
assert_eq!(bool_val, "true");
|
||||
assert_eq!(int_val, "42");
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -1305,20 +1270,17 @@ kernel_params = "console=hvc0"
|
||||
.contains("Failed to read TOML file"));
|
||||
}
|
||||
|
||||
#[rstest]
|
||||
#[case("get")]
|
||||
#[case("set")]
|
||||
fn test_invalid_toml(#[case] op: &str) {
|
||||
#[test]
|
||||
fn test_get_toml_value_invalid_toml() {
|
||||
let temp_file = NamedTempFile::new().unwrap();
|
||||
let temp_path = temp_file.path();
|
||||
|
||||
// Write invalid TOML
|
||||
std::fs::write(temp_path, "this is not [ valid toml {").unwrap();
|
||||
|
||||
let result = match op {
|
||||
"get" => get_toml_value(temp_path, "some.path").map(drop),
|
||||
"set" => set_toml_value(temp_path, "some.path", "\"value\""),
|
||||
_ => panic!("unknown op"),
|
||||
};
|
||||
assert!(result.is_err(), "Should fail parsing invalid TOML (op={})", op);
|
||||
let result = get_toml_value(temp_path, "some.path");
|
||||
assert!(result.is_err(), "Should fail parsing invalid TOML");
|
||||
// Just verify it's an error, don't check specific message
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -1343,6 +1305,18 @@ kernel_params = "console=hvc0"
|
||||
assert!(result.is_err());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_set_toml_value_invalid_toml() {
|
||||
let temp_file = NamedTempFile::new().unwrap();
|
||||
let temp_path = temp_file.path();
|
||||
|
||||
// Write invalid TOML
|
||||
std::fs::write(temp_path, "this is not [ valid toml {").unwrap();
|
||||
|
||||
let result = set_toml_value(temp_path, "some.path", "\"value\"");
|
||||
assert!(result.is_err(), "Should fail parsing invalid TOML");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_append_to_toml_array_nonexistent_file() {
|
||||
let result = append_to_toml_array(
|
||||
@@ -1353,25 +1327,30 @@ kernel_params = "console=hvc0"
|
||||
assert!(result.is_err());
|
||||
}
|
||||
|
||||
#[rstest]
|
||||
#[case("append")]
|
||||
#[case("get")]
|
||||
fn test_toml_array_not_an_array(#[case] op: &str) {
|
||||
#[test]
|
||||
fn test_append_to_toml_array_not_an_array() {
|
||||
let temp_file = NamedTempFile::new().unwrap();
|
||||
let temp_path = temp_file.path();
|
||||
|
||||
// Write TOML with a string, not an array
|
||||
std::fs::write(temp_path, "[section]\nkey = \"value\"").unwrap();
|
||||
|
||||
let result = match op {
|
||||
"append" => append_to_toml_array(temp_path, "section.key", "\"item\"").map(drop),
|
||||
"get" => get_toml_array(temp_path, "section.key").map(drop),
|
||||
_ => panic!("unknown op"),
|
||||
};
|
||||
assert!(result.is_err(), "op={}", op);
|
||||
assert!(
|
||||
result.unwrap_err().to_string().contains("not an array"),
|
||||
"op={}",
|
||||
op
|
||||
);
|
||||
let result = append_to_toml_array(temp_path, "section.key", "\"item\"");
|
||||
assert!(result.is_err());
|
||||
assert!(result.unwrap_err().to_string().contains("not an array"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_get_toml_array_not_an_array() {
|
||||
let temp_file = NamedTempFile::new().unwrap();
|
||||
let temp_path = temp_file.path();
|
||||
|
||||
// Write TOML with a string, not an array
|
||||
std::fs::write(temp_path, "[section]\nkey = \"value\"").unwrap();
|
||||
|
||||
let result = get_toml_array(temp_path, "section.key");
|
||||
assert!(result.is_err());
|
||||
assert!(result.unwrap_err().to_string().contains("not an array"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
||||
@@ -229,7 +229,6 @@ shims:
|
||||
agent:
|
||||
httpsProxy: ""
|
||||
noProxy: ""
|
||||
# Optional: set runtimeClass.nodeSelector to pin TEE to specific nodes (always applied). If unset, NFD TEE labels are auto-injected when NFD is detected.
|
||||
|
||||
# Default shim per architecture
|
||||
defaultShim:
|
||||
@@ -312,8 +311,8 @@ helm install kata-deploy oci://ghcr.io/kata-containers/kata-deploy-charts/kata-d
|
||||
Includes:
|
||||
- `qemu-snp` - AMD SEV-SNP (amd64)
|
||||
- `qemu-tdx` - Intel TDX (amd64)
|
||||
- `qemu-se` - IBM Secure Execution for Linux (SEL) (s390x)
|
||||
- `qemu-se-runtime-rs` - IBM Secure Execution for Linux (SEL) Rust runtime (s390x)
|
||||
- `qemu-se` - IBM Secure Execution (s390x)
|
||||
- `qemu-se-runtime-rs` - IBM Secure Execution Rust runtime (s390x)
|
||||
- `qemu-cca` - Arm Confidential Compute Architecture (arm64)
|
||||
- `qemu-coco-dev` - Confidential Containers development (amd64, s390x)
|
||||
- `qemu-coco-dev-runtime-rs` - Confidential Containers development Rust runtime (amd64, s390x)
|
||||
@@ -335,27 +334,6 @@ Includes:
|
||||
|
||||
**Note**: These example files are located in the chart directory. When installing from the OCI registry, you'll need to download them separately or clone the repository to access them.
|
||||
|
||||
### RuntimeClass Node Selectors for TEE Shims
|
||||
|
||||
**Manual configuration:** Any `nodeSelector` you set under `shims.<shim>.runtimeClass.nodeSelector`
|
||||
is **always applied** to that shim's RuntimeClass, whether or not NFD is present. Use this when
|
||||
you want to pin TEE workloads to specific nodes (e.g. without NFD, or with custom labels).
|
||||
|
||||
**Auto-inject when NFD is present:** If you do *not* set a `runtimeClass.nodeSelector` for a
|
||||
TEE shim, the chart can **automatically inject** NFD-based labels when NFD is detected in the
|
||||
cluster (deployed by this chart with `node-feature-discovery.enabled=true` or found externally):
|
||||
- AMD SEV-SNP shims: `amd.feature.node.kubernetes.io/snp: "true"`
|
||||
- Intel TDX shims: `intel.feature.node.kubernetes.io/tdx: "true"`
|
||||
- IBM Secure Execution for Linux (SEL) shims (s390x): `feature.node.kubernetes.io/cpu-security.se.enabled: "true"`
|
||||
|
||||
The chart uses Helm's `lookup` function to detect NFD (by looking for the
|
||||
`node-feature-discovery-worker` DaemonSet). Auto-inject only runs when NFD is detected and
|
||||
no manual `runtimeClass.nodeSelector` is set for that shim.
|
||||
|
||||
**Note**: NFD detection requires cluster access. During `helm template` (dry-run without a
|
||||
cluster), external NFD is not seen, so auto-injected labels are not added. Manual
|
||||
`runtimeClass.nodeSelector` values are still applied in all cases.
|
||||
|
||||
## `RuntimeClass` Management
|
||||
|
||||
**NEW**: Starting with Kata Containers v3.23.0, `runtimeClasses` are managed by
|
||||
|
||||
@@ -1,68 +1,9 @@
|
||||
{{- /*
|
||||
Render a single RuntimeClass. Params (dict): root (.), shim, config, shimConfig,
|
||||
nameOverride (optional; if set, use as metadata.name for default RC), useShimNodeSelectors.
|
||||
*/ -}}
|
||||
{{- define "kata-deploy.runtimeclass" -}}
|
||||
---
|
||||
kind: RuntimeClass
|
||||
apiVersion: node.k8s.io/v1
|
||||
metadata:
|
||||
{{- if .root.Values.env.multiInstallSuffix }}
|
||||
name: kata-{{ .shim }}-{{ .root.Values.env.multiInstallSuffix }}
|
||||
{{- else if .nameOverride }}
|
||||
name: {{ .nameOverride }}
|
||||
{{- else }}
|
||||
name: kata-{{ .shim }}
|
||||
{{- end }}
|
||||
labels:
|
||||
app.kubernetes.io/managed-by: kata-deploy
|
||||
{{- if .root.Values.env.multiInstallSuffix }}
|
||||
kata-deploy/instance: {{ .root.Values.env.multiInstallSuffix | quote }}
|
||||
{{- else }}
|
||||
kata-deploy/instance: "default"
|
||||
{{- end }}
|
||||
{{- if .root.Values.env.multiInstallSuffix }}
|
||||
handler: kata-{{ .shim }}-{{ .root.Values.env.multiInstallSuffix }}
|
||||
{{- else }}
|
||||
handler: kata-{{ .shim }}
|
||||
{{- end }}
|
||||
overhead:
|
||||
podFixed:
|
||||
memory: {{ .config.memory | quote }}
|
||||
cpu: {{ .config.cpu | quote }}
|
||||
scheduling:
|
||||
nodeSelector:
|
||||
katacontainers.io/kata-runtime: "true"
|
||||
{{- /* TEE shims: snp, tdx, -se, -se-runtime-rs (SE = IBM Secure Execution / SEL) */ -}}
|
||||
{{- $isTeeShim := or (contains "snp" .shim) (contains "tdx" .shim) (hasSuffix "-se" .shim) (hasSuffix "-se-runtime-rs" .shim) -}}
|
||||
{{- $isPureTeeShim := and $isTeeShim (not (contains "nvidia-gpu" .shim)) -}}
|
||||
{{- if or (and .shimConfig.runtimeClass .shimConfig.runtimeClass.nodeSelector) (and .useShimNodeSelectors $isPureTeeShim) }}
|
||||
{{- if and .shimConfig.runtimeClass .shimConfig.runtimeClass.nodeSelector }}
|
||||
{{- range $key, $value := .shimConfig.runtimeClass.nodeSelector }}
|
||||
{{ $key }}: {{ $value | quote }}
|
||||
{{- end }}
|
||||
{{- else }}
|
||||
{{- if contains "snp" .shim }}
|
||||
amd.feature.node.kubernetes.io/snp: "true"
|
||||
{{- end }}
|
||||
{{- if contains "tdx" .shim }}
|
||||
intel.feature.node.kubernetes.io/tdx: "true"
|
||||
{{- end }}
|
||||
{{- if or (hasSuffix "-se" .shim) (hasSuffix "-se-runtime-rs" .shim) }}
|
||||
feature.node.kubernetes.io/cpu-security.se.enabled: "true"
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
{{- end -}}
|
||||
|
||||
{{- if .Values.runtimeClasses.enabled }}
|
||||
{{- $multiInstallSuffix := .Values.env.multiInstallSuffix }}
|
||||
{{- $createDefaultRC := .Values.runtimeClasses.createDefault }}
|
||||
{{- $defaultRCName := .Values.runtimeClasses.defaultName }}
|
||||
{{- $nfdEnabled := index .Values "node-feature-discovery" "enabled" | default false }}
|
||||
{{- $externalNFDNamespace := include "kata-deploy.detectExistingNFD" . | trim -}}
|
||||
{{- $useShimNodeSelectors := or $nfdEnabled (ne $externalNFDNamespace "") -}}
|
||||
|
||||
{{- /* Get enabled shims from structured config using null-aware logic */ -}}
|
||||
{{- $disableAll := .Values.shims.disableAll | default false -}}
|
||||
{{- $enabledShims := list -}}
|
||||
{{- range $shimName, $shimConfig := .Values.shims -}}
|
||||
@@ -81,6 +22,7 @@ scheduling:
|
||||
{{- end -}}
|
||||
{{- end -}}
|
||||
|
||||
{{- /* Define runtime class configurations with their overhead settings and node selectors */ -}}
|
||||
{{- $runtimeClassConfigs := dict
|
||||
"clh" (dict "memory" "130Mi" "cpu" "250m")
|
||||
"cloud-hypervisor" (dict "memory" "130Mi" "cpu" "250m")
|
||||
@@ -104,16 +46,69 @@ scheduling:
|
||||
"remote" (dict "memory" "120Mi" "cpu" "250m")
|
||||
}}
|
||||
|
||||
{{- /* Create RuntimeClass for each enabled shim; when default RC is requested, emit it by reusing the same template with nameOverride */ -}}
|
||||
{{- $defaultShim := index .Values.defaultShim "amd64" | default (index .Values.defaultShim "arm64") | default (index .Values.defaultShim "s390x") | default (index .Values.defaultShim "ppc64le") }}
|
||||
{{- /* Create RuntimeClass for each enabled shim */ -}}
|
||||
{{- range $shim := $enabledShims }}
|
||||
{{- $config := index $runtimeClassConfigs $shim }}
|
||||
{{- $shimConfig := index $.Values.shims $shim }}
|
||||
{{- if $config }}
|
||||
{{ include "kata-deploy.runtimeclass" (dict "root" $ "shim" $shim "config" $config "shimConfig" $shimConfig "nameOverride" "" "useShimNodeSelectors" $useShimNodeSelectors) }}
|
||||
{{- if and $createDefaultRC (not $multiInstallSuffix) (eq $shim $defaultShim) }}
|
||||
{{ include "kata-deploy.runtimeclass" (dict "root" $ "shim" $shim "config" $config "shimConfig" $shimConfig "nameOverride" $defaultRCName "useShimNodeSelectors" $useShimNodeSelectors) }}
|
||||
---
|
||||
kind: RuntimeClass
|
||||
apiVersion: node.k8s.io/v1
|
||||
metadata:
|
||||
{{- if $multiInstallSuffix }}
|
||||
name: kata-{{ $shim }}-{{ $multiInstallSuffix }}
|
||||
{{- else }}
|
||||
name: kata-{{ $shim }}
|
||||
{{- end }}
|
||||
labels:
|
||||
app.kubernetes.io/managed-by: kata-deploy
|
||||
{{- if $multiInstallSuffix }}
|
||||
kata-deploy/instance: {{ $multiInstallSuffix | quote }}
|
||||
{{- else }}
|
||||
kata-deploy/instance: "default"
|
||||
{{- end }}
|
||||
{{- if $multiInstallSuffix }}
|
||||
handler: kata-{{ $shim }}-{{ $multiInstallSuffix }}
|
||||
{{- else }}
|
||||
handler: kata-{{ $shim }}
|
||||
{{- end }}
|
||||
overhead:
|
||||
podFixed:
|
||||
memory: {{ $config.memory | quote }}
|
||||
cpu: {{ $config.cpu | quote }}
|
||||
scheduling:
|
||||
nodeSelector:
|
||||
katacontainers.io/kata-runtime: "true"
|
||||
{{- if and $shimConfig.runtimeClass $shimConfig.runtimeClass.nodeSelector }}
|
||||
{{- range $key, $value := $shimConfig.runtimeClass.nodeSelector }}
|
||||
{{ $key }}: {{ $value | quote }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
|
||||
{{- /* Create default RuntimeClass if requested */ -}}
|
||||
{{- if and $createDefaultRC (not $multiInstallSuffix) }}
|
||||
{{- /* Get default shim from structured config - use amd64 as the primary reference */ -}}
|
||||
{{- $defaultShim := index .Values.defaultShim "amd64" | default (index .Values.defaultShim "arm64") | default (index .Values.defaultShim "s390x") | default (index .Values.defaultShim "ppc64le") }}
|
||||
{{- $defaultConfig := index $runtimeClassConfigs $defaultShim }}
|
||||
{{- if and $defaultShim $defaultConfig }}
|
||||
---
|
||||
kind: RuntimeClass
|
||||
apiVersion: node.k8s.io/v1
|
||||
metadata:
|
||||
name: {{ $defaultRCName }}
|
||||
labels:
|
||||
app.kubernetes.io/managed-by: kata-deploy
|
||||
kata-deploy/instance: "default"
|
||||
handler: kata-{{ $defaultShim }}
|
||||
overhead:
|
||||
podFixed:
|
||||
memory: {{ $defaultConfig.memory | quote }}
|
||||
cpu: {{ $defaultConfig.cpu | quote }}
|
||||
scheduling:
|
||||
nodeSelector:
|
||||
katacontainers.io/kata-runtime: "true"
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
|
||||
@@ -17,7 +17,6 @@ shims:
|
||||
disableAll: true
|
||||
|
||||
# Enable TEE shims (qemu-snp, qemu-snp-runtime-rs, qemu-tdx, qemu-tdx-runtime-rs, qemu-se, qemu-se-runtime-rs, qemu-cca, qemu-coco-dev, qemu-coco-dev-runtime-rs)
|
||||
# NFD TEE labels (snp, tdx, se) are auto-injected into RuntimeClasses when NFD is detected; no need to set nodeSelector here.
|
||||
qemu-snp:
|
||||
enabled: true
|
||||
supportedArches:
|
||||
|
||||
@@ -117,9 +117,8 @@ shims:
|
||||
runtimeClass:
|
||||
# This label is automatically added by gpu-operator. Override it
|
||||
# if you want to use a different label.
|
||||
# Uncomment once GPU Operator v26.3 is out
|
||||
# nodeSelector:
|
||||
# nvidia.com/cc.ready.state: "false"
|
||||
nodeSelector:
|
||||
nvidia.com/cc.ready.state: "false"
|
||||
|
||||
qemu-nvidia-gpu-snp:
|
||||
enabled: ~
|
||||
@@ -140,8 +139,7 @@ shims:
|
||||
# If you don't have NFD, you need to add the snp label by other
|
||||
# means to your SNP nodes.
|
||||
nodeSelector:
|
||||
# Uncomment once GPU Operator v26.3 is out
|
||||
# nvidia.com/cc.ready.state: "true"
|
||||
nvidia.com/cc.ready.state: "true"
|
||||
amd.feature.node.kubernetes.io/snp: "true"
|
||||
|
||||
qemu-nvidia-gpu-tdx:
|
||||
@@ -163,8 +161,7 @@ shims:
|
||||
# If you don't have NFD, you need to add the tdx label by other
|
||||
# means to your TDX nodes.
|
||||
nodeSelector:
|
||||
# Uncomment once GPU Operator v26.3 is out
|
||||
# nvidia.com/cc.ready.state: "true"
|
||||
nvidia.com/cc.ready.state: "true"
|
||||
intel.feature.node.kubernetes.io/tdx: "true"
|
||||
|
||||
qemu-snp:
|
||||
|
||||
@@ -23,21 +23,23 @@ pushd ${KATA_DEPLOY_DIR}
|
||||
|
||||
arch=$(uname -m)
|
||||
[ "$arch" = "x86_64" ] && arch="amd64"
|
||||
# Disable provenance and SBOM so each tag is a single image manifest. quay.io rejects
|
||||
# pushing multi-arch manifest lists that include attestation manifests ("manifest invalid").
|
||||
PLATFORM="linux/${arch}"
|
||||
IMAGE_TAG="${REGISTRY}:kata-containers-$(git rev-parse HEAD)-${arch}"
|
||||
|
||||
echo "Building the image"
|
||||
docker buildx build --platform "${PLATFORM}" --provenance false --sbom false \
|
||||
--tag "${IMAGE_TAG}" --push .
|
||||
docker build --tag ${IMAGE_TAG} .
|
||||
|
||||
echo "Pushing the image to the registry"
|
||||
docker push ${IMAGE_TAG}
|
||||
|
||||
if [ -n "${TAG}" ]; then
|
||||
ADDITIONAL_TAG="${REGISTRY}:${TAG}"
|
||||
|
||||
echo "Building the ${ADDITIONAL_TAG} image"
|
||||
docker buildx build --platform "${PLATFORM}" --provenance false --sbom false \
|
||||
--tag "${ADDITIONAL_TAG}" --push .
|
||||
|
||||
docker build --tag ${ADDITIONAL_TAG} .
|
||||
|
||||
echo "Pushing the image ${ADDITIONAL_TAG} to the registry"
|
||||
docker push ${ADDITIONAL_TAG}
|
||||
fi
|
||||
|
||||
popd
|
||||
|
||||
@@ -1 +1 @@
|
||||
181
|
||||
180
|
||||
|
||||
@@ -144,17 +144,15 @@ function _publish_multiarch_manifest()
|
||||
_check_required_env_var "KATA_DEPLOY_IMAGE_TAGS"
|
||||
_check_required_env_var "KATA_DEPLOY_REGISTRIES"
|
||||
|
||||
# Per-arch images are built without provenance/SBOM so each tag is a single image manifest;
|
||||
# quay.io rejects pushing multi-arch manifest lists that include attestation manifests
|
||||
# ("manifest invalid"), so we do not enable them for this workflow.
|
||||
# imagetools create pushes to --tag by default.
|
||||
for registry in "${REGISTRIES[@]}"; do
|
||||
for tag in "${IMAGE_TAGS[@]}"; do
|
||||
docker buildx imagetools create --tag "${registry}:${tag}" \
|
||||
"${registry}:${tag}-amd64" \
|
||||
"${registry}:${tag}-arm64" \
|
||||
"${registry}:${tag}-s390x" \
|
||||
"${registry}:${tag}-ppc64le"
|
||||
docker manifest create ${registry}:${tag} \
|
||||
--amend ${registry}:${tag}-amd64 \
|
||||
--amend ${registry}:${tag}-arm64 \
|
||||
--amend ${registry}:${tag}-s390x \
|
||||
--amend ${registry}:${tag}-ppc64le
|
||||
|
||||
docker manifest push ${registry}:${tag}
|
||||
done
|
||||
done
|
||||
}
|
||||
|
||||
@@ -30,7 +30,6 @@ RUN apt-get update && \
|
||||
curl \
|
||||
g++ \
|
||||
gcc \
|
||||
gnupg \
|
||||
libprotobuf-dev \
|
||||
libssl-dev \
|
||||
make \
|
||||
|
||||
@@ -88,8 +88,8 @@ assets:
|
||||
qemu:
|
||||
description: "VMM that uses KVM"
|
||||
url: "https://github.com/qemu/qemu"
|
||||
version: "v10.2.1"
|
||||
tag: "v10.2.1"
|
||||
version: "v10.2.0"
|
||||
tag: "v10.2.0"
|
||||
# Do not include any non-full release versions
|
||||
# Break the line *without CR or space being appended*, to appease
|
||||
# yamllint, and note the deliberate ' ' at the end of the expression.
|
||||
@@ -207,11 +207,11 @@ assets:
|
||||
kernel:
|
||||
description: "Linux kernel optimised for virtual machines"
|
||||
url: "https://cdn.kernel.org/pub/linux/kernel/v6.x/"
|
||||
version: "v6.18.12"
|
||||
version: "v6.18.5"
|
||||
nvidia:
|
||||
description: "Linux kernel optimised for virtual machines"
|
||||
url: "https://cdn.kernel.org/pub/linux/kernel/v6.x/"
|
||||
version: "v6.18.12"
|
||||
version: "v6.18.5"
|
||||
|
||||
kernel-arm-experimental:
|
||||
description: "Linux kernel with cpu/mem hotplug support on arm64"
|
||||
|
||||
Reference in New Issue
Block a user