diff --git a/Cargo.lock b/Cargo.lock index 6b8fd10441..22e9aea52b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -846,9 +846,9 @@ checksum = "5d20789868f4b01b2f2caec9f5c4e0213b41e3e5702a50157d699ae31ced2fcb" [[package]] name = "byte-unit" -version = "5.2.0" +version = "5.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8c6d47a4e2961fb8721bcfc54feae6455f2f64e7054f9bc67e875f0e77f4c58d" +checksum = "37bcaa4a0975bed4a760af3efe4368825098ce5f9d37a30c5a021d635dc63d8f" dependencies = [ "rust_decimal", "schemars", @@ -2788,7 +2788,7 @@ dependencies = [ "httpdate", "itoa", "pin-project-lite", - "socket2 0.4.10", + "socket2 0.5.10", "tokio", "tower-service", "tracing", diff --git a/src/libs/kata-types/Cargo.toml b/src/libs/kata-types/Cargo.toml index e6202e6486..e3cd01ea37 100644 --- a/src/libs/kata-types/Cargo.toml +++ b/src/libs/kata-types/Cargo.toml @@ -14,7 +14,7 @@ edition = "2018" bitmask-enum = "2.1.0" anyhow = "1.0" base64 = "0.13.0" -byte-unit = "5.1.6" +byte-unit = "5.2.3" glob = "0.3.0" lazy_static = "1.4.0" num_cpus = "1.13.1" diff --git a/src/libs/kata-types/src/annotations/mod.rs b/src/libs/kata-types/src/annotations/mod.rs index b4453a2230..983369ca51 100644 --- a/src/libs/kata-types/src/annotations/mod.rs +++ b/src/libs/kata-types/src/annotations/mod.rs @@ -813,37 +813,24 @@ impl Annotation { } // Hypervisor Memory related annotations KATA_ANNO_CFG_HYPERVISOR_DEFAULT_MEMORY => { - match byte_unit::Byte::parse_str(value, true) { - Ok(mem_bytes) => { - let memory_size = mem_bytes - .get_adjusted_unit(byte_unit::Unit::MiB) - .get_value() - as u32; - info!(sl!(), "get mem {} from annotations: {}", memory_size, value); - if memory_size - < get_hypervisor_plugin(hypervisor_name) - .unwrap() - .get_min_memory() - { - return Err(io::Error::new( - io::ErrorKind::InvalidData, - format!( - "memory specified in annotation {} is less than minimum limitation {}", - memory_size, - get_hypervisor_plugin(hypervisor_name) - .unwrap() - .get_min_memory() - ), - )); - } - hv.memory_info.default_memory = memory_size; - } - Err(error) => { - error!( - sl!(), - "failed to parse byte from string {} error {:?}", value, error - ); + if let Some(memory_size) = convert_to_megabytes(value)? { + if memory_size + < get_hypervisor_plugin(hypervisor_name) + .unwrap() + .get_min_memory() + { + return Err(io::Error::new( + io::ErrorKind::InvalidData, + format!( + "memory specified in annotation {} is less than minimum limitation {}", + memory_size, + get_hypervisor_plugin(hypervisor_name) + .unwrap() + .get_min_memory() + ), + )); } + hv.memory_info.default_memory = memory_size; } } KATA_ANNO_CFG_HYPERVISOR_MEMORY_SLOTS => match self.get_value::(key) { @@ -1225,3 +1212,62 @@ impl Annotation { Ok(()) } } + +fn convert_to_megabytes(mem_size_str: &str) -> Result> { + match byte_unit::Byte::parse_str(mem_size_str, true) { + Ok(mut mem_size) => { + let no_suffix_given = mem_size_str + .trim() + .chars() + .all(|c: char| c.is_ascii_digit()); + if no_suffix_given { + // NOTE the error is apparently unreachable at the moment: + // Byte::from_u64_with_unit() doesn't fail unless its argument + // is too big, however that same too big arg will fail to + // Byte::parse_str() in the first place. (Obviously we still + // need to handle it anyway.) + mem_size = + byte_unit::Byte::from_u64_with_unit(mem_size.as_u64(), byte_unit::Unit::MiB) + .ok_or(io::Error::new( + io::ErrorKind::InvalidData, + format!("failed to convert {} to MiB", mem_size.as_u64()), + ))?; + } + let memory_size = mem_size.get_adjusted_unit(byte_unit::Unit::MiB).get_value() as u32; + Ok(Some(memory_size)) + } + Err(error) => { + error!( + sl!(), + "failed to parse byte from string {} error {:?}", mem_size_str, error + ); + Ok(None) + } + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn parse_memory_no_unit() { + let result = convert_to_megabytes("2048"); + assert!(result.is_ok()); + assert_eq!(result.unwrap(), Some(2048)); + } + + #[test] + fn parse_memory_with_units() { + let result = convert_to_megabytes("2 GiB"); + assert!(result.is_ok()); + assert_eq!(result.unwrap(), Some(2048)); + } + + #[test] + fn parse_memory_parse_error() { + let result = convert_to_megabytes("2048r"); + assert!(result.is_ok()); + assert_eq!(result.unwrap(), None); + } +}