diff --git a/src/tools/kata-ctl/Cargo.lock b/src/tools/kata-ctl/Cargo.lock index 6e7dc602fa..903465d495 100644 --- a/src/tools/kata-ctl/Cargo.lock +++ b/src/tools/kata-ctl/Cargo.lock @@ -1519,6 +1519,8 @@ dependencies = [ "semver", "serde", "serde_json", + "strum", + "strum_macros", "tempfile", "thiserror", ] diff --git a/src/tools/kata-ctl/Cargo.toml b/src/tools/kata-ctl/Cargo.toml index 235072e4ca..31c230f336 100644 --- a/src/tools/kata-ctl/Cargo.toml +++ b/src/tools/kata-ctl/Cargo.toml @@ -19,6 +19,8 @@ serde_json = "1.0.85" thiserror = "1.0.35" privdrop = "0.5.2" nix = "0.25.0" +strum = "0.24.1" +strum_macros = "0.24.3" runtimes = { path = "../../runtime-rs/crates/runtimes" } serde = "1.0.149" diff --git a/src/tools/kata-ctl/src/arch/mod.rs b/src/tools/kata-ctl/src/arch/mod.rs index b85811a0ca..b0010955d6 100644 --- a/src/tools/kata-ctl/src/arch/mod.rs +++ b/src/tools/kata-ctl/src/arch/mod.rs @@ -3,8 +3,6 @@ // SPDX-License-Identifier: Apache-2.0 // -use anyhow::Result; - #[cfg(target_arch = "aarch64")] pub mod aarch64; #[cfg(target_arch = "aarch64")] @@ -32,7 +30,3 @@ pub use x86_64 as arch_specific; target_arch = "x86_64" )))] compile_error!("unknown architecture"); - -pub fn check() -> Result<()> { - arch_specific::check() -} 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 95817981e1..fbd01cfd32 100644 --- a/src/tools/kata-ctl/src/arch/x86_64/mod.rs +++ b/src/tools/kata-ctl/src/arch/x86_64/mod.rs @@ -8,6 +8,7 @@ pub use arch_specific::*; mod arch_specific { use crate::check; + use crate::types::*; use anyhow::{anyhow, Result}; const PROC_CPUINFO: &str = "/proc/cpuinfo"; @@ -16,8 +17,19 @@ mod arch_specific { const CPU_FLAGS_INTEL: &[&str] = &["lm", "sse4_1", "vmx"]; const CPU_ATTRIBS_INTEL: &[&str] = &["GenuineIntel"]; - // check cpu - fn check_cpu() -> Result<()> { + // List of check functions + static CHECK_LIST: &[CheckItem] = &[CheckItem { + name: CheckType::CheckCpu, + descr: "This parameter performs the cpu check", + fp: check_cpu, + perm: PermissionType::NonPrivileged, + }]; + + pub fn get_checks() -> &'static [CheckItem<'static>] { + CHECK_LIST + } + + fn check_cpu(_args: &str) -> Result<()> { println!("INFO: check CPU: x86_64"); let cpu_info = check::get_single_cpu_info(PROC_CPUINFO, CPUINFO_DELIMITER)?; @@ -42,14 +54,4 @@ mod arch_specific { Ok(()) } - - pub fn check() -> Result<()> { - println!("INFO: check: x86_64"); - - let _cpu_result = check_cpu(); - - // TODO: collect outcome of tests to determine if checks pass or not - - Ok(()) - } } diff --git a/src/tools/kata-ctl/src/args.rs b/src/tools/kata-ctl/src/args.rs index 2cc3b0dc8d..86ffe07054 100644 --- a/src/tools/kata-ctl/src/args.rs +++ b/src/tools/kata-ctl/src/args.rs @@ -64,6 +64,9 @@ pub enum CheckSubCommand { /// List all official and pre-release packages IncludeAllReleases, + + /// List all available checks + List, } #[derive(Debug, Args)] diff --git a/src/tools/kata-ctl/src/check.rs b/src/tools/kata-ctl/src/check.rs index bdc72efb6f..0d72d087d5 100644 --- a/src/tools/kata-ctl/src/check.rs +++ b/src/tools/kata-ctl/src/check.rs @@ -16,16 +16,11 @@ struct Release { tarball_url: String, } -use serde_json::Value; #[cfg(any( target_arch = "aarch64", target_arch = "powerpc64le", target_arch = "x86_64" ))] -use std::collections::HashMap; - -const KATA_GITHUB_URL: &str = - "https://api.github.com/repos/kata-containers/kata-containers/releases/latest"; const KATA_GITHUB_RELEASE_URL: &str = "https://api.github.com/repos/kata-containers/kata-containers/releases"; @@ -125,18 +120,6 @@ pub fn run_network_checks() -> Result<()> { Ok(()) } -fn get_kata_version_by_url(url: &str) -> std::result::Result { - let content = reqwest::blocking::Client::new() - .get(url) - .header(CONTENT_TYPE, JSON_TYPE) - .header(USER_AGENT, USER_AGT) - .send()? - .json::>()?; - - let version = content["tag_name"].as_str().unwrap(); - Ok(version.to_string()) -} - fn get_kata_all_releases_by_url() -> std::result::Result, reqwest::Error> { let releases: Vec = reqwest::blocking::Client::new() .get(KATA_GITHUB_RELEASE_URL) @@ -167,14 +150,6 @@ fn handle_reqwest_error(e: reqwest::Error) -> anyhow::Error { anyhow!(e).context("unknown http connection failure: {:?}") } -pub fn check_version() -> Result<()> { - let version = get_kata_version_by_url(KATA_GITHUB_URL).map_err(handle_reqwest_error)?; - - println!("Version: {}", version); - - Ok(()) -} - pub fn check_all_releases() -> Result<()> { let releases: Vec = get_kata_all_releases_by_url().map_err(handle_reqwest_error)?; @@ -215,6 +190,23 @@ pub fn check_official_releases() -> Result<()> { mod tests { use super::*; use semver::Version; + use serde_json::Value; + use std::collections::HashMap; + + const KATA_GITHUB_URL: &str = + "https://api.github.com/repos/kata-containers/kata-containers/releases/latest"; + + fn get_kata_version_by_url(url: &str) -> std::result::Result { + let content = reqwest::blocking::Client::new() + .get(url) + .header(CONTENT_TYPE, JSON_TYPE) + .header(USER_AGENT, USER_AGT) + .send()? + .json::>()?; + + let version = content["tag_name"].as_str().unwrap(); + Ok(version.to_string()) + } #[test] fn test_get_cpu_info_empty_input() { diff --git a/src/tools/kata-ctl/src/main.rs b/src/tools/kata-ctl/src/main.rs index df3e0d7e7a..f283781b95 100644 --- a/src/tools/kata-ctl/src/main.rs +++ b/src/tools/kata-ctl/src/main.rs @@ -7,6 +7,7 @@ mod arch; mod args; mod check; mod ops; +mod types; mod utils; use anyhow::Result; diff --git a/src/tools/kata-ctl/src/ops/check_ops.rs b/src/tools/kata-ctl/src/ops/check_ops.rs index 170071e106..2890053cc4 100644 --- a/src/tools/kata-ctl/src/ops/check_ops.rs +++ b/src/tools/kata-ctl/src/ops/check_ops.rs @@ -3,23 +3,77 @@ // SPDX-License-Identifier: Apache-2.0 // -use crate::arch; -use crate::check; -use crate::ops::version; +use crate::arch::x86_64::get_checks; use crate::args::{CheckArgument, CheckSubCommand, IptablesCommand, MetricsCommand}; -use anyhow::Result; +use crate::check; + +use crate::ops::version; + +use crate::types::*; + +use anyhow::{anyhow, Result}; const NAME: &str = "kata-ctl"; +// This function retrieves the cmd function passes as argument +fn get_builtin_check_func(name: CheckType) -> Result { + let check_list = get_checks(); + + for check in check_list { + if check.name.eq(&name) { + return Ok(check.fp); + } + } + + Err(anyhow!("Invalid command: {:?}", name)) +} + +// This function is called from each 'kata-ctl check' argument section +fn handle_builtin_check(check: CheckType, args: &str) -> Result<()> { + let f = match get_builtin_check_func(check) { + Ok(fp) => fp, + Err(e) => return Err(e), + }; + + f(args) +} + +fn get_client_cmd_details() -> Vec { + let mut cmds = Vec::new(); + let check_list = get_checks(); + + for cmd in check_list { + cmds.push(format!("{} ({}. Mode: {})", cmd.name, cmd.descr, cmd.perm)); + } + + cmds +} + +fn print_check_list() -> Result<()> { + let cmds = get_client_cmd_details(); + + if cmds.is_empty() { + println!("Checks not found!\n"); + + return Ok(()); + } + + cmds.iter().for_each(|n| println!(" - {}", n)); + + println!(); + + Ok(()) +} + pub fn handle_check(checkcmd: CheckArgument) -> Result<()> { let command = checkcmd.command; match command { CheckSubCommand::All => { // run architecture-specific tests - arch::check()?; + handle_builtin_check(CheckType::CheckCpu, "")?; // run code that uses network checks check::run_network_checks()?; @@ -27,12 +81,15 @@ pub fn handle_check(checkcmd: CheckArgument) -> Result<()> { CheckSubCommand::NoNetworkChecks => { // run architecture-specific tests - arch::check()?; + handle_builtin_check(CheckType::CheckCpu, "")?; } CheckSubCommand::CheckVersionOnly => { - // retrieve latest release - check::check_version()?; + handle_version()?; + } + + CheckSubCommand::List => { + print_check_list()?; } CheckSubCommand::OnlyListReleases => { // retrieve official release @@ -83,6 +140,7 @@ pub fn handle_metrics(_args: MetricsCommand) -> Result<()> { pub fn handle_version() -> Result<()> { let version = version::get().unwrap(); + println!("{} version {:?} (type: rust)", NAME, version); Ok(()) } diff --git a/src/tools/kata-ctl/src/types.rs b/src/tools/kata-ctl/src/types.rs new file mode 100644 index 0000000000..483e5bce70 --- /dev/null +++ b/src/tools/kata-ctl/src/types.rs @@ -0,0 +1,35 @@ +// Copyright (c) 2022 Intel Corporation +// +// SPDX-License-Identifier: Apache-2.0 +// + +use anyhow::Result; +use strum_macros::EnumString; + +// Builtin check command handler type. +pub type BuiltinCmdFp = fn(args: &str) -> Result<()>; + +// CheckType encodes the name of each check provided by kata-ctl. +#[derive(Debug, strum_macros::Display, EnumString, PartialEq)] +pub enum CheckType { + CheckCpu, + CheckNetwork, +} + +// PermissionType is used to show whether a check needs to run with elevated (super-user) +// privileges, or whether it can run as normal user. +#[derive(strum_macros::Display, EnumString, PartialEq)] +pub enum PermissionType { + Privileged, + NonPrivileged, +} + +// CheckItem is used to encode the check metadata that each architecture +// returns in a list of CheckItem's using the architecture implementation +// of get_checks(). +pub struct CheckItem<'a> { + pub name: CheckType, + pub descr: &'a str, + pub fp: BuiltinCmdFp, + pub perm: PermissionType, +}