mirror of
https://github.com/kata-containers/kata-containers.git
synced 2025-04-30 04:34:27 +00:00
kata-ctl: Add cpu check
Add architecture-specific code for x86_64 and generic calls handling checks for CPU flags and attributes. Signed-off-by: Chelsea Mafrica <chelsea.e.mafrica@intel.com>
This commit is contained in:
parent
7c9f9a5a1d
commit
018aa899cb
@ -7,11 +7,47 @@
|
|||||||
pub use arch_specific::*;
|
pub use arch_specific::*;
|
||||||
|
|
||||||
mod arch_specific {
|
mod arch_specific {
|
||||||
use anyhow::Result;
|
use anyhow::{anyhow, Result};
|
||||||
|
use crate::check;
|
||||||
|
|
||||||
|
const PROC_CPUINFO: &str = "/proc/cpuinfo";
|
||||||
|
const CPUINFO_DELIMITER: &str = "\nprocessor";
|
||||||
|
const CPUINFO_FLAGS_TAG: &str = "flags";
|
||||||
|
const CPU_FLAGS_INTEL: &'static [&'static str] = &["lm", "sse4_1", "vmx"];
|
||||||
|
const CPU_ATTRIBS_INTEL: &'static [&'static str] = &["GenuineIntel"];
|
||||||
|
|
||||||
|
// check cpu
|
||||||
|
fn check_cpu() -> Result<()> {
|
||||||
|
println!("INFO: check CPU: x86_64");
|
||||||
|
|
||||||
|
let cpu_info = check::get_single_cpu_info(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))?;
|
||||||
|
|
||||||
|
// perform checks
|
||||||
|
// TODO: Perform checks based on hypervisor type
|
||||||
|
// TODO: Add more information to output (see kata-check in go tool); adjust formatting
|
||||||
|
let missing_cpu_attributes = check::check_cpu_attribs(&cpu_info, CPU_ATTRIBS_INTEL)?;
|
||||||
|
if missing_cpu_attributes.len() > 0 {
|
||||||
|
eprintln!("WARNING: Missing CPU attributes {:?}", missing_cpu_attributes);
|
||||||
|
}
|
||||||
|
let missing_cpu_flags = check::check_cpu_flags(&cpu_flags, CPU_FLAGS_INTEL)?;
|
||||||
|
if missing_cpu_flags.len() > 0 {
|
||||||
|
eprintln!("WARNING: Missing CPU flags {:?}", missing_cpu_flags);
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
pub fn check(_global_args: clap::ArgMatches) -> Result<()> {
|
pub fn check(_global_args: clap::ArgMatches) -> Result<()> {
|
||||||
println!("INFO: check: x86_64");
|
println!("INFO: check: x86_64");
|
||||||
|
|
||||||
|
let _cpu_result = check_cpu();
|
||||||
|
|
||||||
|
// TODO: collect outcome of tests to determine if checks pass or not
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -5,8 +5,109 @@
|
|||||||
|
|
||||||
// Contains checks that are not architecture-specific
|
// Contains checks that are not architecture-specific
|
||||||
|
|
||||||
use anyhow::{Result};
|
use anyhow::{anyhow, Result};
|
||||||
|
use std::fs;
|
||||||
|
|
||||||
|
fn get_cpu_info(cpu_info_file: &str) -> Result<String> {
|
||||||
|
let contents = fs::read_to_string(cpu_info_file)?;
|
||||||
|
Ok(contents)
|
||||||
|
}
|
||||||
|
|
||||||
|
// get_single_cpu_info returns the contents of the first cpu from
|
||||||
|
// the specified cpuinfo file by parsing based on a specified delimiter
|
||||||
|
pub fn get_single_cpu_info(cpu_info_file: &str, substring: &str) -> Result<String> {
|
||||||
|
let contents = get_cpu_info(cpu_info_file)?;
|
||||||
|
|
||||||
|
if contents.is_empty() {
|
||||||
|
return Err(anyhow!("cpu_info string is empty"))?;
|
||||||
|
}
|
||||||
|
|
||||||
|
let subcontents: Vec<&str> = contents.split(substring).collect();
|
||||||
|
let result = subcontents
|
||||||
|
.first()
|
||||||
|
.ok_or("error splitting contents of cpuinfo")
|
||||||
|
.map_err(|e| anyhow!(e))?
|
||||||
|
.to_string();
|
||||||
|
|
||||||
|
Ok(result)
|
||||||
|
}
|
||||||
|
|
||||||
|
// get_cpu_flags returns a string of cpu flags from cpuinfo, passed in
|
||||||
|
// as a string
|
||||||
|
pub fn get_cpu_flags(cpu_info: &str, cpu_flags_tag: &str) -> Result<String> {
|
||||||
|
if cpu_info.is_empty() {
|
||||||
|
return Err(anyhow!("cpu_info string is empty"))?;
|
||||||
|
}
|
||||||
|
|
||||||
|
let subcontents: Vec<&str> = cpu_info.split("\n").collect();
|
||||||
|
for line in subcontents {
|
||||||
|
if line.starts_with(cpu_flags_tag) {
|
||||||
|
let line_data: Vec<&str> = line.split(":").collect();
|
||||||
|
let flags = line_data
|
||||||
|
.last()
|
||||||
|
.ok_or("error splitting flags in cpuinfo")
|
||||||
|
.map_err(|e| anyhow!(e))?
|
||||||
|
.to_string();
|
||||||
|
return Ok(flags);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok("".to_string())
|
||||||
|
}
|
||||||
|
|
||||||
|
// get_missing_strings searches for required (strings) in data and returns
|
||||||
|
// a vector containing the missing strings
|
||||||
|
fn get_missing_strings(data: &str, required: &'static [&'static str]) -> Result<Vec<String>> {
|
||||||
|
let data_vec: Vec <&str> = data.split_whitespace().collect();
|
||||||
|
|
||||||
|
let mut missing: Vec <String> = Vec::new();
|
||||||
|
|
||||||
|
for item in required {
|
||||||
|
if !data_vec.contains(&item) {
|
||||||
|
missing.push(item.to_string());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(missing)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn check_cpu_flags(retrieved_flags: &str, required_flags: &'static [&'static str]) -> Result<Vec<String>> {
|
||||||
|
let missing_flags = get_missing_strings(retrieved_flags, required_flags)?;
|
||||||
|
|
||||||
|
Ok(missing_flags)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn check_cpu_attribs(cpu_info: &str, required_attribs: &'static [&'static str]) -> Result<Vec<String>> {
|
||||||
|
let mut cpu_info_processed = cpu_info.replace("\t", "");
|
||||||
|
cpu_info_processed = cpu_info_processed.replace("\n", " ");
|
||||||
|
|
||||||
|
let missing_attribs = get_missing_strings(&cpu_info_processed, required_attribs)?;
|
||||||
|
Ok(missing_attribs)
|
||||||
|
}
|
||||||
|
|
||||||
pub fn run_network_checks() -> Result<()> {
|
pub fn run_network_checks() -> Result<()> {
|
||||||
unimplemented!("Tests using network checks not implemented");
|
unimplemented!("Tests using network checks not implemented");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_get_cpu_info_empty_input() {
|
||||||
|
let expected = "No such file or directory (os error 2)";
|
||||||
|
let actual = get_cpu_info("").err().unwrap().to_string();
|
||||||
|
assert_eq!(expected, actual);
|
||||||
|
|
||||||
|
let actual = get_single_cpu_info("", "\nprocessor").err().unwrap().to_string();
|
||||||
|
assert_eq!(expected, actual);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_get_cpu_flags_empty_input() {
|
||||||
|
let expected = "cpu_info string is empty";
|
||||||
|
let actual = get_cpu_flags("", "").err().unwrap().to_string();
|
||||||
|
assert_eq!(expected, actual);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user