diff --git a/src/tools/kata-ctl/Cargo.lock b/src/tools/kata-ctl/Cargo.lock index 0db5779e96..b10691db07 100644 --- a/src/tools/kata-ctl/Cargo.lock +++ b/src/tools/kata-ctl/Cargo.lock @@ -533,57 +533,6 @@ dependencies = [ "tokio", ] -[[package]] -name = "hypervisor" -version = "0.1.0" -dependencies = [ - "anyhow", - "async-trait", - "dbs-utils", - "dragonball", - "go-flag", - "kata-sys-util", - "kata-types", - "libc", - "logging", - "nix 0.24.2", - "persist", - "rand 0.8.5", - "seccompiler", - "serde", - "serde_json", - "shim-interface", - "slog", - "slog-scope", - "thiserror", - "tokio", - "vmm-sys-util 0.11.0", -] - -[[package]] -name = "iana-time-zone" -version = "0.1.53" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "64c122667b287044802d6ce17ee2ddf13207ed924c712de9a66a5814d5b64765" -dependencies = [ - "android_system_properties", - "core-foundation-sys", - "iana-time-zone-haiku", - "js-sys", - "wasm-bindgen", - "winapi", -] - -[[package]] -name = "iana-time-zone-haiku" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0703ae284fc167426161c2e3f1da3ea71d94b21bedbcc9494e92b28e334e3dca" -dependencies = [ - "cxx", - "cxx-build", -] - [[package]] name = "idna" version = "0.3.0" @@ -910,21 +859,6 @@ version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "478c572c3d73181ff3c2539045f6eb99e5491218eae919370993b890cdbdd98e" -[[package]] -name = "persist" -version = "0.1.0" -dependencies = [ - "anyhow", - "async-trait", - "kata-sys-util", - "kata-types", - "libc", - "safe-path", - "serde", - "serde_json", - "shim-interface", -] - [[package]] name = "petgraph" version = "0.5.1" @@ -1218,71 +1152,6 @@ dependencies = [ "winapi", ] -[[package]] -name = "rlimit" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "347703a5ae47adf1e693144157be231dde38c72bd485925cae7407ad3e52480b" -dependencies = [ - "libc", -] - -[[package]] -name = "rtnetlink" -version = "0.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "46f1cfa18f8cebe685373a2697915d7e0db3b4554918bba118385e0f71f258a7" -dependencies = [ - "futures", - "log", - "netlink-packet-route", - "netlink-proto", - "nix 0.24.2", - "thiserror", - "tokio", -] - -[[package]] -name = "runtimes" -version = "0.1.0" -dependencies = [ - "anyhow", - "common", - "hyper", - "hyperlocal", - "hypervisor", - "kata-types", - "lazy_static", - "logging", - "oci", - "persist", - "shim-interface", - "slog", - "slog-scope", - "tokio", - "virt_container", -] - -[[package]] -name = "rustc-demangle" -version = "0.1.21" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ef03e0a2b150c7a90d01faf6254c9c48a41e95fb2a8c2ac1c6f0d2b9aefc342" - -[[package]] -name = "rustix" -version = "0.34.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2079c267b8394eb529872c3cf92e181c378b41fea36e68130357b52493701d2e" -dependencies = [ - "bitflags", - "errno", - "io-lifetimes", - "libc", - "linux-raw-sys", - "winapi", -] - [[package]] name = "rustls" version = "0.20.6" @@ -1415,17 +1284,6 @@ dependencies = [ "serde", ] -[[package]] -name = "sha2" -version = "0.10.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "82e6b795fe2e3b1e845bafcb27aa35405c4d47cdfc92af5fc8d3002f76cebdc0" -dependencies = [ - "cfg-if 1.0.0", - "cpufeatures", - "digest", -] - [[package]] name = "shim-interface" version = "0.1.0" @@ -1436,15 +1294,6 @@ dependencies = [ "tokio", ] -[[package]] -name = "signal-hook-registry" -version = "1.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e51e73328dc4ac0c7ccbda3a494dfa03df1de2f46018127f60c693f2648455b0" -dependencies = [ - "libc", -] - [[package]] name = "slab" version = "0.4.7" diff --git a/src/tools/kata-ctl/src/arch/aarch64/mod.rs b/src/tools/kata-ctl/src/arch/aarch64/mod.rs index 0dc8692b59..7966123bdf 100644 --- a/src/tools/kata-ctl/src/arch/aarch64/mod.rs +++ b/src/tools/kata-ctl/src/arch/aarch64/mod.rs @@ -12,6 +12,10 @@ mod arch_specific { use std::path::Path; const KVM_DEV: &str = "/dev/kvm"; + #[allow(dead_code)] + pub const ARCH_CPU_VENDOR_FIELD: &str = "CPU implementer"; + #[allow(dead_code)] + pub const ARCH_CPU_MODEL_FIELD: &str = "CPU architecture"; // List of check functions static CHECK_LIST: &[CheckItem] = &[CheckItem { diff --git a/src/tools/kata-ctl/src/arch/powerpc64le/mod.rs b/src/tools/kata-ctl/src/arch/powerpc64le/mod.rs index 6d8affaa17..1cc49d70cc 100644 --- a/src/tools/kata-ctl/src/arch/powerpc64le/mod.rs +++ b/src/tools/kata-ctl/src/arch/powerpc64le/mod.rs @@ -10,6 +10,9 @@ pub use arch_specific::*; mod arch_specific { use anyhow::Result; + pub const ARCH_CPU_VENDOR_FIELD: &str = ""; + pub const ARCH_CPU_MODEL_FIELD: &str = "model"; + pub fn check() -> Result<()> { unimplemented!("Check not implemented in powerpc64le"); } diff --git a/src/tools/kata-ctl/src/arch/s390x/mod.rs b/src/tools/kata-ctl/src/arch/s390x/mod.rs index ba022fdff9..b3196547b3 100644 --- a/src/tools/kata-ctl/src/arch/s390x/mod.rs +++ b/src/tools/kata-ctl/src/arch/s390x/mod.rs @@ -12,21 +12,25 @@ mod arch_specific { use crate::types::*; use anyhow::{anyhow, Result}; - const PROC_CPUINFO: &str = "/proc/cpuinfo"; const CPUINFO_DELIMITER: &str = "processor "; const CPUINFO_FEATURES_TAG: &str = "features"; const CPU_FEATURES_REQ: &[&str] = &["sie"]; + #[allow(dead_code)] + pub const ARCH_CPU_VENDOR_FIELD: &str = check::GENERIC_CPU_VENDOR_FIELD; + #[allow(dead_code)] + pub const ARCH_CPU_MODEL_FIELD: &str = "machine"; + // check cpu fn check_cpu() -> Result<()> { println!("INFO: check CPU: s390x"); - let cpu_info = check::get_single_cpu_info(PROC_CPUINFO, CPUINFO_DELIMITER)?; + let cpu_info = check::get_single_cpu_info(check::PROC_CPUINFO, CPUINFO_DELIMITER)?; let cpu_features = check::get_cpu_flags(&cpu_info, CPUINFO_FEATURES_TAG).map_err(|e| { anyhow!( "Error parsing CPU features, file {:?}, {:?}", - PROC_CPUINFO, + check::PROC_CPUINFO, e ) })?; diff --git a/src/tools/kata-ctl/src/arch/x86_64/mod.rs b/src/tools/kata-ctl/src/arch/x86_64/mod.rs index 53413b2c57..924536a131 100644 --- a/src/tools/kata-ctl/src/arch/x86_64/mod.rs +++ b/src/tools/kata-ctl/src/arch/x86_64/mod.rs @@ -11,11 +11,12 @@ mod arch_specific { use crate::types::*; use anyhow::{anyhow, Result}; - const PROC_CPUINFO: &str = "/proc/cpuinfo"; const CPUINFO_DELIMITER: &str = "\nprocessor"; const CPUINFO_FLAGS_TAG: &str = "flags"; const CPU_FLAGS_INTEL: &[&str] = &["lm", "sse4_1", "vmx"]; const CPU_ATTRIBS_INTEL: &[&str] = &["GenuineIntel"]; + pub const ARCH_CPU_VENDOR_FIELD: &str = check::GENERIC_CPU_VENDOR_FIELD; + pub const ARCH_CPU_MODEL_FIELD: &str = check::GENERIC_CPU_MODEL_FIELD; // List of check functions static CHECK_LIST: &[CheckItem] = &[CheckItem { @@ -29,13 +30,19 @@ mod arch_specific { Some(CHECK_LIST) } + // check cpu fn check_cpu(_args: &str) -> Result<()> { println!("INFO: check CPU: x86_64"); - let cpu_info = check::get_single_cpu_info(PROC_CPUINFO, CPUINFO_DELIMITER)?; + let cpu_info = check::get_single_cpu_info(check::PROC_CPUINFO, CPUINFO_DELIMITER)?; - let cpu_flags = check::get_cpu_flags(&cpu_info, CPUINFO_FLAGS_TAG) - .map_err(|e| anyhow!("Error parsing CPU flags, file {:?}, {:?}", PROC_CPUINFO, e))?; + let cpu_flags = check::get_cpu_flags(&cpu_info, CPUINFO_FLAGS_TAG).map_err(|e| { + anyhow!( + "Error parsing CPU flags, file {:?}, {:?}", + check::PROC_CPUINFO, + e + ) + })?; // perform checks // TODO: Perform checks based on hypervisor type diff --git a/src/tools/kata-ctl/src/check.rs b/src/tools/kata-ctl/src/check.rs index 1396062706..81b9b83a77 100644 --- a/src/tools/kata-ctl/src/check.rs +++ b/src/tools/kata-ctl/src/check.rs @@ -23,6 +23,14 @@ const JSON_TYPE: &str = "application/json"; const USER_AGT: &str = "kata"; +#[allow(dead_code)] +pub const GENERIC_CPU_VENDOR_FIELD: &str = "vendor_id"; +#[allow(dead_code)] +pub const GENERIC_CPU_MODEL_FIELD: &str = "model name"; + +#[allow(dead_code)] +pub const PROC_CPUINFO: &str = "/proc/cpuinfo"; + #[cfg(any(target_arch = "s390x", target_arch = "x86_64"))] fn get_cpu_info(cpu_info_file: &str) -> Result { let contents = std::fs::read_to_string(cpu_info_file)?; diff --git a/src/tools/kata-ctl/src/utils.rs b/src/tools/kata-ctl/src/utils.rs index 6b49603cac..b1564f4c47 100644 --- a/src/tools/kata-ctl/src/utils.rs +++ b/src/tools/kata-ctl/src/utils.rs @@ -5,6 +5,11 @@ #![allow(dead_code)] +#[cfg(any(target_arch = "s390x", target_arch = "x86_64"))] +use crate::arch::arch_specific; +#[cfg(any(target_arch = "s390x", target_arch = "x86_64"))] +use crate::check::get_single_cpu_info; + use anyhow::{anyhow, Context, Result}; use std::fs; @@ -38,6 +43,107 @@ pub fn get_kernel_version(proc_version_file: &str) -> Result { Ok(kernel_version) } +const OS_RELEASE: &str = "/etc/os-release"; + +// Clear Linux has a different path (for stateless support) +const OS_RELEASE_CLR: &str = "/usr/lib/os-release"; + +const UNKNOWN: &str = "unknown"; + +fn get_field_fn(line: &str, delimiter: &str, file_name: &str) -> Result { + let fields: Vec<&str> = line.split(delimiter).collect(); + if fields.len() < 2 { + return Err(anyhow!("Unexpected file contents for {}", file_name)); + } else { + let val = fields[1].trim(); + Ok(String::from(val)) + } +} +// Ref: https://www.freedesktop.org/software/systemd/man/os-release.html +pub fn get_distro_details(os_release: &str, os_release_clr: &str) -> Result<(String, String)> { + let files = vec![os_release, os_release_clr]; + let mut name = String::new(); + let mut version = String::new(); + + for release_file in files.iter() { + match fs::read_to_string(release_file) { + Err(e) => { + if e.kind() == std::io::ErrorKind::NotFound { + continue; + } else { + return Err(anyhow!( + "Error reading file {}: {}", + release_file, + e.to_string() + )); + } + } + Ok(contents) => { + let lines = contents.lines(); + + for line in lines { + if line.starts_with("NAME=") && name.is_empty() { + name = get_field_fn(line, "=", release_file)?; + } else if line.starts_with("VERSION_ID=") && version.is_empty() { + version = get_field_fn(line, "=", release_file)?; + } + } + if !name.is_empty() && !version.is_empty() { + return Ok((name, version)); + } + } + } + } + + if name.is_empty() { + name = String::from(UNKNOWN); + } + + if version.is_empty() { + version = String::from(UNKNOWN); + } + + Ok((name, version)) +} + +#[cfg(any(target_arch = "s390x", target_arch = "x86_64"))] +pub fn get_generic_cpu_details(cpu_info_file: &str) -> Result<(String, String)> { + let cpu_info = get_single_cpu_info(cpu_info_file, "\n\n")?; + let lines = cpu_info.lines(); + println!("Single cpu info: {}", cpu_info); + let mut vendor = String::new(); + let mut model = String::new(); + + for line in lines { + if !arch_specific::ARCH_CPU_VENDOR_FIELD.is_empty() + && line.starts_with(arch_specific::ARCH_CPU_VENDOR_FIELD) + { + vendor = get_field_fn(line, ":", cpu_info_file)?; + } + if !arch_specific::ARCH_CPU_MODEL_FIELD.is_empty() + && line.starts_with(arch_specific::ARCH_CPU_MODEL_FIELD) + { + model = get_field_fn(line, ":", cpu_info_file)?; + } + } + + if vendor.is_empty() && !arch_specific::ARCH_CPU_VENDOR_FIELD.is_empty() { + return Err(anyhow!( + "Cannot find cpu vendor field in file : {}", + cpu_info_file + )); + } + + if model.is_empty() && !arch_specific::ARCH_CPU_MODEL_FIELD.is_empty() { + return Err(anyhow!( + "Cannot find cpu model field in file : {}", + cpu_info_file + )); + } + + Ok((vendor, model)) +} + #[cfg(test)] mod tests { use super::*; @@ -91,4 +197,90 @@ mod tests { let expected = format!("unexpected contents in file {}", path.to_str().unwrap()); assert_eq!(actual, expected); } + + #[test] + fn test_get_distro_details_empty_files() { + let res = get_distro_details("xvz.xt", "bar.txt"); + assert!(res.is_ok()); + let (name, version) = res.unwrap(); + assert_eq!(name, UNKNOWN); + assert_eq!(version, UNKNOWN); + } + + #[test] + fn test_get_distro_details_valid_file() { + let dir = tempdir().unwrap(); + let file_path = dir.path().join("os-version"); + let path = file_path.clone(); + let mut file = fs::File::create(file_path).unwrap(); + writeln!(file, "NAME=Ubuntu\nID_LIKE=debian\nVERSION_ID=20.04.4\n").unwrap(); + let res = get_distro_details("/etc/foo.txt", path.to_str().unwrap()); + let (name, version) = res.unwrap(); + assert_eq!(name, "Ubuntu"); + assert_eq!(version, "20.04.4"); + } + + #[test] + fn test_get_distro_details_system() { + let res = get_distro_details(OS_RELEASE, OS_RELEASE_CLR); + assert!(res.is_ok()); + } + + #[cfg(any(target_arch = "x86_64"))] + #[test] + fn get_generic_cpu_details_system() { + let res = get_generic_cpu_details(crate::check::PROC_CPUINFO); + assert!(res.is_ok()); + } + + #[cfg(any(target_arch = "s390x", target_arch = "x86_64"))] + #[test] + fn get_generic_cpu_details_valid_contents() { + let dir = tempdir().unwrap(); + let file_path = dir.path().join("cpuinfo"); + let path = file_path.clone(); + let mut file = fs::File::create(file_path).unwrap(); + let expected_vendor_id = "GenuineIntel"; + let expected_model_name = "i7-1065G7 CPU"; + let contents = format!( + "{} : {} \n{} : {}\n stepping: 5\n\n", + arch_specific::ARCH_CPU_VENDOR_FIELD, + expected_vendor_id, + arch_specific::ARCH_CPU_MODEL_FIELD, + expected_model_name + ); + writeln!(file, "{}", contents).unwrap(); + let res = get_generic_cpu_details(path.to_str().unwrap()); + assert_eq!(res.as_ref().unwrap().0, expected_vendor_id); + assert_eq!(res.as_ref().unwrap().1, expected_model_name); + } + + #[cfg(any(target_arch = "s390x", target_arch = "x86_64"))] + #[test] + fn get_generic_cpu_details_invalid_file() { + let res = get_generic_cpu_details("/tmp/missing.txt"); + assert!(res.is_err()); + } + + #[cfg(any(target_arch = "s390x", target_arch = "x86_64"))] + #[test] + fn get_generic_cpu_details_invalid_contents() { + let dir = tempdir().unwrap(); + let file_path = dir.path().join("cpuinfo"); + let path = file_path.clone(); + let mut file = fs::File::create(file_path).unwrap(); + writeln!( + file, + "vendor :GenuineIntel\nmodel_name=i7-1065G7 CPU\nstepping:5\n\n" + ) + .unwrap(); + let actual = get_generic_cpu_details(path.to_str().unwrap()) + .unwrap_err() + .to_string(); + let expected = format!( + r#"Cannot find cpu vendor field in file : {}"#, + path.to_str().unwrap() + ); + assert_eq!(actual, expected); + } }