diff --git a/src/libs/kata-types/src/annotations/mod.rs b/src/libs/kata-types/src/annotations/mod.rs index f1b3d1a97a..1a6d3713a7 100644 --- a/src/libs/kata-types/src/annotations/mod.rs +++ b/src/libs/kata-types/src/annotations/mod.rs @@ -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::(key) { + KATA_ANNO_CFG_HYPERVISOR_DEFAULT_VCPUS => match self.get_value::(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, diff --git a/src/libs/kata-types/src/config/drop_in.rs b/src/libs/kata-types/src/config/drop_in.rs index 208ea72fdc..8477992ade 100644 --- a/src/libs/kata-types/src/config/drop_in.rs +++ b/src/libs/kata-types/src/config/drop_in.rs @@ -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(), diff --git a/src/libs/kata-types/src/config/hypervisor/ch.rs b/src/libs/kata-types/src/config/hypervisor/ch.rs index 6831ee9cdb..be1dfba895 100644 --- a/src/libs/kata-types/src/config/hypervisor/ch.rs +++ b/src/libs/kata-types/src/config/hypervisor/ch.rs @@ -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 { diff --git a/src/libs/kata-types/src/config/hypervisor/dragonball.rs b/src/libs/kata-types/src/config/hypervisor/dragonball.rs index 089bc2672c..42c8021ac3 100644 --- a/src/libs/kata-types/src/config/hypervisor/dragonball.rs +++ b/src/libs/kata-types/src/config/hypervisor/dragonball.rs @@ -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 { diff --git a/src/libs/kata-types/src/config/hypervisor/firecracker.rs b/src/libs/kata-types/src/config/hypervisor/firecracker.rs index 3c348c89c5..b9e20454c8 100644 --- a/src/libs/kata-types/src/config/hypervisor/firecracker.rs +++ b/src/libs/kata-types/src/config/hypervisor/firecracker.rs @@ -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 { diff --git a/src/libs/kata-types/src/config/hypervisor/mod.rs b/src/libs/kata-types/src/config/hypervisor/mod.rs index 83ea1f2eed..52ac7ba2b9 100644 --- a/src/libs/kata-types/src/config/hypervisor/mod.rs +++ b/src/libs/kata-types/src/config/hypervisor/mod.rs @@ -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, }, }, diff --git a/src/libs/kata-types/src/config/hypervisor/qemu.rs b/src/libs/kata-types/src/config/hypervisor/qemu.rs index 627c8f2dc3..27f53e2e86 100644 --- a/src/libs/kata-types/src/config/hypervisor/qemu.rs +++ b/src/libs/kata-types/src/config/hypervisor/qemu.rs @@ -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 { diff --git a/src/libs/kata-types/tests/test_config.rs b/src/libs/kata-types/tests/test_config.rs index 370fdddbad..3abb672e08 100644 --- a/src/libs/kata-types/tests/test_config.rs +++ b/src/libs/kata-types/tests/test_config.rs @@ -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); diff --git a/src/runtime-rs/crates/hypervisor/ch-config/src/convert.rs b/src/runtime-rs/crates/hypervisor/ch-config/src/convert.rs index 6e7b6fef79..49cdcf4b59 100644 --- a/src/runtime-rs/crates/hypervisor/ch-config/src/convert.rs +++ b/src/runtime-rs/crates/hypervisor/ch-config/src/convert.rs @@ -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() diff --git a/src/runtime-rs/crates/resource/src/cpu_mem/cpu.rs b/src/runtime-rs/crates/resource/src/cpu_mem/cpu.rs index fc0fc7afd0..027bf7da28 100644 --- a/src/runtime-rs/crates/resource/src/cpu_mem/cpu.rs +++ b/src/runtime-rs/crates/resource/src/cpu_mem/cpu.rs @@ -25,7 +25,7 @@ pub struct CpuResource { pub(crate) current_vcpu: Arc>, /// Default number of vCPUs - pub(crate) default_vcpu: u32, + pub(crate) default_vcpu: f32, /// CpuResource of each container pub(crate) container_cpu_resources: Arc>>, @@ -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())), }) } @@ -119,7 +119,7 @@ impl CpuResource { async fn calc_cpu_resources(&self) -> Result { let resources = self.container_cpu_resources.read().await; if resources.is_empty() { - return Ok(self.default_vcpu); + return Ok(self.default_vcpu.ceil() as u32); } // If requests of individual containers are expresses with different @@ -156,7 +156,6 @@ impl CpuResource { let quota = cpu_resource.quota() as f64; let period = cpu_resource.period() as f64; if quota >= 0.0 && period != 0.0 { - info!(sl!(), "total_quota={}, adding {}/{} == {}", total_quota, quota, period, quota * (max_period / period)); total_quota += quota * (max_period / period); } } @@ -199,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) @@ -216,7 +215,7 @@ mod tests { use kata_types::config::{Hypervisor, TomlConfig}; use oci::LinuxCpu; - fn get_cpu_resource_with_default_vcpus(default_vcpus: i32) -> CpuResource { + fn get_cpu_resource_with_default_vcpus(default_vcpus: f32) -> CpuResource { let mut config = TomlConfig::default(); config .hypervisor @@ -244,7 +243,7 @@ mod tests { // 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); + 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). @@ -274,9 +273,9 @@ mod tests { #[tokio::test] async fn test_big_allocation_1() { - let default_vcpus = 10; + let default_vcpus = 10.0; - let mut cpu_resource = get_cpu_resource_with_default_vcpus(default_vcpus as i32); + let mut cpu_resource = get_cpu_resource_with_default_vcpus(default_vcpus); add_linux_container_cpu_resources( &mut cpu_resource, vec![ @@ -289,14 +288,14 @@ mod tests { assert_eq!( cpu_resource.calc_cpu_resources().await.unwrap(), - 128 + default_vcpus + 128 + default_vcpus as u32 ); } #[tokio::test] async fn test_big_allocation_2() { - let default_vcpus = 10; - let mut cpu_resource = get_cpu_resource_with_default_vcpus(default_vcpus as i32); + 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![ @@ -309,26 +308,26 @@ mod tests { assert_eq!( cpu_resource.calc_cpu_resources().await.unwrap(), - (33 + 31 + 77 + 1) + default_vcpus + (33 + 31 + 77 + 1) + default_vcpus as u32 ); } #[tokio::test] async fn test_big_allocation_3() { - let default_vcpus = 10; - let mut cpu_resource = get_cpu_resource_with_default_vcpus(default_vcpus as i32); + 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 + 142 + default_vcpus as u32 ); } #[tokio::test] async fn test_big_allocation_4() { - let default_vcpus = 10; - let mut cpu_resource = get_cpu_resource_with_default_vcpus(default_vcpus as i32); + 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![ @@ -342,14 +341,14 @@ mod tests { assert_eq!( cpu_resource.calc_cpu_resources().await.unwrap(), - (4 * 17 + 1) + default_vcpus + (4 * 17 + 1) + default_vcpus as u32 ); } #[tokio::test] async fn test_divisible_periods() { - let default_vcpus = 3; - let mut cpu_resource = get_cpu_resource_with_default_vcpus(default_vcpus as i32); + 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)], @@ -358,10 +357,10 @@ mod tests { assert_eq!( cpu_resource.calc_cpu_resources().await.unwrap(), - 3 + default_vcpus + 3 + default_vcpus as u32 ); - let mut cpu_resource = get_cpu_resource_with_default_vcpus(default_vcpus as i32); + 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)], @@ -370,14 +369,14 @@ mod tests { assert_eq!( cpu_resource.calc_cpu_resources().await.unwrap(), - 4 + default_vcpus + 4 + default_vcpus as u32 ); } #[tokio::test] async fn test_indivisible_periods() { - let default_vcpus = 1; - let mut cpu_resource = get_cpu_resource_with_default_vcpus(default_vcpus as i32); + 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)], @@ -386,10 +385,10 @@ mod tests { assert_eq!( cpu_resource.calc_cpu_resources().await.unwrap(), - 4 + default_vcpus + 4 + default_vcpus as u32 ); - let mut cpu_resource = get_cpu_resource_with_default_vcpus(default_vcpus as i32); + 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)], @@ -398,7 +397,7 @@ mod tests { assert_eq!( cpu_resource.calc_cpu_resources().await.unwrap(), - 5 + default_vcpus + 5 + default_vcpus as u32 ); } } diff --git a/src/runtime-rs/crates/resource/src/cpu_mem/initial_size.rs b/src/runtime-rs/crates/resource/src/cpu_mem/initial_size.rs index 92bfc81b27..72e79641fd 100644 --- a/src/runtime-rs/crates/resource/src/cpu_mem/initial_size.rs +++ b/src/runtime-rs/crates/resource/src/cpu_mem/initial_size.rs @@ -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 { diff --git a/src/tools/kata-ctl/src/ops/env_ops.rs b/src/tools/kata-ctl/src/ops/env_ops.rs index 109dce6a9b..1846970d69 100644 --- a/src/tools/kata-ctl/src/ops/env_ops.rs +++ b/src/tools/kata-ctl/src/ops/env_ops.rs @@ -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)]