Merge pull request #10580 from pmores/make-vcpu-allocation-more-accurate

runtime-rs: make vcpu allocation more accurate
This commit is contained in:
Fupan Li
2025-08-08 14:14:40 +08:00
committed by GitHub
14 changed files with 342 additions and 62 deletions

View File

@@ -635,13 +635,13 @@ impl Annotation {
KATA_ANNO_CFG_HYPERVISOR_CPU_FEATURES => {
hv.cpu_info.cpu_features = value.to_string();
}
KATA_ANNO_CFG_HYPERVISOR_DEFAULT_VCPUS => match self.get_value::<i32>(key) {
KATA_ANNO_CFG_HYPERVISOR_DEFAULT_VCPUS => match self.get_value::<f32>(key) {
Ok(num_cpus) => {
let num_cpus = num_cpus.unwrap_or_default();
if num_cpus
> get_hypervisor_plugin(hypervisor_name)
.unwrap()
.get_max_cpus() as i32
.get_max_cpus() as f32
{
return Err(io::Error::new(
io::ErrorKind::InvalidData,
@@ -1079,6 +1079,9 @@ impl Annotation {
}
}
}
config.adjust_config()?;
Ok(())
}
}

View File

@@ -369,7 +369,7 @@ mod drop_in_directory_handling {
config.hypervisor["qemu"].path,
"/usr/bin/qemu-kvm".to_string()
);
assert_eq!(config.hypervisor["qemu"].cpu_info.default_vcpus, 2);
assert_eq!(config.hypervisor["qemu"].cpu_info.default_vcpus, 2.0);
assert_eq!(config.hypervisor["qemu"].device_info.default_bridges, 4);
assert_eq!(
config.hypervisor["qemu"].shared_fs.shared_fs.as_deref(),

View File

@@ -109,7 +109,7 @@ impl ConfigPlugin for CloudHypervisorConfig {
return Err(eother!("Both guest boot image and initrd for CH are empty"));
}
if (ch.cpu_info.default_vcpus > 0
if (ch.cpu_info.default_vcpus > 0.0
&& ch.cpu_info.default_vcpus as u32 > default::MAX_CH_VCPUS)
|| ch.cpu_info.default_maxvcpus > default::MAX_CH_VCPUS
{

View File

@@ -66,7 +66,7 @@ impl ConfigPlugin for DragonballConfig {
}
if db.cpu_info.default_vcpus as u32 > db.cpu_info.default_maxvcpus {
db.cpu_info.default_vcpus = db.cpu_info.default_maxvcpus as i32;
db.cpu_info.default_vcpus = db.cpu_info.default_maxvcpus as f32;
}
if db.machine_info.entropy_source.is_empty() {
@@ -135,7 +135,7 @@ impl ConfigPlugin for DragonballConfig {
));
}
if (db.cpu_info.default_vcpus > 0
if (db.cpu_info.default_vcpus > 0.0
&& db.cpu_info.default_vcpus as u32 > default::MAX_DRAGONBALL_VCPUS)
|| db.cpu_info.default_maxvcpus > default::MAX_DRAGONBALL_VCPUS
{

View File

@@ -93,7 +93,7 @@ impl ConfigPlugin for FirecrackerConfig {
));
}
if (firecracker.cpu_info.default_vcpus > 0
if (firecracker.cpu_info.default_vcpus > 0.0
&& firecracker.cpu_info.default_vcpus as u32 > default::MAX_FIRECRACKER_VCPUS)
|| firecracker.cpu_info.default_maxvcpus > default::MAX_FIRECRACKER_VCPUS
{

View File

@@ -348,7 +348,7 @@ pub struct CpuInfo {
/// > 0 <= number of physical cores --> will be set to the specified number
/// > number of physical cores --> will be set to the actual number of physical cores
#[serde(default)]
pub default_vcpus: i32,
pub default_vcpus: f32,
/// Default maximum number of vCPUs per SB/VM:
/// - unspecified or == 0 --> will be set to the actual number of physical cores or
@@ -380,22 +380,22 @@ impl CpuInfo {
let features: Vec<&str> = self.cpu_features.split(',').map(|v| v.trim()).collect();
self.cpu_features = features.join(",");
let cpus = num_cpus::get() as u32;
let cpus = num_cpus::get() as f32;
// adjust default_maxvcpus
if self.default_maxvcpus == 0 || self.default_maxvcpus > cpus {
self.default_maxvcpus = cpus;
if self.default_maxvcpus == 0 || self.default_maxvcpus as f32 > cpus {
self.default_maxvcpus = cpus as u32;
}
// adjust default_vcpus
if self.default_vcpus < 0 || self.default_vcpus as u32 > cpus {
self.default_vcpus = cpus as i32;
} else if self.default_vcpus == 0 {
self.default_vcpus = default::DEFAULT_GUEST_VCPUS as i32;
if self.default_vcpus < 0.0 || self.default_vcpus > cpus {
self.default_vcpus = cpus;
} else if self.default_vcpus == 0.0 {
self.default_vcpus = default::DEFAULT_GUEST_VCPUS as f32;
}
if self.default_vcpus > self.default_maxvcpus as i32 {
self.default_vcpus = self.default_maxvcpus as i32;
if self.default_vcpus > self.default_maxvcpus as f32 {
self.default_vcpus = self.default_maxvcpus as f32;
}
Ok(())
@@ -403,7 +403,7 @@ impl CpuInfo {
/// Validate the configuration information.
pub fn validate(&self) -> Result<()> {
if self.default_vcpus > self.default_maxvcpus as i32 {
if self.default_vcpus > self.default_maxvcpus as f32 {
return Err(eother!(
"The default_vcpus({}) is greater than default_maxvcpus({})",
self.default_vcpus,
@@ -1413,8 +1413,8 @@ mod tests {
#[test]
fn test_cpu_info_adjust_config() {
// get CPU cores of the test node
let node_cpus = num_cpus::get() as u32;
let default_vcpus = default::DEFAULT_GUEST_VCPUS as i32;
let node_cpus = num_cpus::get() as f32;
let default_vcpus = default::DEFAULT_GUEST_VCPUS as f32;
struct TestData<'a> {
desc: &'a str,
@@ -1427,38 +1427,38 @@ mod tests {
desc: "all with default values",
input: &mut CpuInfo {
cpu_features: "".to_string(),
default_vcpus: 0,
default_vcpus: 0.0,
default_maxvcpus: 0,
},
output: CpuInfo {
cpu_features: "".to_string(),
default_vcpus,
default_maxvcpus: node_cpus,
default_maxvcpus: node_cpus as u32,
},
},
TestData {
desc: "all with big values",
input: &mut CpuInfo {
cpu_features: "a,b,c".to_string(),
default_vcpus: 9999999,
default_vcpus: 9999999.0,
default_maxvcpus: 9999999,
},
output: CpuInfo {
cpu_features: "a,b,c".to_string(),
default_vcpus: node_cpus as i32,
default_maxvcpus: node_cpus,
default_vcpus: node_cpus,
default_maxvcpus: node_cpus as u32,
},
},
TestData {
desc: "default_vcpus lager than default_maxvcpus",
input: &mut CpuInfo {
cpu_features: "a, b ,c".to_string(),
default_vcpus: -1,
default_vcpus: -1.0,
default_maxvcpus: 1,
},
output: CpuInfo {
cpu_features: "a,b,c".to_string(),
default_vcpus: 1,
default_vcpus: 1.0,
default_maxvcpus: 1,
},
},

View File

@@ -128,7 +128,7 @@ impl ConfigPlugin for QemuConfig {
}
}
if (qemu.cpu_info.default_vcpus > 0
if (qemu.cpu_info.default_vcpus > 0.0
&& qemu.cpu_info.default_vcpus as u32 > default::MAX_QEMU_VCPUS)
|| qemu.cpu_info.default_maxvcpus > default::MAX_QEMU_VCPUS
{

View File

@@ -131,9 +131,7 @@ impl TomlConfig {
pub fn load_from_file<P: AsRef<Path>>(config_file: P) -> Result<(TomlConfig, PathBuf)> {
let mut result = Self::load_raw_from_file(config_file);
if let Ok((ref mut config, _)) = result {
Hypervisor::adjust_config(config)?;
Runtime::adjust_config(config)?;
Agent::adjust_config(config)?;
config.adjust_config()?;
info!(sl!(), "get kata config: {:?}", config);
}
@@ -175,13 +173,20 @@ impl TomlConfig {
/// drop-in config file fragments in config.d/.
pub fn load(content: &str) -> Result<TomlConfig> {
let mut config: TomlConfig = toml::from_str(content)?;
Hypervisor::adjust_config(&mut config)?;
Runtime::adjust_config(&mut config)?;
Agent::adjust_config(&mut config)?;
config.adjust_config()?;
info!(sl!(), "get kata config: {:?}", config);
Ok(config)
}
/// Adjust Kata configuration information.
pub fn adjust_config(&mut self) -> Result<()> {
Hypervisor::adjust_config(self)?;
Runtime::adjust_config(self)?;
Agent::adjust_config(self)?;
Ok(())
}
/// Validate Kata configuration information.
pub fn validate(&self) -> Result<()> {
Hypervisor::validate(self)?;

View File

@@ -186,7 +186,7 @@ mod tests {
"./test_hypervisor_hook_path"
);
assert!(!hv.memory_info.enable_mem_prealloc);
assert_eq!(hv.cpu_info.default_vcpus, 12);
assert_eq!(hv.cpu_info.default_vcpus, 12.0);
assert!(!hv.memory_info.enable_guest_swap);
assert_eq!(hv.memory_info.default_memory, 100);
assert!(!hv.enable_iothreads);

View File

@@ -319,12 +319,12 @@ impl TryFrom<(CpuInfo, GuestProtection)> for CpusConfig {
let guest_protection_to_use = args.1;
// This can only happen if runtime-rs fails to set default values.
if cpu.default_vcpus <= 0 {
if cpu.default_vcpus <= 0.0 {
return Err(CpusConfigError::BootVCPUsTooSmall);
}
let default_vcpus =
u8::try_from(cpu.default_vcpus).map_err(CpusConfigError::BootVCPUsTooBig)?;
let default_vcpus = u8::try_from(cpu.default_vcpus.ceil() as u32)
.map_err(CpusConfigError::BootVCPUsTooBig)?;
// This can only happen if runtime-rs fails to set default values.
if cpu.default_maxvcpus == 0 {
@@ -611,7 +611,7 @@ mod tests {
};
let cpu_info = CpuInfo {
default_vcpus: cpu_default as i32,
default_vcpus: cpu_default as f32,
default_maxvcpus,
..Default::default()
@@ -1159,7 +1159,7 @@ mod tests {
},
TestData {
cpu_info: CpuInfo {
default_vcpus: -1,
default_vcpus: -1.0,
..Default::default()
},
@@ -1168,7 +1168,7 @@ mod tests {
},
TestData {
cpu_info: CpuInfo {
default_vcpus: 1,
default_vcpus: 1.0,
default_maxvcpus: 0,
..Default::default()
@@ -1178,7 +1178,7 @@ mod tests {
},
TestData {
cpu_info: CpuInfo {
default_vcpus: 9,
default_vcpus: 9.0,
default_maxvcpus: 7,
..Default::default()
@@ -1188,7 +1188,7 @@ mod tests {
},
TestData {
cpu_info: CpuInfo {
default_vcpus: 1,
default_vcpus: 1.0,
default_maxvcpus: 1,
..Default::default()
},
@@ -1208,7 +1208,7 @@ mod tests {
},
TestData {
cpu_info: CpuInfo {
default_vcpus: 1,
default_vcpus: 1.0,
default_maxvcpus: 3,
..Default::default()
},
@@ -1228,7 +1228,7 @@ mod tests {
},
TestData {
cpu_info: CpuInfo {
default_vcpus: 1,
default_vcpus: 1.0,
default_maxvcpus: 13,
..Default::default()
},
@@ -1823,7 +1823,7 @@ mod tests {
cfg: HypervisorConfig {
cpu_info: CpuInfo {
default_vcpus: 0,
default_vcpus: 0.0,
..cpu_info.clone()
},
@@ -1939,7 +1939,7 @@ mod tests {
vsock_socket_path: "vsock_socket_path".into(),
cfg: HypervisorConfig {
cpu_info: CpuInfo {
default_vcpus: 1,
default_vcpus: 1.0,
default_maxvcpus: 1,
..Default::default()
@@ -1963,7 +1963,7 @@ mod tests {
..Default::default()
},
cpu_info: CpuInfo {
default_vcpus: 1,
default_vcpus: 1.0,
default_maxvcpus: 1,
..Default::default()

View File

@@ -25,7 +25,7 @@ pub struct CpuResource {
pub(crate) current_vcpu: Arc<RwLock<u32>>,
/// Default number of vCPUs
pub(crate) default_vcpu: u32,
pub(crate) default_vcpu: f32,
/// CpuResource of each container
pub(crate) container_cpu_resources: Arc<RwLock<HashMap<String, LinuxContainerCpuResources>>>,
@@ -40,7 +40,7 @@ impl CpuResource {
.context(format!("failed to get hypervisor {}", hypervisor_name))?;
Ok(Self {
current_vcpu: Arc::new(RwLock::new(hypervisor_config.cpu_info.default_vcpus as u32)),
default_vcpu: hypervisor_config.cpu_info.default_vcpus as u32,
default_vcpu: hypervisor_config.cpu_info.default_vcpus,
container_cpu_resources: Arc::new(RwLock::new(HashMap::new())),
})
}
@@ -117,27 +117,66 @@ impl CpuResource {
// calculates the total required vcpus by adding each container's requirements within the pod
async fn calc_cpu_resources(&self) -> Result<u32> {
let mut total_vcpu = 0;
let mut cpuset_vcpu: HashSet<u32> = HashSet::new();
let resources = self.container_cpu_resources.read().await;
if resources.is_empty() {
return Ok(self.default_vcpu.ceil() as u32);
}
// If requests of individual containers are expresses with different
// periods we'll need to rewrite them with a common denominator
// (period) before we can add the numerators (quotas). We choose
// to use the largest period as the common denominator since it
// shifts precision out of the fractional part and into the
// integral part in case a rewritten quota ends up non-integral.
let max_period = resources
.iter()
.map(|(_, cpu_resource)| cpu_resource.period())
.max()
// It's ok to unwrap() here as we have checked that 'resources' is
// not empty.
.unwrap() as f64;
let mut cpuset_vcpu: HashSet<u32> = HashSet::new();
// Even though summing up quotas is fixed-point conceptually we
// represent the sum as floating-point because
// - we might be rewriting the quota/period fractions if periods
// vary,and a rewritten quota can end up non-integral. We want
// to preserve the fractional parts until the final rounding
// not to lose precision inadvertenty.
// - also to avoid some tedious casting doing maths with quotas.
// Using a 64-bit float to represent what are conceptually integral
// numbers should be safe here - f64 starts losing precision for
// integers only past 2^53 and a sums of quotas are extremely unlikely
// to reach that magnitude.
let mut total_quota: f64 = 0.0;
for (_, cpu_resource) in resources.iter() {
let vcpu = cpu_resource.get_vcpus().unwrap_or(0) as u32;
cpuset_vcpu.extend(cpu_resource.cpuset().iter());
total_vcpu += vcpu;
let quota = cpu_resource.quota() as f64;
let period = cpu_resource.period() as f64;
if quota >= 0.0 && period != 0.0 {
total_quota += quota * (max_period / period);
}
}
// contrained only by cpuset
if total_vcpu == 0 && !cpuset_vcpu.is_empty() {
if total_quota == 0.0 && !cpuset_vcpu.is_empty() {
info!(sl!(), "(from cpuset)get vcpus # {:?}", cpuset_vcpu);
return Ok(cpuset_vcpu.len() as u32);
}
let total_vcpu = if total_quota > 0.0 && max_period != 0.0 {
self.default_vcpu as f64 + total_quota / max_period
} else {
self.default_vcpu as f64
};
info!(
sl!(),
"(from cfs_quota&cfs_period)get vcpus count {}", total_vcpu
);
Ok(total_vcpu)
Ok(total_vcpu.ceil() as u32)
}
// do hotplug and hot-unplug the vcpu
@@ -159,7 +198,7 @@ impl CpuResource {
// do not reduce computing power
// the number of vcpus would not be lower than the default size
let new_vcpus = cmp::max(new_vcpus, self.default_vcpu);
let new_vcpus = cmp::max(new_vcpus, self.default_vcpu.ceil() as u32);
let (_, new) = hypervisor
.resize_vcpu(old_vcpus, new_vcpus)
@@ -169,3 +208,238 @@ impl CpuResource {
Ok(new)
}
}
#[cfg(test)]
mod tests {
use super::*;
use kata_types::config::{Hypervisor, TomlConfig};
use oci::LinuxCpu;
fn get_cpu_resource_with_default_vcpus(default_vcpus: f32) -> CpuResource {
let mut config = TomlConfig::default();
config
.hypervisor
.insert("qemu".to_owned(), Hypervisor::default());
config
.hypervisor
.entry("qemu".to_owned())
.and_modify(|hv_config| hv_config.cpu_info.default_vcpus = default_vcpus);
config.runtime.hypervisor_name = "qemu".to_owned();
CpuResource::new(Arc::new(config)).unwrap()
}
async fn add_linux_container_cpu_resources(cpu_res: &mut CpuResource, res: Vec<(i64, u64)>) {
let mut resources = cpu_res.container_cpu_resources.write().await;
for (i, (quota, period)) in res.iter().enumerate() {
let mut linux_cpu = LinuxCpu::default();
linux_cpu.set_quota(Some(*quota));
linux_cpu.set_period(Some(*period));
let res = LinuxContainerCpuResources::try_from(&linux_cpu).unwrap();
resources.insert(i.to_string(), res);
}
}
// A lot of the following tests document why a fixed-point-style
// calc_cpu_resources() implementation is better than a f32-based one.
#[tokio::test]
async fn test_rounding() {
let mut cpu_resource = get_cpu_resource_with_default_vcpus(0.0);
// A f32-based calc_cpu_resources() implementation would fail this
// test (adding 0.1 ten times gives roughly 1.0000001).
// An f64-based implementation would pass this one (with the summation
// result of 0.99999999999999989) but it still doesn't guarantee the
// correct result in general. For instance, adding 0.1 twenty times
// in 64 bits results in 2.0000000000000004.
add_linux_container_cpu_resources(
&mut cpu_resource,
vec![
(100_000, 1_000_000),
(100_000, 1_000_000),
(100_000, 1_000_000),
(100_000, 1_000_000),
(100_000, 1_000_000),
(100_000, 1_000_000),
(100_000, 1_000_000),
(100_000, 1_000_000),
(100_000, 1_000_000),
(100_000, 1_000_000),
],
)
.await;
assert_eq!(cpu_resource.calc_cpu_resources().await.unwrap(), 1);
}
#[tokio::test]
async fn test_big_allocation_1() {
let default_vcpus = 10.0;
let mut cpu_resource = get_cpu_resource_with_default_vcpus(default_vcpus);
add_linux_container_cpu_resources(
&mut cpu_resource,
vec![
(32_000_000, 1_000_000),
(32_000_000, 1_000_000),
(64_000_000, 1_000_000),
],
)
.await;
assert_eq!(
cpu_resource.calc_cpu_resources().await.unwrap(),
128 + default_vcpus as u32
);
}
#[tokio::test]
async fn test_big_allocation_2() {
let default_vcpus = 10.0;
let mut cpu_resource = get_cpu_resource_with_default_vcpus(default_vcpus);
add_linux_container_cpu_resources(
&mut cpu_resource,
vec![
(33_000_000, 1_000_000),
(31_000_000, 1_000_000),
(77_000_011, 1_000_000),
],
)
.await;
assert_eq!(
cpu_resource.calc_cpu_resources().await.unwrap(),
(33 + 31 + 77 + 1) + default_vcpus as u32
);
}
#[tokio::test]
async fn test_big_allocation_3() {
let default_vcpus = 10.0;
let mut cpu_resource = get_cpu_resource_with_default_vcpus(default_vcpus);
add_linux_container_cpu_resources(&mut cpu_resource, vec![(141_000_008, 1_000_000)]).await;
assert_eq!(
cpu_resource.calc_cpu_resources().await.unwrap(),
142 + default_vcpus as u32
);
}
#[tokio::test]
async fn test_big_allocation_4() {
let default_vcpus = 10.0;
let mut cpu_resource = get_cpu_resource_with_default_vcpus(default_vcpus);
add_linux_container_cpu_resources(
&mut cpu_resource,
vec![
(17_000_001, 1_000_000),
(17_000_001, 1_000_000),
(17_000_001, 1_000_000),
(17_000_001, 1_000_000),
],
)
.await;
assert_eq!(
cpu_resource.calc_cpu_resources().await.unwrap(),
(4 * 17 + 1) + default_vcpus as u32
);
}
#[tokio::test]
async fn test_divisible_periods() {
let default_vcpus = 3.0;
let mut cpu_resource = get_cpu_resource_with_default_vcpus(default_vcpus);
add_linux_container_cpu_resources(
&mut cpu_resource,
vec![(1_000_000, 1_000_000), (1_000_000, 500_000)],
)
.await;
assert_eq!(
cpu_resource.calc_cpu_resources().await.unwrap(),
3 + default_vcpus as u32
);
let mut cpu_resource = get_cpu_resource_with_default_vcpus(default_vcpus);
add_linux_container_cpu_resources(
&mut cpu_resource,
vec![(3_000_000, 1_500_000), (1_000_000, 500_000)],
)
.await;
assert_eq!(
cpu_resource.calc_cpu_resources().await.unwrap(),
4 + default_vcpus as u32
);
}
#[tokio::test]
async fn test_indivisible_periods() {
let default_vcpus = 1.0;
let mut cpu_resource = get_cpu_resource_with_default_vcpus(default_vcpus);
add_linux_container_cpu_resources(
&mut cpu_resource,
vec![(1_000_000, 1_000_000), (900_000, 300_000)],
)
.await;
assert_eq!(
cpu_resource.calc_cpu_resources().await.unwrap(),
4 + default_vcpus as u32
);
let mut cpu_resource = get_cpu_resource_with_default_vcpus(default_vcpus);
add_linux_container_cpu_resources(
&mut cpu_resource,
vec![(1_000_000, 1_000_000), (900_000, 299_999)],
)
.await;
assert_eq!(
cpu_resource.calc_cpu_resources().await.unwrap(),
5 + default_vcpus as u32
);
}
#[tokio::test]
async fn test_fractional_default_vcpus() {
let default_vcpus = 0.5;
let mut cpu_resource = get_cpu_resource_with_default_vcpus(default_vcpus);
add_linux_container_cpu_resources(&mut cpu_resource, vec![(250_000, 1_000_000)]).await;
assert_eq!(cpu_resource.calc_cpu_resources().await.unwrap(), 1);
let mut cpu_resource = get_cpu_resource_with_default_vcpus(default_vcpus);
add_linux_container_cpu_resources(&mut cpu_resource, vec![(500_000, 1_000_000)]).await;
assert_eq!(cpu_resource.calc_cpu_resources().await.unwrap(), 1);
let mut cpu_resource = get_cpu_resource_with_default_vcpus(default_vcpus);
add_linux_container_cpu_resources(&mut cpu_resource, vec![(500_001, 1_000_000)]).await;
assert_eq!(cpu_resource.calc_cpu_resources().await.unwrap(), 2);
// This test doesn't pass because 0.1 is periodic in binary and thus
// not exactly representable by a float of any width for fundamental
// reasons. Its actual representation is slightly over 0.1
// (e.g. 0.100000001 in f32), which after adding the 900_000/1_000_000
// container request pushes the sum over 1.
// I don't think this problem is solvable without expressing
// 'default_vcpus' in configuration.toml in a fixed point manner (e.g.
// as an integral percentage of a vCPU).
/*
let default_vcpus = 0.1;
let mut cpu_resource = get_cpu_resource_with_default_vcpus(default_vcpus);
add_linux_container_cpu_resources(
&mut cpu_resource,
vec![(900_000, 1_000_000)],
)
.await;
assert_eq!(
cpu_resource.calc_cpu_resources().await.unwrap(),
1
);
*/
}
}

View File

@@ -141,7 +141,7 @@ impl InitialSizeManager {
.context("failed to get hypervisor config")?;
if self.resource.vcpu > 0 {
hv.cpu_info.default_vcpus = self.resource.vcpu as i32
hv.cpu_info.default_vcpus = self.resource.vcpu as f32
}
self.resource.orig_toml_default_mem = hv.memory_info.default_memory;
if self.resource.mem_mb > 0 {

View File

@@ -198,7 +198,7 @@ pub struct HypervisorInfo {
#[serde(default)]
enable_iommu_platform: bool,
#[serde(default)]
default_vcpus: i32,
default_vcpus: f32,
#[serde(default)]
cpu_features: String,
#[serde(default)]

View File

@@ -12,7 +12,6 @@ load "${BATS_TEST_DIRNAME}/tests_common.sh"
setup() {
[ "${KATA_HYPERVISOR}" == "dragonball" ] || [ "${KATA_HYPERVISOR}" == "cloud-hypervisor" ] && \
skip "runtime-rs is still using the old vcpus allocation algorithm, skipping the test see https://github.com/kata-containers/kata-containers/issues/8660"
[ "${KATA_HYPERVISOR}" = "qemu-runtime-rs" ] && skip "Requires CPU hotplug which isn't supported on ${KATA_HYPERVISOR} yet"
[ "$(uname -m)" == "aarch64" ] && skip "See: https://github.com/kata-containers/kata-containers/issues/10928"
setup_common
@@ -50,7 +49,6 @@ setup() {
teardown() {
[ "${KATA_HYPERVISOR}" == "dragonball" ] || [ "${KATA_HYPERVISOR}" == "cloud-hypervisor" ] && \
skip "runtime-rs is still using the old vcpus allocation algorithm, skipping the test see https://github.com/kata-containers/kata-containers/issues/8660"
[ "${KATA_HYPERVISOR}" = "qemu-runtime-rs" ] && skip "Requires CPU hotplug which isn't supported on ${KATA_HYPERVISOR} yet"
[ "$(uname -m)" == "aarch64" ] && skip "See: https://github.com/kata-containers/kata-containers/issues/10928"
for pod in "${pods[@]}"; do