From 86ad832e37c87bf62aa08f34191a00997a00ffac Mon Sep 17 00:00:00 2001 From: Bin Liu Date: Fri, 2 Sep 2022 17:36:28 +0800 Subject: [PATCH 01/42] runtime-rs: force shutdown shim process in it can't exit In some case the call of cleanup from shim to service manager will fail, and the shim process will continue to running, that will make process leak. This commit will force shutdown the shim process in case of any errors in service crate. Fixes: #5087 Signed-off-by: Bin Liu --- .../share_fs/share_virtio_fs_standalone.rs | 5 +++- src/runtime-rs/crates/service/src/manager.rs | 2 +- src/runtime-rs/crates/shim/src/shim_delete.rs | 30 ++++++++++++++++--- 3 files changed, 31 insertions(+), 6 deletions(-) diff --git a/src/runtime-rs/crates/resource/src/share_fs/share_virtio_fs_standalone.rs b/src/runtime-rs/crates/resource/src/share_fs/share_virtio_fs_standalone.rs index 9c798d7467..b0c9149735 100644 --- a/src/runtime-rs/crates/resource/src/share_fs/share_virtio_fs_standalone.rs +++ b/src/runtime-rs/crates/resource/src/share_fs/share_virtio_fs_standalone.rs @@ -67,7 +67,10 @@ impl ShareVirtioFsStandalone { fn virtiofsd_args(&self, sock_path: &str) -> Result> { let source_path = get_host_ro_shared_path(&self.config.id); if !source_path.exists() { - return Err(anyhow!("The virtiofs shared path didn't exist")); + return Err(anyhow!( + "The virtiofs shared path({:?}) didn't exist", + source_path + )); } let mut args: Vec = vec![ diff --git a/src/runtime-rs/crates/service/src/manager.rs b/src/runtime-rs/crates/service/src/manager.rs index 214db1e47d..1019aa220a 100644 --- a/src/runtime-rs/crates/service/src/manager.rs +++ b/src/runtime-rs/crates/service/src/manager.rs @@ -155,7 +155,7 @@ impl ServiceManager { let handler = RuntimeHandlerManager::new(sid, sender) .await .context("new runtime handler")?; - handler.cleanup().await?; + handler.cleanup().await.context("runtime handler cleanup")?; let temp_dir = [KATA_PATH, sid].join("/"); if std::fs::metadata(temp_dir.as_str()).is_ok() { // try to remove dir and skip the result diff --git a/src/runtime-rs/crates/shim/src/shim_delete.rs b/src/runtime-rs/crates/shim/src/shim_delete.rs index 8429d34aeb..acaa0d83e2 100644 --- a/src/runtime-rs/crates/shim/src/shim_delete.rs +++ b/src/runtime-rs/crates/shim/src/shim_delete.rs @@ -6,6 +6,9 @@ use anyhow::{Context, Result}; use containerd_shim_protos::api; +use kata_sys_util::spec::{get_bundle_path, get_contaier_type, load_oci_spec}; +use kata_types::container::ContainerType; +use nix::{sys::signal::kill, sys::signal::SIGKILL, unistd::Pid}; use protobuf::Message; use std::{fs, path::Path}; @@ -14,7 +17,7 @@ use crate::{shim::ShimExecutor, Error}; impl ShimExecutor { pub async fn delete(&mut self) -> Result<()> { self.args.validate(true).context("validate")?; - let rsp = self.do_cleanup().await.context("do cleanup")?; + let rsp = self.do_cleanup().await.context("shim do cleanup")?; rsp.write_to_writer(&mut std::io::stdout()) .context(Error::FileWrite(format!("write {:?} to stdout", rsp)))?; Ok(()) @@ -41,9 +44,28 @@ impl ShimExecutor { info!(sl!(), "remote socket path: {:?}", &file_path); fs::remove_file(file_path).ok(); } - service::ServiceManager::cleanup(&self.args.id) - .await - .context("cleanup")?; + + if let Err(e) = service::ServiceManager::cleanup(&self.args.id).await { + error!( + sl!(), + "failed to cleanup in service manager: {:?}. force shutdown shim process", e + ); + + let bundle_path = get_bundle_path().context("get bundle path")?; + if let Ok(spec) = load_oci_spec() { + if let Ok(ContainerType::PodSandbox) = get_contaier_type(&spec) { + // only force shutdown for sandbox container + if let Ok(shim_pid) = self.read_pid_file(&bundle_path) { + info!(sl!(), "force to shutdown shim process {}", shim_pid); + let pid = Pid::from_raw(shim_pid as i32); + if let Err(_e) = kill(pid, SIGKILL) { + // ignore kill errors + } + } + } + } + } + Ok(rsp) } } From 046ddc6463dcd0ce671135812f095a6ece8d638e Mon Sep 17 00:00:00 2001 From: Peng Tao Date: Thu, 29 Sep 2022 10:36:59 +0800 Subject: [PATCH 02/42] readme: remove libraries mentioning There are two duplicated mentioning of the rust libraries in README.md. Let's just remove them all as the section is intended to list out core Kata components rather than general libraries. Fixes: #5275 Signed-off-by: Peng Tao --- README.md | 2 -- src/runtime-rs/README.md | 4 ++++ 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 2b0759a2c0..c29a1c8595 100644 --- a/README.md +++ b/README.md @@ -119,10 +119,8 @@ The table below lists the core parts of the project: | [runtime](src/runtime) | core | Main component run by a container manager and providing a containerd shimv2 runtime implementation. | | [runtime-rs](src/runtime-rs) | core | The Rust version runtime. | | [agent](src/agent) | core | Management process running inside the virtual machine / POD that sets up the container environment. | -| [libraries](src/libs) | core | Library crates shared by multiple Kata Container components or published to [`crates.io`](https://crates.io/index.html) | | [`dragonball`](src/dragonball) | core | An optional built-in VMM brings out-of-the-box Kata Containers experience with optimizations on container workloads | | [documentation](docs) | documentation | Documentation common to all components (such as design and install documentation). | -| [libraries](src/libs) | core | Library crates shared by multiple Kata Container components or published to [`crates.io`](https://crates.io/index.html) | | [tests](https://github.com/kata-containers/tests) | tests | Excludes unit tests which live with the main code. | ### Additional components diff --git a/src/runtime-rs/README.md b/src/runtime-rs/README.md index a9f85e45d5..a10e827ba2 100644 --- a/src/runtime-rs/README.md +++ b/src/runtime-rs/README.md @@ -97,6 +97,10 @@ Currently, only built-in `Dragonball` has been implemented. Persist defines traits and functions to help different components save state to disk and load state from disk. +### helper libraries + +Some helper libraries are maintained in [the library directory](../libs) so that they can be shared with other rust components. + ## Build and install ```bash From 8d4ced3c860f1653a101a1ff2a952afe0c7baecd Mon Sep 17 00:00:00 2001 From: Bin Liu Date: Fri, 23 Sep 2022 19:19:08 +0800 Subject: [PATCH 03/42] runtime-rs: support ephemeral storage for emptydir Add support for ephemeral storage and k8s emptydir. Depends-on:github.com/kata-containers/tests#5161 Fixes: #4730 Signed-off-by: Bin Liu --- src/libs/kata-sys-util/src/k8s.rs | 4 +- src/libs/kata-types/src/mount.rs | 2 +- .../crates/resource/src/share_fs/mod.rs | 1 + .../src/share_fs/virtio_fs_share_mount.rs | 48 +++++++++++++++++++ .../resource/src/volume/share_fs_volume.rs | 5 +- .../src/container_manager/container.rs | 5 ++ 6 files changed, 62 insertions(+), 3 deletions(-) diff --git a/src/libs/kata-sys-util/src/k8s.rs b/src/libs/kata-sys-util/src/k8s.rs index be95d5d330..4ae31921e7 100644 --- a/src/libs/kata-sys-util/src/k8s.rs +++ b/src/libs/kata-sys-util/src/k8s.rs @@ -49,7 +49,7 @@ pub fn is_host_empty_dir(path: &str) -> bool { false } -// set_ephemeral_storage_type sets the mount type to 'ephemeral' +// update_ephemeral_storage_type sets the mount type to 'ephemeral' // if the mount source path is provisioned by k8s for ephemeral storage. // For the given pod ephemeral volume is created only once // backed by tmpfs inside the VM. For successive containers @@ -63,6 +63,8 @@ pub fn update_ephemeral_storage_type(oci_spec: &mut Spec) { if is_ephemeral_volume(&m.source) { m.r#type = String::from(mount::KATA_EPHEMERAL_VOLUME_TYPE); } else if is_host_empty_dir(&m.source) { + // FIXME support disable_guest_empty_dir + // https://github.com/kata-containers/kata-containers/blob/02a51e75a7e0c6fce5e8abe3b991eeac87e09645/src/runtime/pkg/katautils/create.go#L105 m.r#type = String::from(mount::KATA_HOST_DIR_VOLUME_TYPE); } } diff --git a/src/libs/kata-types/src/mount.rs b/src/libs/kata-types/src/mount.rs index 2ccc0feed2..b58e810d60 100644 --- a/src/libs/kata-types/src/mount.rs +++ b/src/libs/kata-types/src/mount.rs @@ -13,7 +13,7 @@ pub const KATA_VOLUME_TYPE_PREFIX: &str = "kata:"; pub const KATA_GUEST_MOUNT_PREFIX: &str = "kata:guest-mount:"; /// KATA_EPHEMERAL_DEV_TYPE creates a tmpfs backed volume for sharing files between containers. -pub const KATA_EPHEMERAL_VOLUME_TYPE: &str = "kata:ephemeral"; +pub const KATA_EPHEMERAL_VOLUME_TYPE: &str = "ephemeral"; /// KATA_HOST_DIR_TYPE use for host empty dir pub const KATA_HOST_DIR_VOLUME_TYPE: &str = "kata:hostdir"; diff --git a/src/runtime-rs/crates/resource/src/share_fs/mod.rs b/src/runtime-rs/crates/resource/src/share_fs/mod.rs index b7611964d6..b9abdb9df6 100644 --- a/src/runtime-rs/crates/resource/src/share_fs/mod.rs +++ b/src/runtime-rs/crates/resource/src/share_fs/mod.rs @@ -55,6 +55,7 @@ pub struct ShareFsVolumeConfig { pub target: String, pub readonly: bool, pub mount_options: Vec, + pub mount: oci::Mount, } pub struct ShareFsMountResult { diff --git a/src/runtime-rs/crates/resource/src/share_fs/virtio_fs_share_mount.rs b/src/runtime-rs/crates/resource/src/share_fs/virtio_fs_share_mount.rs index 295554f110..ce32779748 100644 --- a/src/runtime-rs/crates/resource/src/share_fs/virtio_fs_share_mount.rs +++ b/src/runtime-rs/crates/resource/src/share_fs/virtio_fs_share_mount.rs @@ -8,12 +8,15 @@ use agent::Storage; use anyhow::{anyhow, Context, Result}; use async_trait::async_trait; use kata_types::k8s::is_watchable_mount; +use kata_types::mount; +use nix::sys::stat::stat; use std::fs; use std::os::unix::fs::PermissionsExt; use std::path::Path; const WATCHABLE_PATH_NAME: &str = "watchable"; const WATCHABLE_BIND_DEV_TYPE: &str = "watchable-bind"; +const EPHEMERAL_PATH: &str = "/run/kata-containers/sandbox/ephemeral"; use super::{ utils, ShareFsMount, ShareFsMountResult, ShareFsRootfsConfig, ShareFsVolumeConfig, @@ -105,6 +108,51 @@ impl ShareFsMount for VirtiofsShareMount { let storages = vec![watchable_storage]; + return Ok(ShareFsMountResult { + guest_path, + storages, + }); + } else if config.mount.r#type == mount::KATA_EPHEMERAL_VOLUME_TYPE { + // refer to the golang `handleEphemeralStorage` code at + // https://github.com/kata-containers/kata-containers/blob/9516286f6dd5cfd6b138810e5d7c9e01cf6fc043/src/runtime/virtcontainers/kata_agent.go#L1354 + + let source = &config.mount.source; + let file_stat = + stat(Path::new(source)).with_context(|| format!("mount source {}", source))?; + + // if volume's gid isn't root group(default group), this means there's + // an specific fsGroup is set on this local volume, then it should pass + // to guest. + let dir_options = if file_stat.st_gid != 0 { + vec![format!("fsgid={}", file_stat.st_gid)] + } else { + vec![] + }; + + let file_name = Path::new(source) + .file_name() + .context("get file name from mount.source")?; + let source = Path::new(EPHEMERAL_PATH) + .join(file_name) + .into_os_string() + .into_string() + .map_err(|e| anyhow!("failed to get ephemeral path {:?}", e))?; + + // Create a storage struct so that kata agent is able to create + // tmpfs backed volume inside the VM + let ephemeral_storage = agent::Storage { + driver: String::from(mount::KATA_EPHEMERAL_VOLUME_TYPE), + driver_options: Vec::new(), + source: String::from("tmpfs"), + fs_type: String::from("tmpfs"), + fs_group: None, + options: dir_options, + mount_point: source.clone(), + }; + + guest_path = source; + let storages = vec![ephemeral_storage]; + return Ok(ShareFsMountResult { guest_path, storages, diff --git a/src/runtime-rs/crates/resource/src/volume/share_fs_volume.rs b/src/runtime-rs/crates/resource/src/volume/share_fs_volume.rs index d1a01d0306..c75ea5ca12 100644 --- a/src/runtime-rs/crates/resource/src/volume/share_fs_volume.rs +++ b/src/runtime-rs/crates/resource/src/volume/share_fs_volume.rs @@ -10,6 +10,7 @@ use anyhow::{anyhow, Context, Result}; use super::Volume; use crate::share_fs::{ShareFs, ShareFsVolumeConfig}; +use kata_types::mount; // copy file to container's rootfs if filesystem sharing is not supported, otherwise // bind mount it in the shared directory. @@ -66,6 +67,7 @@ impl ShareFsVolume { target: file_name, readonly: false, mount_options: m.options.clone(), + mount: m.clone(), }) .await .context("share fs volume")?; @@ -101,7 +103,8 @@ impl Volume for ShareFsVolume { } pub(crate) fn is_share_fs_volume(m: &oci::Mount) -> bool { - m.r#type == "bind" && !is_host_device(&m.destination) + (m.r#type == "bind" || m.r#type == mount::KATA_EPHEMERAL_VOLUME_TYPE) + && !is_host_device(&m.destination) } fn is_host_device(dest: &str) -> bool { diff --git a/src/runtime-rs/crates/runtimes/virt_container/src/container_manager/container.rs b/src/runtime-rs/crates/runtimes/virt_container/src/container_manager/container.rs index 834c68b77c..74853aec60 100644 --- a/src/runtime-rs/crates/runtimes/virt_container/src/container_manager/container.rs +++ b/src/runtime-rs/crates/runtimes/virt_container/src/container_manager/container.rs @@ -15,6 +15,7 @@ use common::{ ProcessType, }, }; +use kata_sys_util::k8s::update_ephemeral_storage_type; use oci::{LinuxResources, Process as OCIProcess}; use resource::ResourceManager; use tokio::sync::RwLock; @@ -110,6 +111,7 @@ impl Container { .context("handler volumes")?; let mut oci_mounts = vec![]; let mut storages = vec![]; + for v in volumes { let mut volume_mounts = v.get_volume_mount().context("get volume mount")?; if !volume_mounts.is_empty() { @@ -378,6 +380,9 @@ fn amend_spec(spec: &mut oci::Spec, disable_guest_seccomp: bool) -> Result<()> { // hook should be done on host spec.hooks = None; + // special process K8s ephemeral volumes. + update_ephemeral_storage_type(spec); + if let Some(linux) = spec.linux.as_mut() { if disable_guest_seccomp { linux.seccomp = None; From 9717dc3f753673ef362e190a0302fd9a17c27174 Mon Sep 17 00:00:00 2001 From: Chao Wu Date: Sun, 9 Oct 2022 14:33:34 +0800 Subject: [PATCH 04/42] Dragonball: remove redundant comments in event manager handle_events for EventManager doesn't take max_events as arguments, so we need to update the comments for it. p.s. max_events is defined when initializing the EventManager. fixes: #5382 Signed-off-by: Chao Wu --- src/dragonball/src/event_manager.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/src/dragonball/src/event_manager.rs b/src/dragonball/src/event_manager.rs index f07b786506..69bf4dab4c 100644 --- a/src/dragonball/src/event_manager.rs +++ b/src/dragonball/src/event_manager.rs @@ -101,7 +101,6 @@ impl EventManager { /// Poll pending events and invoke registered event handler. /// /// # Arguments: - /// * max_events: maximum number of pending events to handle /// * timeout: maximum time in milliseconds to wait pub fn handle_events(&self, timeout: i32) -> std::result::Result { self.epoll_mgr From 72259f101a67c3c323bc4a58442e7b7bc72ad851 Mon Sep 17 00:00:00 2001 From: wllenyj Date: Tue, 17 May 2022 02:07:12 +0800 Subject: [PATCH 05/42] dragonball: add more unit test for vmm actions Added more unit tests for vmm actions. Signed-off-by: wllenyj --- src/dragonball/src/api/v1/vmm_action.rs | 755 +++++++++++++++++- .../src/device_manager/fs_dev_mgr.rs | 2 +- src/dragonball/src/vm/mod.rs | 14 + 3 files changed, 769 insertions(+), 2 deletions(-) diff --git a/src/dragonball/src/api/v1/vmm_action.rs b/src/dragonball/src/api/v1/vmm_action.rs index 06004f3f0c..d9a529cc99 100644 --- a/src/dragonball/src/api/v1/vmm_action.rs +++ b/src/dragonball/src/api/v1/vmm_action.rs @@ -83,7 +83,7 @@ pub enum VmmActionError { #[cfg(feature = "virtio-fs")] /// The action `InsertFsDevice` failed either because of bad user input or an internal error. - #[error("virtio-fs device: {0}")] + #[error("virtio-fs device error: {0}")] FsDevice(#[source] FsDeviceError), } @@ -634,3 +634,756 @@ fn handle_cpu_topology( Ok(cpu_topology) } + +#[cfg(test)] +mod tests { + use std::sync::mpsc::channel; + use std::sync::{Arc, Mutex}; + + use dbs_utils::epoll_manager::EpollManager; + use vmm_sys_util::tempfile::TempFile; + + use super::*; + use crate::vmm::tests::create_vmm_instance; + + struct TestData<'a> { + req: Option, + vm_state: InstanceState, + f: &'a dyn Fn(VmmRequestResult), + } + + impl<'a> TestData<'a> { + fn new(req: VmmAction, vm_state: InstanceState, f: &'a dyn Fn(VmmRequestResult)) -> Self { + Self { + req: Some(req), + vm_state, + f, + } + } + + fn check_request(&mut self) { + let (to_vmm, from_api) = channel(); + let (to_api, from_vmm) = channel(); + + let vmm = Arc::new(Mutex::new(create_vmm_instance())); + let mut vservice = VmmService::new(from_api, to_api); + + let epoll_mgr = EpollManager::default(); + let mut event_mgr = EventManager::new(&vmm, epoll_mgr).unwrap(); + let mut v = vmm.lock().unwrap(); + + let vm = v.get_vm_mut().unwrap(); + vm.set_instance_state(self.vm_state); + + to_vmm.send(Box::new(self.req.take().unwrap())).unwrap(); + assert!(vservice.run_vmm_action(&mut v, &mut event_mgr).is_ok()); + + let response = from_vmm.try_recv(); + assert!(response.is_ok()); + (&self.f)(*response.unwrap()); + } + } + + #[test] + fn test_vmm_action_receive_unknown() { + let (_to_vmm, from_api) = channel(); + let (to_api, _from_vmm) = channel(); + let vmm = Arc::new(Mutex::new(create_vmm_instance())); + let mut vservice = VmmService::new(from_api, to_api); + let epoll_mgr = EpollManager::default(); + let mut event_mgr = EventManager::new(&vmm, epoll_mgr).unwrap(); + let mut v = vmm.lock().unwrap(); + + assert!(vservice.run_vmm_action(&mut v, &mut event_mgr).is_ok()); + } + + #[should_panic] + #[test] + fn test_vmm_action_disconnected() { + let (to_vmm, from_api) = channel(); + let (to_api, _from_vmm) = channel(); + let vmm = Arc::new(Mutex::new(create_vmm_instance())); + let mut vservice = VmmService::new(from_api, to_api); + let epoll_mgr = EpollManager::default(); + let mut event_mgr = EventManager::new(&vmm, epoll_mgr).unwrap(); + let mut v = vmm.lock().unwrap(); + + drop(to_vmm); + vservice.run_vmm_action(&mut v, &mut event_mgr).unwrap(); + } + + #[test] + fn test_vmm_action_config_boot_source() { + let kernel_file = TempFile::new().unwrap(); + + let tests = &mut [ + // invalid state + TestData::new( + VmmAction::ConfigureBootSource(BootSourceConfig::default()), + InstanceState::Running, + &|result| { + if let Err(VmmActionError::BootSource( + BootSourceConfigError::UpdateNotAllowedPostBoot, + )) = result + { + let err_string = format!("{}", result.unwrap_err()); + let expected_err = String::from( + "failed to configure boot source for VM: \ + the update operation is not allowed after boot", + ); + assert_eq!(err_string, expected_err); + } else { + panic!(); + } + }, + ), + // invalid kernel file path + TestData::new( + VmmAction::ConfigureBootSource(BootSourceConfig::default()), + InstanceState::Uninitialized, + &|result| { + if let Err(VmmActionError::BootSource( + BootSourceConfigError::InvalidKernelPath(_), + )) = result + { + let err_string = format!("{}", result.unwrap_err()); + let expected_err = String::from( + "failed to configure boot source for VM: \ + the kernel file cannot be opened due to invalid kernel path or invalid permissions: \ + No such file or directory (os error 2)"); + assert_eq!(err_string, expected_err); + } else { + panic!(); + } + }, + ), + //success + TestData::new( + VmmAction::ConfigureBootSource(BootSourceConfig { + kernel_path: kernel_file.as_path().to_str().unwrap().to_string(), + ..Default::default() + }), + InstanceState::Uninitialized, + &|result| { + assert!(result.is_ok()); + }, + ), + ]; + + for t in tests.iter_mut() { + t.check_request(); + } + } + + #[test] + fn test_vmm_action_set_vm_configuration() { + let tests = &mut [ + // invalid state + TestData::new( + VmmAction::SetVmConfiguration(VmConfigInfo::default()), + InstanceState::Running, + &|result| { + assert!(matches!( + result, + Err(VmmActionError::MachineConfig( + VmConfigError::UpdateNotAllowedPostBoot + )) + )); + let err_string = format!("{}", result.unwrap_err()); + let expected_err = String::from( + "failed to set configuration for the VM: \ + update operation is not allowed after boot", + ); + assert_eq!(err_string, expected_err); + }, + ), + // invalid cpu count (0) + TestData::new( + VmmAction::SetVmConfiguration(VmConfigInfo { + vcpu_count: 0, + ..Default::default() + }), + InstanceState::Uninitialized, + &|result| { + assert!(matches!( + result, + Err(VmmActionError::MachineConfig( + VmConfigError::InvalidVcpuCount(0) + )) + )); + let err_string = format!("{}", result.unwrap_err()); + let expected_err = String::from( + "failed to set configuration for the VM: \ + the vCPU number '0' can only be 1 or an even number when hyperthreading is enabled"); + assert_eq!(err_string, expected_err); + }, + ), + // invalid max cpu count (too small) + TestData::new( + VmmAction::SetVmConfiguration(VmConfigInfo { + vcpu_count: 4, + max_vcpu_count: 2, + ..Default::default() + }), + InstanceState::Uninitialized, + &|result| { + assert!(matches!( + result, + Err(VmmActionError::MachineConfig( + VmConfigError::InvalidMaxVcpuCount(2) + )) + )); + let err_string = format!("{}", result.unwrap_err()); + let expected_err = String::from( + "failed to set configuration for the VM: \ + the max vCPU number '2' shouldn't less than vCPU count and can only be 1 or an even number when hyperthreading is enabled"); + assert_eq!(err_string, expected_err); + }, + ), + // invalid cpu topology (larger than 254) + TestData::new( + VmmAction::SetVmConfiguration(VmConfigInfo { + vcpu_count: 254, + cpu_topology: CpuTopology { + threads_per_core: 2, + cores_per_die: 128, + dies_per_socket: 1, + sockets: 1, + }, + ..Default::default() + }), + InstanceState::Uninitialized, + &|result| { + assert!(matches!( + result, + Err(VmmActionError::MachineConfig( + VmConfigError::VcpuCountExceedsMaximum + )) + )); + let err_string = format!("{}", result.unwrap_err()); + let expected_err = String::from( + "failed to set configuration for the VM: \ + the vCPU number shouldn't large than 254", + ); + + assert_eq!(err_string, expected_err) + }, + ), + // cpu topology and max_vcpu_count are not matched - success + TestData::new( + VmmAction::SetVmConfiguration(VmConfigInfo { + vcpu_count: 16, + max_vcpu_count: 32, + cpu_topology: CpuTopology { + threads_per_core: 1, + cores_per_die: 128, + dies_per_socket: 1, + sockets: 1, + }, + ..Default::default() + }), + InstanceState::Uninitialized, + &|result| { + result.unwrap(); + }, + ), + // invalid threads_per_core + TestData::new( + VmmAction::SetVmConfiguration(VmConfigInfo { + vcpu_count: 4, + max_vcpu_count: 4, + cpu_topology: CpuTopology { + threads_per_core: 4, + cores_per_die: 1, + dies_per_socket: 1, + sockets: 1, + }, + ..Default::default() + }), + InstanceState::Uninitialized, + &|result| { + assert!(matches!( + result, + Err(VmmActionError::MachineConfig( + VmConfigError::InvalidThreadsPerCore(4) + )) + )); + let err_string = format!("{}", result.unwrap_err()); + let expected_err = String::from( + "failed to set configuration for the VM: \ + the threads_per_core number '4' can only be 1 or 2", + ); + + assert_eq!(err_string, expected_err) + }, + ), + // invalid mem size + TestData::new( + VmmAction::SetVmConfiguration(VmConfigInfo { + mem_size_mib: 3, + ..Default::default() + }), + InstanceState::Uninitialized, + &|result| { + assert!(matches!( + result, + Err(VmmActionError::MachineConfig( + VmConfigError::InvalidMemorySize(3) + )) + )); + let err_string = format!("{}", result.unwrap_err()); + let expected_err = String::from( + "failed to set configuration for the VM: \ + the memory size 0x3MiB is invalid", + ); + assert_eq!(err_string, expected_err); + }, + ), + // invalid mem path + TestData::new( + VmmAction::SetVmConfiguration(VmConfigInfo { + mem_type: String::from("hugetlbfs"), + mem_file_path: String::from(""), + ..Default::default() + }), + InstanceState::Uninitialized, + &|result| { + assert!(matches!( + result, + Err(VmmActionError::MachineConfig( + VmConfigError::InvalidMemFilePath(_) + )) + )); + let err_string = format!("{}", result.unwrap_err()); + let expected_err = String::from( + "failed to set configuration for the VM: \ + the memory file path is invalid", + ); + assert_eq!(err_string, expected_err); + }, + ), + // success + TestData::new( + VmmAction::SetVmConfiguration(VmConfigInfo::default()), + InstanceState::Uninitialized, + &|result| { + assert!(result.is_ok()); + }, + ), + ]; + + for t in tests.iter_mut() { + t.check_request(); + } + } + + #[test] + fn test_vmm_action_start_microvm() { + let tests = &mut [ + // invalid state (running) + TestData::new(VmmAction::StartMicroVm, InstanceState::Running, &|result| { + assert!(matches!( + result, + Err(VmmActionError::StartMicroVm( + StartMicroVmError::MicroVMAlreadyRunning + )) + )); + let err_string = format!("{}", result.unwrap_err()); + let expected_err = String::from( + "failed to boot the VM: \ + the virtual machine is already running", + ); + assert_eq!(err_string, expected_err); + }), + // no kernel configuration + TestData::new( + VmmAction::StartMicroVm, + InstanceState::Uninitialized, + &|result| { + assert!(matches!( + result, + Err(VmmActionError::StartMicroVm( + StartMicroVmError::MissingKernelConfig + )) + )); + let err_string = format!("{}", result.unwrap_err()); + let expected_err = String::from( + "failed to boot the VM: \ + cannot start the virtual machine without kernel configuration", + ); + assert_eq!(err_string, expected_err); + }, + ), + ]; + + for t in tests.iter_mut() { + t.check_request(); + } + } + + #[test] + fn test_vmm_action_shutdown_microvm() { + let tests = &mut [ + // success + TestData::new( + VmmAction::ShutdownMicroVm, + InstanceState::Uninitialized, + &|result| { + assert!(result.is_ok()); + }, + ), + ]; + + for t in tests.iter_mut() { + t.check_request(); + } + } + + #[cfg(feature = "virtio-blk")] + #[test] + fn test_vmm_action_insert_block_device() { + let dummy_file = TempFile::new().unwrap(); + let dummy_path = dummy_file.as_path().to_owned(); + + let tests = &mut [ + // invalid state + TestData::new( + VmmAction::InsertBlockDevice(BlockDeviceConfigInfo::default()), + InstanceState::Running, + &|result| { + assert!(matches!( + result, + Err(VmmActionError::Block( + BlockDeviceError::UpdateNotAllowedPostBoot + )) + )); + let err_string = format!("{}", result.unwrap_err()); + let expected_err = String::from( + "virtio-blk device error: \ + block device does not support runtime update", + ); + assert_eq!(err_string, expected_err); + }, + ), + // success + TestData::new( + VmmAction::InsertBlockDevice(BlockDeviceConfigInfo { + path_on_host: dummy_path, + device_type: crate::device_manager::blk_dev_mgr::BlockDeviceType::RawBlock, + is_root_device: true, + part_uuid: None, + is_read_only: false, + is_direct: false, + no_drop: false, + drive_id: String::from("1"), + rate_limiter: None, + num_queues: BlockDeviceConfigInfo::default_num_queues(), + queue_size: 256, + use_shared_irq: None, + use_generic_irq: None, + }), + InstanceState::Uninitialized, + &|result| { + assert!(result.is_ok()); + }, + ), + ]; + + for t in tests.iter_mut() { + t.check_request(); + } + } + + #[cfg(feature = "virtio-blk")] + #[test] + fn test_vmm_action_update_block_device() { + let tests = &mut [ + // invalid id + TestData::new( + VmmAction::UpdateBlockDevice(BlockDeviceConfigUpdateInfo { + drive_id: String::from("1"), + rate_limiter: None, + }), + InstanceState::Running, + &|result| { + assert!(matches!( + result, + Err(VmmActionError::Block(BlockDeviceError::InvalidDeviceId(_))) + )); + let err_string = format!("{}", result.unwrap_err()); + let expected_err = String::from( + "virtio-blk device error: \ + invalid block device id '1'", + ); + assert_eq!(err_string, expected_err); + }, + ), + ]; + + for t in tests.iter_mut() { + t.check_request(); + } + } + + #[cfg(feature = "virtio-blk")] + #[test] + fn test_vmm_action_remove_block_device() { + let tests = &mut [ + // invalid state + TestData::new( + VmmAction::RemoveBlockDevice(String::from("1")), + InstanceState::Running, + &|result| { + assert!(matches!( + result, + Err(VmmActionError::Block( + BlockDeviceError::UpdateNotAllowedPostBoot + )) + )); + let err_string = format!("{}", result.unwrap_err()); + let expected_err = String::from( + "virtio-blk device error: \ + block device does not support runtime update", + ); + assert_eq!(err_string, expected_err); + }, + ), + // invalid id + TestData::new( + VmmAction::RemoveBlockDevice(String::from("1")), + InstanceState::Uninitialized, + &|result| { + assert!(matches!( + result, + Err(VmmActionError::Block(BlockDeviceError::InvalidDeviceId(_))) + )); + let err_string = format!("{}", result.unwrap_err()); + let expected_err = String::from( + "virtio-blk device error: \ + invalid block device id '1'", + ); + assert_eq!(err_string, expected_err); + }, + ), + ]; + + for t in tests.iter_mut() { + t.check_request(); + } + } + + #[cfg(feature = "virtio-fs")] + #[test] + fn test_vmm_action_insert_fs_device() { + let tests = &mut [ + // invalid state + TestData::new( + VmmAction::InsertFsDevice(FsDeviceConfigInfo::default()), + InstanceState::Running, + &|result| { + assert!(matches!( + result, + Err(VmmActionError::FsDevice( + FsDeviceError::UpdateNotAllowedPostBoot + )) + )); + let err_string = format!("{}", result.unwrap_err()); + let expected_err = String::from( + "virtio-fs device error: \ + update operation is not allowed after boot", + ); + assert_eq!(err_string, expected_err); + }, + ), + // success + TestData::new( + VmmAction::InsertFsDevice(FsDeviceConfigInfo::default()), + InstanceState::Uninitialized, + &|result| { + assert!(result.is_ok()); + }, + ), + ]; + + for t in tests.iter_mut() { + t.check_request(); + } + } + + #[cfg(feature = "virtio-fs")] + #[test] + fn test_vmm_action_manipulate_fs_device() { + let tests = &mut [ + // invalid state + TestData::new( + VmmAction::ManipulateFsBackendFs(FsMountConfigInfo::default()), + InstanceState::Uninitialized, + &|result| { + assert!(matches!( + result, + Err(VmmActionError::FsDevice(FsDeviceError::MicroVMNotRunning)) + )); + let err_string = format!("{}", result.unwrap_err()); + let expected_err = String::from( + "virtio-fs device error: \ + vm is not running when attaching a backend fs", + ); + assert_eq!(err_string, expected_err); + }, + ), + // invalid backend + TestData::new( + VmmAction::ManipulateFsBackendFs(FsMountConfigInfo::default()), + InstanceState::Running, + &|result| { + assert!(matches!( + result, + Err(VmmActionError::FsDevice( + FsDeviceError::AttachBackendFailed(_) + )) + )); + let err_string = format!("{}", result.unwrap_err()); + println!("{}", err_string); + let expected_err = String::from( + "virtio-fs device error: \ + Fs device attach a backend fs failed", + ); + assert_eq!(err_string, expected_err); + }, + ), + ]; + for t in tests.iter_mut() { + t.check_request(); + } + } + + #[cfg(feature = "virtio-net")] + #[test] + fn test_vmm_action_insert_network_device() { + let tests = &mut [ + // hotplug unready + TestData::new( + VmmAction::InsertNetworkDevice(VirtioNetDeviceConfigInfo::default()), + InstanceState::Running, + &|result| { + assert!(matches!( + result, + Err(VmmActionError::StartMicroVm( + StartMicroVmError::UpcallMissVsock + )) + )); + let err_string = format!("{}", result.unwrap_err()); + let expected_err = String::from( + "failed to boot the VM: \ + the upcall client needs a virtio-vsock device for communication", + ); + assert_eq!(err_string, expected_err); + }, + ), + // success + TestData::new( + VmmAction::InsertNetworkDevice(VirtioNetDeviceConfigInfo::default()), + InstanceState::Uninitialized, + &|result| { + assert!(result.is_ok()); + }, + ), + ]; + + for t in tests.iter_mut() { + t.check_request(); + } + } + + #[cfg(feature = "virtio-net")] + #[test] + fn test_vmm_action_update_network_interface() { + let tests = &mut [ + // invalid id + TestData::new( + VmmAction::UpdateNetworkInterface(VirtioNetDeviceConfigUpdateInfo { + iface_id: String::from("1"), + rx_rate_limiter: None, + tx_rate_limiter: None, + }), + InstanceState::Running, + &|result| { + assert!(matches!( + result, + Err(VmmActionError::VirtioNet( + VirtioNetDeviceError::InvalidIfaceId(_) + )) + )); + let err_string = format!("{}", result.unwrap_err()); + let expected_err = String::from( + "virtio-net device error: \ + invalid virtio-net iface id '1'", + ); + assert_eq!(err_string, expected_err); + }, + ), + ]; + + for t in tests.iter_mut() { + t.check_request(); + } + } + + #[cfg(feature = "virtio-vsock")] + #[test] + fn test_vmm_action_insert_vsock_device() { + let tests = &mut [ + // invalid state + TestData::new( + VmmAction::InsertVsockDevice(VsockDeviceConfigInfo::default()), + InstanceState::Running, + &|result| { + assert!(matches!( + result, + Err(VmmActionError::Vsock( + VsockDeviceError::UpdateNotAllowedPostBoot + )) + )); + let err_string = format!("{}", result.unwrap_err()); + let expected_err = String::from( + "failed to add virtio-vsock device: \ + update operation is not allowed after boot", + ); + assert_eq!(err_string, expected_err); + }, + ), + // invalid guest_cid + TestData::new( + VmmAction::InsertVsockDevice(VsockDeviceConfigInfo::default()), + InstanceState::Uninitialized, + &|result| { + assert!(matches!( + result, + Err(VmmActionError::Vsock(VsockDeviceError::GuestCIDInvalid(0))) + )); + let err_string = format!("{}", result.unwrap_err()); + let expected_err = String::from( + "failed to add virtio-vsock device: \ + the guest CID 0 is invalid", + ); + assert_eq!(err_string, expected_err); + }, + ), + // success + TestData::new( + VmmAction::InsertVsockDevice(VsockDeviceConfigInfo { + guest_cid: 3, + ..Default::default() + }), + InstanceState::Uninitialized, + &|result| { + assert!(result.is_ok()); + }, + ), + ]; + + for t in tests.iter_mut() { + t.check_request(); + } + } +} diff --git a/src/dragonball/src/device_manager/fs_dev_mgr.rs b/src/dragonball/src/device_manager/fs_dev_mgr.rs index 088dc980f1..76b1d2d93d 100644 --- a/src/dragonball/src/device_manager/fs_dev_mgr.rs +++ b/src/dragonball/src/device_manager/fs_dev_mgr.rs @@ -242,7 +242,7 @@ impl ConfigItem for FsDeviceConfigInfo { } /// Configuration information of manipulating backend fs for a virtiofs device. -#[derive(Clone, Debug, Deserialize, PartialEq, Serialize)] +#[derive(Clone, Debug, Deserialize, PartialEq, Serialize, Default)] pub struct FsMountConfigInfo { /// Mount operations, mount, update, umount pub ops: String, diff --git a/src/dragonball/src/vm/mod.rs b/src/dragonball/src/vm/mod.rs index f5f62a0407..1d78ac31cb 100644 --- a/src/dragonball/src/vm/mod.rs +++ b/src/dragonball/src/vm/mod.rs @@ -814,3 +814,17 @@ impl Vm { Err(StartMicroVmError::MicroVMAlreadyRunning) } } + +#[cfg(test)] +pub mod tests { + use super::*; + + impl Vm { + pub fn set_instance_state(&mut self, mstate: InstanceState) { + self.shared_info + .write() + .expect("Failed to start microVM because shared info couldn't be written due to poisoned lock") + .state = mstate; + } + } +} From 3fe81fe4ab2625fb04c55bff29fc1a2056787b71 Mon Sep 17 00:00:00 2001 From: wllenyj Date: Mon, 22 Aug 2022 18:14:40 +0800 Subject: [PATCH 06/42] dragonball-ut: use skip_if_not_root to skip root case Use skip_if_not_root to skip when unit test requires privileges. Signed-off-by: wllenyj --- src/dragonball/Cargo.toml | 1 + src/dragonball/src/api/v1/vmm_action.rs | 27 +++++++++++++++++++++++++ src/dragonball/src/kvm_context.rs | 13 ++++++++++-- src/dragonball/src/vcpu/vcpu_impl.rs | 5 +++++ src/dragonball/src/vmm.rs | 4 ++++ 5 files changed, 48 insertions(+), 2 deletions(-) diff --git a/src/dragonball/Cargo.toml b/src/dragonball/Cargo.toml index c1a24a4f69..b103d4f149 100644 --- a/src/dragonball/Cargo.toml +++ b/src/dragonball/Cargo.toml @@ -43,6 +43,7 @@ vm-memory = { version = "0.9.0", features = ["backend-mmap"] } [dev-dependencies] slog-term = "2.9.0" slog-async = "2.7.0" +test-utils = { path = "../libs/test-utils" } [features] acpi = [] diff --git a/src/dragonball/src/api/v1/vmm_action.rs b/src/dragonball/src/api/v1/vmm_action.rs index d9a529cc99..96ca6d1508 100644 --- a/src/dragonball/src/api/v1/vmm_action.rs +++ b/src/dragonball/src/api/v1/vmm_action.rs @@ -641,6 +641,7 @@ mod tests { use std::sync::{Arc, Mutex}; use dbs_utils::epoll_manager::EpollManager; + use test_utils::skip_if_not_root; use vmm_sys_util::tempfile::TempFile; use super::*; @@ -686,6 +687,8 @@ mod tests { #[test] fn test_vmm_action_receive_unknown() { + skip_if_not_root!(); + let (_to_vmm, from_api) = channel(); let (to_api, _from_vmm) = channel(); let vmm = Arc::new(Mutex::new(create_vmm_instance())); @@ -714,6 +717,8 @@ mod tests { #[test] fn test_vmm_action_config_boot_source() { + skip_if_not_root!(); + let kernel_file = TempFile::new().unwrap(); let tests = &mut [ @@ -777,6 +782,8 @@ mod tests { #[test] fn test_vmm_action_set_vm_configuration() { + skip_if_not_root!(); + let tests = &mut [ // invalid state TestData::new( @@ -979,6 +986,8 @@ mod tests { #[test] fn test_vmm_action_start_microvm() { + skip_if_not_root!(); + let tests = &mut [ // invalid state (running) TestData::new(VmmAction::StartMicroVm, InstanceState::Running, &|result| { @@ -1023,6 +1032,8 @@ mod tests { #[test] fn test_vmm_action_shutdown_microvm() { + skip_if_not_root!(); + let tests = &mut [ // success TestData::new( @@ -1042,6 +1053,8 @@ mod tests { #[cfg(feature = "virtio-blk")] #[test] fn test_vmm_action_insert_block_device() { + skip_if_not_root!(); + let dummy_file = TempFile::new().unwrap(); let dummy_path = dummy_file.as_path().to_owned(); @@ -1097,6 +1110,8 @@ mod tests { #[cfg(feature = "virtio-blk")] #[test] fn test_vmm_action_update_block_device() { + skip_if_not_root!(); + let tests = &mut [ // invalid id TestData::new( @@ -1128,6 +1143,8 @@ mod tests { #[cfg(feature = "virtio-blk")] #[test] fn test_vmm_action_remove_block_device() { + skip_if_not_root!(); + let tests = &mut [ // invalid state TestData::new( @@ -1175,6 +1192,8 @@ mod tests { #[cfg(feature = "virtio-fs")] #[test] fn test_vmm_action_insert_fs_device() { + skip_if_not_root!(); + let tests = &mut [ // invalid state TestData::new( @@ -1213,6 +1232,8 @@ mod tests { #[cfg(feature = "virtio-fs")] #[test] fn test_vmm_action_manipulate_fs_device() { + skip_if_not_root!(); + let tests = &mut [ // invalid state TestData::new( @@ -1260,6 +1281,8 @@ mod tests { #[cfg(feature = "virtio-net")] #[test] fn test_vmm_action_insert_network_device() { + skip_if_not_root!(); + let tests = &mut [ // hotplug unready TestData::new( @@ -1298,6 +1321,8 @@ mod tests { #[cfg(feature = "virtio-net")] #[test] fn test_vmm_action_update_network_interface() { + skip_if_not_root!(); + let tests = &mut [ // invalid id TestData::new( @@ -1332,6 +1357,8 @@ mod tests { #[cfg(feature = "virtio-vsock")] #[test] fn test_vmm_action_insert_vsock_device() { + skip_if_not_root!(); + let tests = &mut [ // invalid state TestData::new( diff --git a/src/dragonball/src/kvm_context.rs b/src/dragonball/src/kvm_context.rs index f160b264b8..f4a8408608 100644 --- a/src/dragonball/src/kvm_context.rs +++ b/src/dragonball/src/kvm_context.rs @@ -210,14 +210,19 @@ mod x86_64 { #[cfg(test)] mod tests { - use super::*; - use kvm_ioctls::Kvm; use std::fs::File; use std::os::unix::fs::MetadataExt; use std::os::unix::io::{AsRawFd, FromRawFd}; + use kvm_ioctls::Kvm; + use test_utils::skip_if_not_root; + + use super::*; + #[test] fn test_create_kvm_context() { + skip_if_not_root!(); + let c = KvmContext::new(None).unwrap(); assert!(c.max_memslots >= 32); @@ -234,6 +239,8 @@ mod tests { #[cfg(target_arch = "x86_64")] #[test] fn test_get_supported_cpu_id() { + skip_if_not_root!(); + let c = KvmContext::new(None).unwrap(); let _ = c @@ -244,6 +251,8 @@ mod tests { #[test] fn test_create_vm() { + skip_if_not_root!(); + let c = KvmContext::new(None).unwrap(); let _ = c.create_vm().unwrap(); diff --git a/src/dragonball/src/vcpu/vcpu_impl.rs b/src/dragonball/src/vcpu/vcpu_impl.rs index 513fa435f9..ae5d404d1a 100644 --- a/src/dragonball/src/vcpu/vcpu_impl.rs +++ b/src/dragonball/src/vcpu/vcpu_impl.rs @@ -771,6 +771,7 @@ pub mod tests { use dbs_device::device_manager::IoManager; use kvm_ioctls::Kvm; use lazy_static::lazy_static; + use test_utils::skip_if_not_root; use super::*; use crate::kvm_context::KvmContext; @@ -880,6 +881,8 @@ pub mod tests { #[test] fn test_vcpu_run_emulation() { + skip_if_not_root!(); + let (mut vcpu, _) = create_vcpu(); #[cfg(target_arch = "x86_64")] @@ -964,6 +967,8 @@ pub mod tests { #[cfg(target_arch = "x86_64")] #[test] fn test_vcpu_check_io_port_info() { + skip_if_not_root!(); + let (vcpu, _receiver) = create_vcpu(); // debug info signal diff --git a/src/dragonball/src/vmm.rs b/src/dragonball/src/vmm.rs index a25543e342..1cfbfac584 100644 --- a/src/dragonball/src/vmm.rs +++ b/src/dragonball/src/vmm.rs @@ -189,6 +189,8 @@ impl Vmm { #[cfg(test)] pub(crate) mod tests { + use test_utils::skip_if_not_root; + use super::*; pub fn create_vmm_instance() -> Vmm { @@ -210,6 +212,8 @@ pub(crate) mod tests { #[test] fn test_create_vmm_instance() { + skip_if_not_root!(); + create_vmm_instance(); } } From 2ddc948d30abb1bbc0a1883e8c29755f3254706e Mon Sep 17 00:00:00 2001 From: wllenyj Date: Mon, 22 Aug 2022 17:55:31 +0800 Subject: [PATCH 07/42] Makefile: add dragonball components. Enable ci to run dragonball unit tests. Fixes: #4899 Signed-off-by: wllenyj --- Makefile | 1 + src/dragonball/Makefile | 3 +++ 2 files changed, 4 insertions(+) diff --git a/Makefile b/Makefile index 4d2be6b4d8..6eca68ae1b 100644 --- a/Makefile +++ b/Makefile @@ -8,6 +8,7 @@ COMPONENTS = COMPONENTS += libs COMPONENTS += agent +COMPONENTS += dragonball COMPONENTS += runtime COMPONENTS += runtime-rs diff --git a/src/dragonball/Makefile b/src/dragonball/Makefile index ca4216b1f7..c4955cf856 100644 --- a/src/dragonball/Makefile +++ b/src/dragonball/Makefile @@ -15,6 +15,9 @@ clippy: -- \ -D warnings +vendor: + @echo "INFO: vendor do nothing.." + format: @echo "INFO: cargo fmt..." cargo fmt -- --check From b62b18bf1cad5ceaa8e133924177daf01e8931f7 Mon Sep 17 00:00:00 2001 From: wllenyj Date: Fri, 23 Sep 2022 00:17:00 +0800 Subject: [PATCH 08/42] dragonball: fix clippy warning Fixed: - unnecessary_lazy_evaluations - derive_partial_eq_without_eq - redundant_closure - single_match - question_mark - unused-must-use - redundant_clone - needless_return Signed-off-by: wllenyj --- src/dragonball/src/address_space_manager.rs | 16 +++++----- src/dragonball/src/api/v1/boot_source.rs | 2 +- src/dragonball/src/api/v1/instance_info.rs | 4 +-- src/dragonball/src/api/v1/machine_config.rs | 2 +- src/dragonball/src/api/v1/vmm_action.rs | 5 ++-- src/dragonball/src/config_manager.rs | 6 ++-- .../src/device_manager/blk_dev_mgr.rs | 8 ++--- .../src/device_manager/fs_dev_mgr.rs | 6 ++-- src/dragonball/src/device_manager/mod.rs | 8 +++-- .../src/device_manager/virtio_net_dev_mgr.rs | 6 ++-- .../src/device_manager/vsock_dev_mgr.rs | 2 +- src/dragonball/src/resource_manager.rs | 30 +++++++++---------- src/dragonball/src/vcpu/vcpu_impl.rs | 15 ++++------ src/dragonball/src/vm/mod.rs | 6 ++-- 14 files changed, 56 insertions(+), 60 deletions(-) diff --git a/src/dragonball/src/address_space_manager.rs b/src/dragonball/src/address_space_manager.rs index bcc1083a9d..6e4144618c 100644 --- a/src/dragonball/src/address_space_manager.rs +++ b/src/dragonball/src/address_space_manager.rs @@ -35,8 +35,8 @@ use nix::unistd::dup; #[cfg(feature = "atomic-guest-memory")] use vm_memory::GuestMemoryAtomic; use vm_memory::{ - address::Address, FileOffset, GuestAddress, GuestAddressSpace, GuestMemoryMmap, GuestMemoryRegion, - GuestRegionMmap, GuestUsize, MemoryRegionAddress, MmapRegion, + address::Address, FileOffset, GuestAddress, GuestAddressSpace, GuestMemoryMmap, + GuestMemoryRegion, GuestRegionMmap, GuestUsize, MemoryRegionAddress, MmapRegion, }; use crate::resource_manager::ResourceManager; @@ -270,7 +270,7 @@ impl AddressSpaceMgr { let size = info .size .checked_shl(20) - .ok_or_else(|| AddressManagerError::InvalidOperation)?; + .ok_or(AddressManagerError::InvalidOperation)?; // Guest memory does not intersect with the MMIO hole. // TODO: make it work for ARM (issue #4307) @@ -281,13 +281,13 @@ impl AddressSpaceMgr { regions.push(region); start_addr = start_addr .checked_add(size) - .ok_or_else(|| AddressManagerError::InvalidOperation)?; + .ok_or(AddressManagerError::InvalidOperation)?; } else { // Add guest memory below the MMIO hole, avoid splitting the memory region // if the available address region is small than MINIMAL_SPLIT_SPACE MiB. let mut below_size = dbs_boot::layout::MMIO_LOW_START .checked_sub(start_addr) - .ok_or_else(|| AddressManagerError::InvalidOperation)?; + .ok_or(AddressManagerError::InvalidOperation)?; if below_size < (MINIMAL_SPLIT_SPACE) { below_size = 0; } else { @@ -299,12 +299,12 @@ impl AddressSpaceMgr { let above_start = dbs_boot::layout::MMIO_LOW_END + 1; let above_size = size .checked_sub(below_size) - .ok_or_else(|| AddressManagerError::InvalidOperation)?; + .ok_or(AddressManagerError::InvalidOperation)?; let region = self.create_region(above_start, above_size, info, &mut param)?; regions.push(region); start_addr = above_start .checked_add(above_size) - .ok_or_else(|| AddressManagerError::InvalidOperation)?; + .ok_or(AddressManagerError::InvalidOperation)?; } } @@ -502,7 +502,7 @@ impl AddressSpaceMgr { fn configure_numa(&self, mmap_reg: &MmapRegion, node_id: u32) -> Result<()> { let nodemask = 1_u64 .checked_shl(node_id) - .ok_or_else(|| AddressManagerError::InvalidOperation)?; + .ok_or(AddressManagerError::InvalidOperation)?; let res = unsafe { libc::syscall( libc::SYS_mbind, diff --git a/src/dragonball/src/api/v1/boot_source.rs b/src/dragonball/src/api/v1/boot_source.rs index 8ff7e030dc..612de04a18 100644 --- a/src/dragonball/src/api/v1/boot_source.rs +++ b/src/dragonball/src/api/v1/boot_source.rs @@ -18,7 +18,7 @@ pub const DEFAULT_KERNEL_CMDLINE: &str = "reboot=k panic=1 pci=off nomodules 825 i8042.noaux i8042.nomux i8042.nopnp i8042.dumbkbd"; /// Strongly typed data structure used to configure the boot source of the microvm. -#[derive(Clone, Debug, Deserialize, PartialEq, Serialize, Default)] +#[derive(Clone, Debug, Deserialize, PartialEq, Eq, Serialize, Default)] #[serde(deny_unknown_fields)] pub struct BootSourceConfig { /// Path of the kernel image. diff --git a/src/dragonball/src/api/v1/instance_info.rs b/src/dragonball/src/api/v1/instance_info.rs index ae159aa614..86174a2fd7 100644 --- a/src/dragonball/src/api/v1/instance_info.rs +++ b/src/dragonball/src/api/v1/instance_info.rs @@ -10,7 +10,7 @@ use serde_derive::{Deserialize, Serialize}; /// When Dragonball starts, the instance state is Uninitialized. Once start_microvm method is /// called, the state goes from Uninitialized to Starting. The state is changed to Running until /// the start_microvm method ends. Halting and Halted are currently unsupported. -#[derive(Copy, Clone, Debug, Deserialize, PartialEq, Serialize)] +#[derive(Copy, Clone, Debug, Deserialize, PartialEq, Eq, Serialize)] pub enum InstanceState { /// Microvm is not initialized. Uninitialized, @@ -29,7 +29,7 @@ pub enum InstanceState { } /// The state of async actions -#[derive(Debug, Deserialize, Serialize, Clone, PartialEq)] +#[derive(Debug, Deserialize, Serialize, Clone, PartialEq, Eq)] pub enum AsyncState { /// Uninitialized Uninitialized, diff --git a/src/dragonball/src/api/v1/machine_config.rs b/src/dragonball/src/api/v1/machine_config.rs index e4ae228679..7d78f3e443 100644 --- a/src/dragonball/src/api/v1/machine_config.rs +++ b/src/dragonball/src/api/v1/machine_config.rs @@ -10,7 +10,7 @@ pub const MAX_SUPPORTED_VCPUS: u8 = 254; pub const MEMORY_HOTPLUG_ALIGHMENT: u8 = 64; /// Errors associated with configuring the microVM. -#[derive(Debug, PartialEq, thiserror::Error)] +#[derive(Debug, PartialEq, Eq, thiserror::Error)] pub enum VmConfigError { /// Cannot update the configuration of the microvm post boot. #[error("update operation is not allowed after boot")] diff --git a/src/dragonball/src/api/v1/vmm_action.rs b/src/dragonball/src/api/v1/vmm_action.rs index 96ca6d1508..ac1742e953 100644 --- a/src/dragonball/src/api/v1/vmm_action.rs +++ b/src/dragonball/src/api/v1/vmm_action.rs @@ -89,7 +89,7 @@ pub enum VmmActionError { /// This enum represents the public interface of the VMM. Each action contains various /// bits of information (ids, paths, etc.). -#[derive(Clone, Debug, PartialEq)] +#[derive(Clone, Debug, PartialEq, Eq)] pub enum VmmAction { /// Configure the boot source of the microVM using `BootSourceConfig`. /// This action can only be called before the microVM has booted. @@ -298,7 +298,6 @@ impl VmmService { let mut cmdline = linux_loader::cmdline::Cmdline::new(dbs_boot::layout::CMDLINE_MAX_SIZE); let boot_args = boot_source_config .boot_args - .clone() .unwrap_or_else(|| String::from(DEFAULT_KERNEL_CMDLINE)); cmdline .insert_str(boot_args) @@ -681,7 +680,7 @@ mod tests { let response = from_vmm.try_recv(); assert!(response.is_ok()); - (&self.f)(*response.unwrap()); + (self.f)(*response.unwrap()); } } diff --git a/src/dragonball/src/config_manager.rs b/src/dragonball/src/config_manager.rs index fbb66611c3..34a2af2e0f 100644 --- a/src/dragonball/src/config_manager.rs +++ b/src/dragonball/src/config_manager.rs @@ -46,7 +46,7 @@ pub trait ConfigItem { } /// Struct to manage a group of configuration items. -#[derive(Debug, Default, Deserialize, PartialEq, Serialize)] +#[derive(Debug, Default, Deserialize, PartialEq, Eq, Serialize)] pub struct ConfigInfos where T: ConfigItem + Clone, @@ -316,7 +316,7 @@ where } /// Configuration information for RateLimiter token bucket. -#[derive(Clone, Debug, Default, Deserialize, PartialEq, Serialize)] +#[derive(Clone, Debug, Default, Deserialize, PartialEq, Eq, Serialize)] pub struct TokenBucketConfigInfo { /// The size for the token bucket. A TokenBucket of `size` total capacity will take `refill_time` /// milliseconds to go from zero tokens to total capacity. @@ -349,7 +349,7 @@ impl From<&TokenBucketConfigInfo> for TokenBucket { } /// Configuration information for RateLimiter objects. -#[derive(Clone, Debug, Default, Deserialize, PartialEq, Serialize)] +#[derive(Clone, Debug, Default, Deserialize, PartialEq, Eq, Serialize)] pub struct RateLimiterConfigInfo { /// Data used to initialize the RateLimiter::bandwidth bucket. pub bandwidth: TokenBucketConfigInfo, diff --git a/src/dragonball/src/device_manager/blk_dev_mgr.rs b/src/dragonball/src/device_manager/blk_dev_mgr.rs index 4f0fa1e4b0..a34b951653 100644 --- a/src/dragonball/src/device_manager/blk_dev_mgr.rs +++ b/src/dragonball/src/device_manager/blk_dev_mgr.rs @@ -106,7 +106,7 @@ pub enum BlockDeviceError { } /// Type of low level storage device/protocol for virtio-blk devices. -#[derive(Clone, Copy, Debug, PartialEq, Serialize, Deserialize)] +#[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize, Deserialize)] pub enum BlockDeviceType { /// Unknown low level device type. Unknown, @@ -131,7 +131,7 @@ impl BlockDeviceType { } /// Configuration information for a block device. -#[derive(Clone, Debug, Deserialize, PartialEq, Serialize)] +#[derive(Clone, Debug, Deserialize, PartialEq, Eq, Serialize)] pub struct BlockDeviceConfigUpdateInfo { /// Unique identifier of the drive. pub drive_id: String, @@ -151,7 +151,7 @@ impl BlockDeviceConfigUpdateInfo { } /// Configuration information for a block device. -#[derive(Clone, Debug, Deserialize, PartialEq, Serialize)] +#[derive(Clone, Debug, Deserialize, PartialEq, Eq, Serialize)] pub struct BlockDeviceConfigInfo { /// Unique identifier of the drive. pub drive_id: String, @@ -625,7 +625,7 @@ impl BlockDeviceMgr { // we need to satisfy the condition by which a VMM can only have on root device if block_device_config.is_root_device { if self.has_root_block { - return Err(BlockDeviceError::RootBlockDeviceAlreadyAdded); + Err(BlockDeviceError::RootBlockDeviceAlreadyAdded) } else { self.has_root_block = true; self.read_only_root = block_device_config.is_read_only; diff --git a/src/dragonball/src/device_manager/fs_dev_mgr.rs b/src/dragonball/src/device_manager/fs_dev_mgr.rs index 76b1d2d93d..dca0e649e3 100644 --- a/src/dragonball/src/device_manager/fs_dev_mgr.rs +++ b/src/dragonball/src/device_manager/fs_dev_mgr.rs @@ -89,7 +89,7 @@ pub enum FsDeviceError { } /// Configuration information for a vhost-user-fs device. -#[derive(Clone, Debug, Deserialize, PartialEq, Serialize)] +#[derive(Clone, Debug, Deserialize, PartialEq, Eq, Serialize)] pub struct FsDeviceConfigInfo { /// vhost-user socket path. pub sock_path: String, @@ -201,7 +201,7 @@ impl FsDeviceConfigInfo { } /// Configuration information for virtio-fs. -#[derive(Clone, Debug, Deserialize, PartialEq, Serialize)] +#[derive(Clone, Debug, Deserialize, PartialEq, Eq, Serialize)] pub struct FsDeviceConfigUpdateInfo { /// virtiofs mount tag name used inside the guest. /// used as the device name during mount. @@ -242,7 +242,7 @@ impl ConfigItem for FsDeviceConfigInfo { } /// Configuration information of manipulating backend fs for a virtiofs device. -#[derive(Clone, Debug, Deserialize, PartialEq, Serialize, Default)] +#[derive(Clone, Debug, Deserialize, PartialEq, Eq, Serialize, Default)] pub struct FsMountConfigInfo { /// Mount operations, mount, update, umount pub ops: String, diff --git a/src/dragonball/src/device_manager/mod.rs b/src/dragonball/src/device_manager/mod.rs index 8e1b3456fc..75eaef6ac3 100644 --- a/src/dragonball/src/device_manager/mod.rs +++ b/src/dragonball/src/device_manager/mod.rs @@ -147,7 +147,11 @@ pub type Result = ::std::result::Result; /// Type of the dragonball virtio devices. #[cfg(feature = "dbs-virtio-devices")] pub type DbsVirtioDevice = Box< - dyn VirtioDevice, + dyn VirtioDevice< + GuestAddressSpaceImpl, + virtio_queue::QueueStateSync, + vm_memory::GuestRegionMmap, + >, >; /// Type of the dragonball virtio mmio devices. @@ -997,7 +1001,7 @@ impl DeviceManager { { self.vsock_manager .get_default_connector() - .map(|d| Some(d)) + .map(Some) .unwrap_or(None) } #[cfg(not(feature = "virtio-vsock"))] diff --git a/src/dragonball/src/device_manager/virtio_net_dev_mgr.rs b/src/dragonball/src/device_manager/virtio_net_dev_mgr.rs index 3283a00d91..c0b0f62daa 100644 --- a/src/dragonball/src/device_manager/virtio_net_dev_mgr.rs +++ b/src/dragonball/src/device_manager/virtio_net_dev_mgr.rs @@ -93,7 +93,7 @@ pub enum VirtioNetDeviceError { } /// Configuration information for virtio net devices. -#[derive(Clone, Debug, Deserialize, PartialEq, Serialize)] +#[derive(Clone, Debug, Deserialize, PartialEq, Eq, Serialize)] pub struct VirtioNetDeviceConfigUpdateInfo { /// ID of the guest network interface. pub iface_id: String, @@ -123,7 +123,7 @@ impl VirtioNetDeviceConfigUpdateInfo { } /// Configuration information for virtio net devices. -#[derive(Clone, Debug, Deserialize, PartialEq, Serialize, Default)] +#[derive(Clone, Debug, Deserialize, PartialEq, Eq, Serialize, Default)] pub struct VirtioNetDeviceConfigInfo { /// ID of the guest network interface. pub iface_id: String, @@ -264,7 +264,7 @@ impl VirtioNetDeviceMgr { config.use_generic_irq.unwrap_or(USE_GENERIC_IRQ), ) .map_err(VirtioNetDeviceError::DeviceManager)?; - ctx.insert_hotplug_mmio_device(&dev.clone(), None) + ctx.insert_hotplug_mmio_device(&dev, None) .map_err(VirtioNetDeviceError::DeviceManager)?; // live-upgrade need save/restore device from info.device. mgr.info_list[device_index].set_device(dev); diff --git a/src/dragonball/src/device_manager/vsock_dev_mgr.rs b/src/dragonball/src/device_manager/vsock_dev_mgr.rs index 4f0f074134..8588471b71 100644 --- a/src/dragonball/src/device_manager/vsock_dev_mgr.rs +++ b/src/dragonball/src/device_manager/vsock_dev_mgr.rs @@ -70,7 +70,7 @@ pub enum VsockDeviceError { } /// Configuration information for a vsock device. -#[derive(Clone, Debug, Deserialize, PartialEq, Serialize)] +#[derive(Clone, Debug, Deserialize, PartialEq, Eq, Serialize)] pub struct VsockDeviceConfigInfo { /// ID of the vsock device. pub id: String, diff --git a/src/dragonball/src/resource_manager.rs b/src/dragonball/src/resource_manager.rs index 2cb32c0546..4565344826 100644 --- a/src/dragonball/src/resource_manager.rs +++ b/src/dragonball/src/resource_manager.rs @@ -36,7 +36,7 @@ const PIO_MAX: u16 = 0xFFFF; const MMIO_SPACE_RESERVED: u64 = 0x400_0000; /// Errors associated with resource management operations -#[derive(Debug, PartialEq, thiserror::Error)] +#[derive(Debug, PartialEq, Eq, thiserror::Error)] pub enum ResourceError { /// Unknown/unsupported resource type. #[error("unsupported resource type")] @@ -569,9 +569,7 @@ impl ResourceManager { Resource::KvmMemSlot(slot) => self.free_kvm_mem_slot(*slot), Resource::MacAddresss(_) => Ok(()), }; - if result.is_err() { - return result; - } + result?; } Ok(()) } @@ -588,9 +586,9 @@ mod tests { // Allocate/free shared IRQs multiple times. assert_eq!(mgr.allocate_legacy_irq(true, None).unwrap(), SHARED_IRQ); assert_eq!(mgr.allocate_legacy_irq(true, None).unwrap(), SHARED_IRQ); - mgr.free_legacy_irq(SHARED_IRQ); - mgr.free_legacy_irq(SHARED_IRQ); - mgr.free_legacy_irq(SHARED_IRQ); + mgr.free_legacy_irq(SHARED_IRQ).unwrap(); + mgr.free_legacy_irq(SHARED_IRQ).unwrap(); + mgr.free_legacy_irq(SHARED_IRQ).unwrap(); // Allocate specified IRQs. assert_eq!( @@ -598,7 +596,7 @@ mod tests { .unwrap(), LEGACY_IRQ_BASE + 10 ); - mgr.free_legacy_irq(LEGACY_IRQ_BASE + 10); + mgr.free_legacy_irq(LEGACY_IRQ_BASE + 10).unwrap(); assert_eq!( mgr.allocate_legacy_irq(false, Some(LEGACY_IRQ_BASE + 10)) .unwrap(), @@ -635,19 +633,19 @@ mod tests { let mgr = ResourceManager::new(None); let msi = mgr.allocate_msi_irq(3).unwrap(); - mgr.free_msi_irq(msi, 3); + mgr.free_msi_irq(msi, 3).unwrap(); let msi = mgr.allocate_msi_irq(3).unwrap(); - mgr.free_msi_irq(msi, 3); + mgr.free_msi_irq(msi, 3).unwrap(); let irq = mgr.allocate_msi_irq_aligned(8).unwrap(); assert_eq!(irq & 0x7, 0); - mgr.free_msi_irq(msi, 8); + mgr.free_msi_irq(msi, 8).unwrap(); let irq = mgr.allocate_msi_irq_aligned(8).unwrap(); assert_eq!(irq & 0x7, 0); let irq = mgr.allocate_msi_irq_aligned(512).unwrap(); assert_eq!(irq, 512); - mgr.free_msi_irq(irq, 512); + mgr.free_msi_irq(irq, 512).unwrap(); let irq = mgr.allocate_msi_irq_aligned(512).unwrap(); assert_eq!(irq, 512); @@ -690,9 +688,9 @@ mod tests { }, ]; let resources = mgr.allocate_device_resources(&requests, false).unwrap(); - mgr.free_device_resources(&resources); + mgr.free_device_resources(&resources).unwrap(); let resources = mgr.allocate_device_resources(&requests, false).unwrap(); - mgr.free_device_resources(&resources); + mgr.free_device_resources(&resources).unwrap(); requests.push(ResourceConstraint::PioAddress { range: Some((0xc000, 0xc000)), align: 0x1000, @@ -702,7 +700,7 @@ mod tests { let resources = mgr .allocate_device_resources(&requests[0..requests.len() - 1], false) .unwrap(); - mgr.free_device_resources(&resources); + mgr.free_device_resources(&resources).unwrap(); } #[test] @@ -721,7 +719,7 @@ mod tests { let mgr = ResourceManager::new(None); assert_eq!(mgr.allocate_kvm_mem_slot(1, None).unwrap(), 0); assert_eq!(mgr.allocate_kvm_mem_slot(1, Some(200)).unwrap(), 200); - mgr.free_kvm_mem_slot(200); + mgr.free_kvm_mem_slot(200).unwrap(); assert_eq!(mgr.allocate_kvm_mem_slot(1, Some(200)).unwrap(), 200); assert_eq!( mgr.allocate_kvm_mem_slot(1, Some(KVM_USER_MEM_SLOTS)) diff --git a/src/dragonball/src/vcpu/vcpu_impl.rs b/src/dragonball/src/vcpu/vcpu_impl.rs index ae5d404d1a..85f2888ced 100644 --- a/src/dragonball/src/vcpu/vcpu_impl.rs +++ b/src/dragonball/src/vcpu/vcpu_impl.rs @@ -533,16 +533,11 @@ impl Vcpu { fn check_io_port_info(&self, addr: u16, data: &[u8]) -> Result { let mut checked = false; - match addr { - // debug info signal - MAGIC_IOPORT_DEBUG_INFO => { - if data.len() == 4 { - let data = unsafe { std::ptr::read(data.as_ptr() as *const u32) }; - log::warn!("KDBG: guest kernel debug info: 0x{:x}", data); - checked = true; - } - } - _ => {} + // debug info signal + if addr == MAGIC_IOPORT_DEBUG_INFO && data.len() == 4 { + let data = unsafe { std::ptr::read(data.as_ptr() as *const u32) }; + log::warn!("KDBG: guest kernel debug info: 0x{:x}", data); + checked = true; }; Ok(checked) diff --git a/src/dragonball/src/vm/mod.rs b/src/dragonball/src/vm/mod.rs index 1d78ac31cb..39f5483e9c 100644 --- a/src/dragonball/src/vm/mod.rs +++ b/src/dragonball/src/vm/mod.rs @@ -67,7 +67,7 @@ pub enum VmError { } /// Configuration information for user defined NUMA nodes. -#[derive(Clone, Debug, Default, Serialize, Deserialize, PartialEq)] +#[derive(Clone, Debug, Default, Serialize, Deserialize, PartialEq, Eq)] pub struct NumaRegionInfo { /// memory size for this region (unit: MiB) pub size: u64, @@ -80,7 +80,7 @@ pub struct NumaRegionInfo { } /// Information for cpu topology to guide guest init -#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)] +#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq)] pub struct CpuTopology { /// threads per core to indicate hyperthreading is enabled or not pub threads_per_core: u8, @@ -104,7 +104,7 @@ impl Default for CpuTopology { } /// Configuration information for virtual machine instance. -#[derive(Clone, Debug, PartialEq)] +#[derive(Clone, Debug, PartialEq, Eq)] pub struct VmConfigInfo { /// Number of vcpu to start. pub vcpu_count: u8, From 002b18054d82e594a50c2bb0c0fd6fd837c370dd Mon Sep 17 00:00:00 2001 From: Chelsea Mafrica Date: Wed, 13 Jul 2022 00:52:36 -0700 Subject: [PATCH 09/42] kata-ctl: Add initial rust code for kata-ctl Use agent-ctl tool rust code as an example for a skeleton for the new kata-ctl tool. Signed-off-by: Chelsea Mafrica --- src/tools/kata-ctl/.gitignore | 1 + src/tools/kata-ctl/Cargo.lock | 122 ++++++++++++++++++++++++++++++ src/tools/kata-ctl/Cargo.toml | 14 ++++ src/tools/kata-ctl/Makefile | 33 ++++++++ src/tools/kata-ctl/README.md | 15 ++++ src/tools/kata-ctl/src/main.rs | 129 ++++++++++++++++++++++++++++++++ src/tools/kata-ctl/src/utils.rs | 8 ++ 7 files changed, 322 insertions(+) create mode 100644 src/tools/kata-ctl/.gitignore create mode 100644 src/tools/kata-ctl/Cargo.lock create mode 100644 src/tools/kata-ctl/Cargo.toml create mode 100644 src/tools/kata-ctl/Makefile create mode 100644 src/tools/kata-ctl/README.md create mode 100644 src/tools/kata-ctl/src/main.rs create mode 100644 src/tools/kata-ctl/src/utils.rs diff --git a/src/tools/kata-ctl/.gitignore b/src/tools/kata-ctl/.gitignore new file mode 100644 index 0000000000..57872d0f1e --- /dev/null +++ b/src/tools/kata-ctl/.gitignore @@ -0,0 +1 @@ +/vendor/ diff --git a/src/tools/kata-ctl/Cargo.lock b/src/tools/kata-ctl/Cargo.lock new file mode 100644 index 0000000000..84da4ddc66 --- /dev/null +++ b/src/tools/kata-ctl/Cargo.lock @@ -0,0 +1,122 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "ansi_term" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d52a9bb7ec0cf484c551830a7ce27bd20d67eac647e1befb56b0be4ee39a55d2" +dependencies = [ + "winapi", +] + +[[package]] +name = "anyhow" +version = "1.0.58" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bb07d2053ccdbe10e2af2995a2f116c1330396493dc1269f6a91d0ae82e19704" + +[[package]] +name = "atty" +version = "0.2.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8" +dependencies = [ + "hermit-abi", + "libc", + "winapi", +] + +[[package]] +name = "bitflags" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" + +[[package]] +name = "clap" +version = "2.34.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a0610544180c38b88101fecf2dd634b174a62eef6946f84dfc6a7127512b381c" +dependencies = [ + "ansi_term", + "atty", + "bitflags", + "strsim", + "textwrap", + "unicode-width", + "vec_map", +] + +[[package]] +name = "hermit-abi" +version = "0.1.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33" +dependencies = [ + "libc", +] + +[[package]] +name = "kata-ctl" +version = "0.0.0" +dependencies = [ + "anyhow", + "clap", +] + +[[package]] +name = "libc" +version = "0.2.126" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "349d5a591cd28b49e1d1037471617a32ddcda5731b99419008085f72d5a53836" + +[[package]] +name = "strsim" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a" + +[[package]] +name = "textwrap" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060" +dependencies = [ + "unicode-width", +] + +[[package]] +name = "unicode-width" +version = "0.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3ed742d4ea2bd1176e236172c8429aaf54486e7ac098db29ffe6529e0ce50973" + +[[package]] +name = "vec_map" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f1bddf1187be692e79c5ffeab891132dfb0f236ed36a43c7ed39f1165ee20191" + +[[package]] +name = "winapi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" +dependencies = [ + "winapi-i686-pc-windows-gnu", + "winapi-x86_64-pc-windows-gnu", +] + +[[package]] +name = "winapi-i686-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" + +[[package]] +name = "winapi-x86_64-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" diff --git a/src/tools/kata-ctl/Cargo.toml b/src/tools/kata-ctl/Cargo.toml new file mode 100644 index 0000000000..c3ec304ac0 --- /dev/null +++ b/src/tools/kata-ctl/Cargo.toml @@ -0,0 +1,14 @@ +# Copyright (c) 2022 Intel Corporation +# +# SPDX-License-Identifier: Apache-2.0 +# + +[package] +name = "kata-ctl" +version = "0.0.0" +authors = ["The Kata Containers community "] +edition = "2021" + +[dependencies] +clap = "2.33.0" +anyhow = "1.0.31" diff --git a/src/tools/kata-ctl/Makefile b/src/tools/kata-ctl/Makefile new file mode 100644 index 0000000000..c050d6d477 --- /dev/null +++ b/src/tools/kata-ctl/Makefile @@ -0,0 +1,33 @@ +# Copyright (c) 2022 Intel Corporation +# +# SPDX-License-Identifier: Apache-2.0 +# + +include ../../../utils.mk + +.DEFAULT_GOAL := default +default: build + +build: + @RUSTFLAGS="$(EXTRA_RUSTFLAGS) --deny warnings" cargo build --target $(TRIPLE) --$(BUILD_TYPE) + +clean: + cargo clean + +vendor: + cargo vendor + +test: + +install: + @RUSTFLAGS="$(EXTRA_RUSTFLAGS) --deny warnings" cargo install --target $(TRIPLE) --path . + +check: standard_rust_check + +.PHONY: \ + build \ + check \ + clean \ + install \ + test \ + vendor diff --git a/src/tools/kata-ctl/README.md b/src/tools/kata-ctl/README.md new file mode 100644 index 0000000000..1e441d58b2 --- /dev/null +++ b/src/tools/kata-ctl/README.md @@ -0,0 +1,15 @@ +# Kata Containers control tool + +## Overview + +## Audience and environment + +## History + +## Full details + +## Code summary + +## Run the tool + +### Prerequisites diff --git a/src/tools/kata-ctl/src/main.rs b/src/tools/kata-ctl/src/main.rs new file mode 100644 index 0000000000..9b3c0bf2e7 --- /dev/null +++ b/src/tools/kata-ctl/src/main.rs @@ -0,0 +1,129 @@ +// Copyright (c) 2022 Intel Corporation +// +// SPDX-License-Identifier: Apache-2.0 +// + +use anyhow::{anyhow, Result}; +use clap::{crate_name, crate_version, App, Arg, SubCommand}; +use std::process::exit; + +mod utils; + +const DESCRIPTION_TEXT: &str = r#"DESCRIPTION: + kata-ctl description placeholder."#; + +const ABOUT_TEXT: &str = "Kata Containers control tool"; + +fn real_main() -> Result<()> { + let name = crate_name!(); + + let app = App::new(name) + .version(crate_version!()) + .about(ABOUT_TEXT) + .long_about(DESCRIPTION_TEXT) + .subcommand( + SubCommand::with_name("check") + .about("tests if system can run Kata Containers") + ) + .subcommand( + SubCommand::with_name("command-example") + .about("(remove when other subcommands have sufficient detail)") + .arg( + Arg::with_name("arg-example-1") + .long("arg-example-1") + .help("arg example for command-example") + .takes_value(true) + ) + ) + .subcommand( + SubCommand::with_name("direct-volume") + .about("directly assign a volume to Kata Containers to manage") + ) + .subcommand( + SubCommand::with_name("env") + .about("display settings. Default to TOML") + ) + .subcommand( + SubCommand::with_name("exec") + .about("enter into guest by debug console") + ) + .subcommand( + SubCommand::with_name("factory") + .about("manage vm factory") + ) + .subcommand( + SubCommand::with_name("help") + .about("shows a list of commands or help for one command") + ) + .subcommand( + SubCommand::with_name("iptables") + .about("") + ) + .subcommand( + SubCommand::with_name("metrics") + .about("gather metrics associated with infrastructure used to run a sandbox") + ) + .subcommand( + SubCommand::with_name("version") + .about("display version details") + + ); + + let args = app.get_matches(); + + let subcmd = args + .subcommand_name() + .ok_or_else(|| anyhow!("need sub-command"))?; + + match subcmd { + "command-example" => { + println!("{}", utils::command_example(args)); + Ok(()) + } + "check" => { + println!("Not implemented"); + Ok(()) + } + "direct-volume" => { + println!("Not implemented"); + Ok(()) + } + "env" => { + println!("Not implemented"); + Ok(()) + } + "exec" => { + println!("Not implemented"); + Ok(()) + } + "factory" => { + println!("Not implemented"); + Ok(()) + } + "help" => { + println!("Not implemented"); + Ok(()) + } + "iptables" => { + println!("Not implemented"); + Ok(()) + } + "metrics" => { + println!("Not implemented"); + Ok(()) + } + "version" => { + println!("Not implemented"); + Ok(()) + } + _ => return Err(anyhow!(format!("invalid sub-command: {:?}", subcmd))), + } + +} + +fn main() { + if let Err(e) = real_main() { + eprintln!("ERROR: {:#?}", e); + exit(1); + } +} diff --git a/src/tools/kata-ctl/src/utils.rs b/src/tools/kata-ctl/src/utils.rs new file mode 100644 index 0000000000..b779c2147b --- /dev/null +++ b/src/tools/kata-ctl/src/utils.rs @@ -0,0 +1,8 @@ +// Copyright (c) 2022 Intel Corporation +// +// SPDX-License-Identifier: Apache-2.0 +// + +pub fn command_example(_global_args: clap::ArgMatches) -> String { + "test utils command".to_string() +} From d0b33e9a32cddee11b14f06b09af651189148ad3 Mon Sep 17 00:00:00 2001 From: David Esparza Date: Wed, 20 Jul 2022 19:26:32 -0500 Subject: [PATCH 10/42] versions: Add kata-ctl version entry As we're switching to using the rust version of the kata-ctl, lets provide with its own entry in the kata-ctl command line. Signed-off-by: David Esparza Commit-edited-by: James O. D. Hunt --- src/tools/kata-ctl/Cargo.toml | 2 +- src/tools/kata-ctl/Makefile | 36 +++++++++++++++++++++++++--- src/tools/kata-ctl/VERSION | 1 + src/tools/kata-ctl/src/main.rs | 10 +++++--- src/tools/kata-ctl/src/version.rs.in | 16 +++++++++++++ 5 files changed, 58 insertions(+), 7 deletions(-) create mode 120000 src/tools/kata-ctl/VERSION create mode 100644 src/tools/kata-ctl/src/version.rs.in diff --git a/src/tools/kata-ctl/Cargo.toml b/src/tools/kata-ctl/Cargo.toml index c3ec304ac0..582ae631b7 100644 --- a/src/tools/kata-ctl/Cargo.toml +++ b/src/tools/kata-ctl/Cargo.toml @@ -5,7 +5,7 @@ [package] name = "kata-ctl" -version = "0.0.0" +version = "0.0.1" authors = ["The Kata Containers community "] edition = "2021" diff --git a/src/tools/kata-ctl/Makefile b/src/tools/kata-ctl/Makefile index c050d6d477..899c891a6a 100644 --- a/src/tools/kata-ctl/Makefile +++ b/src/tools/kata-ctl/Makefile @@ -5,14 +5,44 @@ include ../../../utils.mk +PROJECT_NAME = Kata Containers +PROJECT_URL = https://github.com/kata-containers +PROJECT_COMPONENT = kata-ctl + +TARGET = $(PROJECT_COMPONENT) + +VERSION_FILE := ./VERSION +VERSION := $(shell grep -v ^\# $(VERSION_FILE)) +COMMIT_NO := $(shell git rev-parse HEAD 2>/dev/null || true) +COMMIT_NO_SHORT := $(shell git rev-parse --short HEAD 2>/dev/null || true) +COMMIT := $(if $(shell git status --porcelain --untracked-files=no 2>/dev/null || true),${COMMIT_NO}-dirty,${COMMIT_NO}) + +# Exported to allow cargo to see it +export KATA_CTL_VERSION := $(if $(COMMIT),$(VERSION)-$(COMMIT),$(VERSION)) + +GENERATED_CODE = src/version.rs + +GENERATED_REPLACEMENTS= \ + KATA_CTL_VERSION + +GENERATED_FILES := $(GENERATED_CODE) + .DEFAULT_GOAL := default -default: build + +default: $(TARGET) build + +$(TARGET): $(GENERATED_CODE) build: - @RUSTFLAGS="$(EXTRA_RUSTFLAGS) --deny warnings" cargo build --target $(TRIPLE) --$(BUILD_TYPE) + @RUSTFLAGS="$(EXTRA_RUSTFLAGS) --deny warnings" cargo build --target $(TRIPLE) $(if $(findstring release,$(BUILD_TYPE)),--release) $(EXTRA_RUSTFEATURES) + +$(GENERATED_FILES): %: %.in + @sed $(foreach r,$(GENERATED_REPLACEMENTS),-e 's|@$r@|$($r)|g') "$<" > "$@" + clean: - cargo clean + @cargo clean + @rm -f $(GENERATED_FILES) vendor: cargo vendor diff --git a/src/tools/kata-ctl/VERSION b/src/tools/kata-ctl/VERSION new file mode 120000 index 0000000000..d62dc733ef --- /dev/null +++ b/src/tools/kata-ctl/VERSION @@ -0,0 +1 @@ +../../../VERSION \ No newline at end of file diff --git a/src/tools/kata-ctl/src/main.rs b/src/tools/kata-ctl/src/main.rs index 9b3c0bf2e7..7368c667e5 100644 --- a/src/tools/kata-ctl/src/main.rs +++ b/src/tools/kata-ctl/src/main.rs @@ -4,21 +4,25 @@ // use anyhow::{anyhow, Result}; -use clap::{crate_name, crate_version, App, Arg, SubCommand}; +use clap::{crate_name, App, Arg, SubCommand}; use std::process::exit; mod utils; +mod version; const DESCRIPTION_TEXT: &str = r#"DESCRIPTION: kata-ctl description placeholder."#; const ABOUT_TEXT: &str = "Kata Containers control tool"; +const NAME: &str = "kata-ctl"; + fn real_main() -> Result<()> { let name = crate_name!(); + let version = version::get(); let app = App::new(name) - .version(crate_version!()) + .version(&*version) .about(ABOUT_TEXT) .long_about(DESCRIPTION_TEXT) .subcommand( @@ -113,7 +117,7 @@ fn real_main() -> Result<()> { Ok(()) } "version" => { - println!("Not implemented"); + println!("{} version {} (type: rust)", NAME, version); Ok(()) } _ => return Err(anyhow!(format!("invalid sub-command: {:?}", subcmd))), diff --git a/src/tools/kata-ctl/src/version.rs.in b/src/tools/kata-ctl/src/version.rs.in new file mode 100644 index 0000000000..77b79d035f --- /dev/null +++ b/src/tools/kata-ctl/src/version.rs.in @@ -0,0 +1,16 @@ +// Copyright (c) 2020 Intel Corporation +// +// SPDX-License-Identifier: Apache-2.0 +// + +// +// WARNING: This file is auto-generated - DO NOT EDIT! +// + +use clap::crate_version; + +const KATA_CTL_VERSION: &str = "@KATA_CTL_VERSION@"; + +pub fn get() -> String { + format!("{}-{}", KATA_CTL_VERSION, crate_version!()) +} From 303fc8b1183594585eb5ff37786b2de2acd41b95 Mon Sep 17 00:00:00 2001 From: David Esparza Date: Wed, 27 Jul 2022 11:31:23 -0500 Subject: [PATCH 11/42] kata-ctl: Add unit tests cases Add more unit tests cases to --version argument. Signed-off-by: David Esparza Commit-edited-by: James O. D. Hunt --- src/tools/kata-ctl/Cargo.lock | 122 --------------------------- src/tools/kata-ctl/Cargo.toml | 5 +- src/tools/kata-ctl/Makefile | 1 + src/tools/kata-ctl/src/version.rs.in | 19 ++++- 4 files changed, 23 insertions(+), 124 deletions(-) delete mode 100644 src/tools/kata-ctl/Cargo.lock diff --git a/src/tools/kata-ctl/Cargo.lock b/src/tools/kata-ctl/Cargo.lock deleted file mode 100644 index 84da4ddc66..0000000000 --- a/src/tools/kata-ctl/Cargo.lock +++ /dev/null @@ -1,122 +0,0 @@ -# This file is automatically @generated by Cargo. -# It is not intended for manual editing. -version = 3 - -[[package]] -name = "ansi_term" -version = "0.12.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d52a9bb7ec0cf484c551830a7ce27bd20d67eac647e1befb56b0be4ee39a55d2" -dependencies = [ - "winapi", -] - -[[package]] -name = "anyhow" -version = "1.0.58" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bb07d2053ccdbe10e2af2995a2f116c1330396493dc1269f6a91d0ae82e19704" - -[[package]] -name = "atty" -version = "0.2.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8" -dependencies = [ - "hermit-abi", - "libc", - "winapi", -] - -[[package]] -name = "bitflags" -version = "1.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" - -[[package]] -name = "clap" -version = "2.34.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a0610544180c38b88101fecf2dd634b174a62eef6946f84dfc6a7127512b381c" -dependencies = [ - "ansi_term", - "atty", - "bitflags", - "strsim", - "textwrap", - "unicode-width", - "vec_map", -] - -[[package]] -name = "hermit-abi" -version = "0.1.19" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33" -dependencies = [ - "libc", -] - -[[package]] -name = "kata-ctl" -version = "0.0.0" -dependencies = [ - "anyhow", - "clap", -] - -[[package]] -name = "libc" -version = "0.2.126" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "349d5a591cd28b49e1d1037471617a32ddcda5731b99419008085f72d5a53836" - -[[package]] -name = "strsim" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a" - -[[package]] -name = "textwrap" -version = "0.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060" -dependencies = [ - "unicode-width", -] - -[[package]] -name = "unicode-width" -version = "0.1.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3ed742d4ea2bd1176e236172c8429aaf54486e7ac098db29ffe6529e0ce50973" - -[[package]] -name = "vec_map" -version = "0.8.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1bddf1187be692e79c5ffeab891132dfb0f236ed36a43c7ed39f1165ee20191" - -[[package]] -name = "winapi" -version = "0.3.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" -dependencies = [ - "winapi-i686-pc-windows-gnu", - "winapi-x86_64-pc-windows-gnu", -] - -[[package]] -name = "winapi-i686-pc-windows-gnu" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" - -[[package]] -name = "winapi-x86_64-pc-windows-gnu" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" diff --git a/src/tools/kata-ctl/Cargo.toml b/src/tools/kata-ctl/Cargo.toml index 582ae631b7..303335cbaa 100644 --- a/src/tools/kata-ctl/Cargo.toml +++ b/src/tools/kata-ctl/Cargo.toml @@ -10,5 +10,8 @@ authors = ["The Kata Containers community "] edition = "2021" [dependencies] -clap = "2.33.0" anyhow = "1.0.31" +clap = "2.33.0" + +[dev-dependencies] +semver = "1.0.12" diff --git a/src/tools/kata-ctl/Makefile b/src/tools/kata-ctl/Makefile index 899c891a6a..23d16e385a 100644 --- a/src/tools/kata-ctl/Makefile +++ b/src/tools/kata-ctl/Makefile @@ -48,6 +48,7 @@ vendor: cargo vendor test: + @RUSTFLAGS="$(EXTRA_RUSTFLAGS) --deny warnings" cargo test --target $(TRIPLE) $(if $(findstring release,$(BUILD_TYPE)),--release) $(EXTRA_RUSTFEATURES) install: @RUSTFLAGS="$(EXTRA_RUSTFLAGS) --deny warnings" cargo install --target $(TRIPLE) --path . diff --git a/src/tools/kata-ctl/src/version.rs.in b/src/tools/kata-ctl/src/version.rs.in index 77b79d035f..b17824a1c7 100644 --- a/src/tools/kata-ctl/src/version.rs.in +++ b/src/tools/kata-ctl/src/version.rs.in @@ -1,4 +1,4 @@ -// Copyright (c) 2020 Intel Corporation +// Copyright (c) 2022 Intel Corporation // // SPDX-License-Identifier: Apache-2.0 // @@ -14,3 +14,20 @@ const KATA_CTL_VERSION: &str = "@KATA_CTL_VERSION@"; pub fn get() -> String { format!("{}-{}", KATA_CTL_VERSION, crate_version!()) } + +#[cfg(test)] +mod tests { + use super::*; + use semver::{Version}; + + #[test] + fn test_get() { + let version = get(); + let v = Version::parse(&version).unwrap(); + + assert!(!v.major.to_string().is_empty()); + assert!(!v.minor.to_string().is_empty()); + assert!(!v.patch.to_string().is_empty()); + assert!(!v.pre.to_string().is_empty()); + } +} From 8e7bb8521c3516aff7ff5be5f279a5e00e8734e1 Mon Sep 17 00:00:00 2001 From: Chelsea Mafrica Date: Wed, 17 Aug 2022 02:56:28 -0700 Subject: [PATCH 12/42] kata-ctl: add code for framework for arch Add framework for different architectures for check. In the existing kata-runtime check, the network checks do not appear to be architecture-specific while the kernel module, cpu, and kvm checks do have separate implementations for different architectures. Signed-off-by: Chelsea Mafrica --- src/tools/kata-ctl/src/arch/aarch64/mod.rs | 15 +++++ src/tools/kata-ctl/src/arch/mod.rs | 42 ++++++++++++++ .../kata-ctl/src/arch/powerpc64le/mod.rs | 15 +++++ src/tools/kata-ctl/src/arch/s390x/mod.rs | 15 +++++ src/tools/kata-ctl/src/arch/x86_64/mod.rs | 17 ++++++ src/tools/kata-ctl/src/check.rs | 12 ++++ src/tools/kata-ctl/src/main.rs | 56 ++++++++++++------- src/tools/kata-ctl/src/utils.rs | 4 -- 8 files changed, 152 insertions(+), 24 deletions(-) create mode 100644 src/tools/kata-ctl/src/arch/aarch64/mod.rs create mode 100644 src/tools/kata-ctl/src/arch/mod.rs create mode 100644 src/tools/kata-ctl/src/arch/powerpc64le/mod.rs create mode 100644 src/tools/kata-ctl/src/arch/s390x/mod.rs create mode 100644 src/tools/kata-ctl/src/arch/x86_64/mod.rs create mode 100644 src/tools/kata-ctl/src/check.rs diff --git a/src/tools/kata-ctl/src/arch/aarch64/mod.rs b/src/tools/kata-ctl/src/arch/aarch64/mod.rs new file mode 100644 index 0000000000..6df39ce748 --- /dev/null +++ b/src/tools/kata-ctl/src/arch/aarch64/mod.rs @@ -0,0 +1,15 @@ +// Copyright (c) 2022 Intel Corporation +// +// SPDX-License-Identifier: Apache-2.0 +// + +#[cfg(target_arch = "aarch64")] +pub use arch_specific::*; + +mod arch_specific { + use anyhow::Result; + + pub fn check() -> Result<()> { + unimplemented!("Check not implemented in aarch64") + } +} diff --git a/src/tools/kata-ctl/src/arch/mod.rs b/src/tools/kata-ctl/src/arch/mod.rs new file mode 100644 index 0000000000..ee6f926f75 --- /dev/null +++ b/src/tools/kata-ctl/src/arch/mod.rs @@ -0,0 +1,42 @@ +// Copyright (c) 2022 Intel Corporation +// +// SPDX-License-Identifier: Apache-2.0 +// + +use anyhow::{Result}; + +#[cfg(target_arch = "aarch64")] +pub mod aarch64; + +#[cfg(target_arch = "powerpc64le")] +pub mod powerpc64le; + +#[cfg(target_arch = "s390x")] +pub mod s390x; + +#[cfg(target_arch = "x86_64")] +pub mod x86_64; + +pub fn check(global_args: clap::ArgMatches) -> Result<()> { + #[cfg(target_arch = "aarch64")] + let result = aarch64::check(); + + #[cfg(target_arch = "powerpc64le")] + let result = powerpc64le::check(); + + #[cfg(target_arch = "s390x")] + let result = s390x::check(); + + #[cfg(target_arch = "x86_64")] + let result = x86_64::check(global_args); + + #[cfg(not(any( + target_arch = "aarch64", + target_arch = "powerpc64le", + target_arch = "s390x", + target_arch = "x86_64" + )))] + panic!("unknown architecture"); + + result +} diff --git a/src/tools/kata-ctl/src/arch/powerpc64le/mod.rs b/src/tools/kata-ctl/src/arch/powerpc64le/mod.rs new file mode 100644 index 0000000000..a87ab02f8c --- /dev/null +++ b/src/tools/kata-ctl/src/arch/powerpc64le/mod.rs @@ -0,0 +1,15 @@ +// Copyright (c) 2022 Intel Corporation +// +// SPDX-License-Identifier: Apache-2.0 +// + +#[cfg(target_arch = "powerpc64le")] +pub use arch_specific::*; + +mod arch_specific { + use anyhow::Result; + + 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 new file mode 100644 index 0000000000..7f6a424c3b --- /dev/null +++ b/src/tools/kata-ctl/src/arch/s390x/mod.rs @@ -0,0 +1,15 @@ +// Copyright (c) 2022 Intel Corporation +// +// SPDX-License-Identifier: Apache-2.0 +// + +#[cfg(target_arch = "s390x")] +pub use arch_specific::*; + +mod arch_specific { + use anyhow::Result; + + pub fn check() -> Result<()> { + unimplemented!("Check not implemented in s390x"); + } +} diff --git a/src/tools/kata-ctl/src/arch/x86_64/mod.rs b/src/tools/kata-ctl/src/arch/x86_64/mod.rs new file mode 100644 index 0000000000..2f27dc2a44 --- /dev/null +++ b/src/tools/kata-ctl/src/arch/x86_64/mod.rs @@ -0,0 +1,17 @@ +// Copyright (c) 2022 Intel Corporation +// +// SPDX-License-Identifier: Apache-2.0 +// + +#[cfg(target_arch = "x86_64")] +pub use arch_specific::*; + +mod arch_specific { + use anyhow::Result; + + pub fn check(_global_args: clap::ArgMatches) -> Result<()> { + println!("INFO: check: x86_64"); + + Ok(()) + } +} diff --git a/src/tools/kata-ctl/src/check.rs b/src/tools/kata-ctl/src/check.rs new file mode 100644 index 0000000000..be39e31e06 --- /dev/null +++ b/src/tools/kata-ctl/src/check.rs @@ -0,0 +1,12 @@ +// Copyright (c) 2022 Intel Corporation +// +// SPDX-License-Identifier: Apache-2.0 +// + +// Contains checks that are not architecture-specific + +use anyhow::{Result}; + +pub fn run_network_checks() -> Result<()> { + unimplemented!("Tests using network checks not implemented"); +} diff --git a/src/tools/kata-ctl/src/main.rs b/src/tools/kata-ctl/src/main.rs index 7368c667e5..9338b4bd61 100644 --- a/src/tools/kata-ctl/src/main.rs +++ b/src/tools/kata-ctl/src/main.rs @@ -9,6 +9,8 @@ use std::process::exit; mod utils; mod version; +mod arch; +mod check; const DESCRIPTION_TEXT: &str = r#"DESCRIPTION: kata-ctl description placeholder."#; @@ -17,6 +19,25 @@ const ABOUT_TEXT: &str = "Kata Containers control tool"; const NAME: &str = "kata-ctl"; +fn run_checks(global_args: clap::ArgMatches) -> Result<()> { + let args = global_args + .subcommand_matches("check") + .ok_or_else(|| anyhow!("BUG: missing sub-command arguments"))?; + + let no_network_check = args.is_present("no-network-checks"); + + // run architecture-agnostic tests + if !no_network_check { + // run code that uses network checks + let _network_checks = check::run_network_checks(); + } + + // run architecture-specific tests + let _all_checks = arch::check(global_args); + + Ok(()) +} + fn real_main() -> Result<()> { let name = crate_name!(); let version = version::get(); @@ -28,15 +49,11 @@ fn real_main() -> Result<()> { .subcommand( SubCommand::with_name("check") .about("tests if system can run Kata Containers") - ) - .subcommand( - SubCommand::with_name("command-example") - .about("(remove when other subcommands have sufficient detail)") .arg( - Arg::with_name("arg-example-1") - .long("arg-example-1") - .help("arg example for command-example") - .takes_value(true) + Arg::with_name("no-network-checks") + .long("no-network-checks") + .help("run check with no network checks") + .takes_value(false) ) ) .subcommand( @@ -80,40 +97,39 @@ fn real_main() -> Result<()> { .ok_or_else(|| anyhow!("need sub-command"))?; match subcmd { - "command-example" => { - println!("{}", utils::command_example(args)); - Ok(()) - } "check" => { - println!("Not implemented"); + match run_checks(args) { + Ok(_result) => println!("check may not be fully implemented"), + Err(err) => println!("{}", err), + } Ok(()) } "direct-volume" => { - println!("Not implemented"); + unimplemented!("Not implemented"); Ok(()) } "env" => { - println!("Not implemented"); + unimplemented!("Not implemented"); Ok(()) } "exec" => { - println!("Not implemented"); + unimplemented!("Not implemented"); Ok(()) } "factory" => { - println!("Not implemented"); + unimplemented!("Not implemented"); Ok(()) } "help" => { - println!("Not implemented"); + unimplemented!("Not implemented"); Ok(()) } "iptables" => { - println!("Not implemented"); + unimplemented!("Not implemented"); Ok(()) } "metrics" => { - println!("Not implemented"); + unimplemented!("Not implemented"); Ok(()) } "version" => { diff --git a/src/tools/kata-ctl/src/utils.rs b/src/tools/kata-ctl/src/utils.rs index b779c2147b..59289ad4a9 100644 --- a/src/tools/kata-ctl/src/utils.rs +++ b/src/tools/kata-ctl/src/utils.rs @@ -2,7 +2,3 @@ // // SPDX-License-Identifier: Apache-2.0 // - -pub fn command_example(_global_args: clap::ArgMatches) -> String { - "test utils command".to_string() -} From cca7e32b54ec88938b9a1694e0a718b9eb1dafcd Mon Sep 17 00:00:00 2001 From: "James O. D. Hunt" Date: Wed, 17 Aug 2022 18:04:20 +0100 Subject: [PATCH 13/42] kata-ctl: Lint fixes to allow the branch to be built Remove return value for branches that call `unimplemented!()`. Signed-off-by: James O. D. Hunt --- src/tools/kata-ctl/src/main.rs | 7 ------- 1 file changed, 7 deletions(-) diff --git a/src/tools/kata-ctl/src/main.rs b/src/tools/kata-ctl/src/main.rs index 9338b4bd61..17875bb0be 100644 --- a/src/tools/kata-ctl/src/main.rs +++ b/src/tools/kata-ctl/src/main.rs @@ -106,31 +106,24 @@ fn real_main() -> Result<()> { } "direct-volume" => { unimplemented!("Not implemented"); - Ok(()) } "env" => { unimplemented!("Not implemented"); - Ok(()) } "exec" => { unimplemented!("Not implemented"); - Ok(()) } "factory" => { unimplemented!("Not implemented"); - Ok(()) } "help" => { unimplemented!("Not implemented"); - Ok(()) } "iptables" => { unimplemented!("Not implemented"); - Ok(()) } "metrics" => { unimplemented!("Not implemented"); - Ok(()) } "version" => { println!("{} version {} (type: rust)", NAME, version); From b63ba66dc347377e5d4e2376f13349128b986c2d Mon Sep 17 00:00:00 2001 From: "James O. D. Hunt" Date: Wed, 17 Aug 2022 18:05:16 +0100 Subject: [PATCH 14/42] kata-ctl: Formatting tweaks Automatic format updates. Signed-off-by: James O. D. Hunt --- src/tools/kata-ctl/src/main.rs | 52 +++++++++++----------------------- 1 file changed, 17 insertions(+), 35 deletions(-) diff --git a/src/tools/kata-ctl/src/main.rs b/src/tools/kata-ctl/src/main.rs index 17875bb0be..484c78a8aa 100644 --- a/src/tools/kata-ctl/src/main.rs +++ b/src/tools/kata-ctl/src/main.rs @@ -7,10 +7,10 @@ use anyhow::{anyhow, Result}; use clap::{crate_name, App, Arg, SubCommand}; use std::process::exit; -mod utils; -mod version; mod arch; mod check; +mod utils; +mod version; const DESCRIPTION_TEXT: &str = r#"DESCRIPTION: kata-ctl description placeholder."#; @@ -48,47 +48,30 @@ fn real_main() -> Result<()> { .long_about(DESCRIPTION_TEXT) .subcommand( SubCommand::with_name("check") - .about("tests if system can run Kata Containers") - .arg( - Arg::with_name("no-network-checks") - .long("no-network-checks") - .help("run check with no network checks") - .takes_value(false) - ) + .about("tests if system can run Kata Containers") + .arg( + Arg::with_name("no-network-checks") + .long("no-network-checks") + .help("run check with no network checks") + .takes_value(false), + ), ) .subcommand( SubCommand::with_name("direct-volume") - .about("directly assign a volume to Kata Containers to manage") + .about("directly assign a volume to Kata Containers to manage"), ) + .subcommand(SubCommand::with_name("env").about("display settings. Default to TOML")) + .subcommand(SubCommand::with_name("exec").about("enter into guest by debug console")) + .subcommand(SubCommand::with_name("factory").about("manage vm factory")) .subcommand( - SubCommand::with_name("env") - .about("display settings. Default to TOML") - ) - .subcommand( - SubCommand::with_name("exec") - .about("enter into guest by debug console") - ) - .subcommand( - SubCommand::with_name("factory") - .about("manage vm factory") - ) - .subcommand( - SubCommand::with_name("help") - .about("shows a list of commands or help for one command") - ) - .subcommand( - SubCommand::with_name("iptables") - .about("") + SubCommand::with_name("help").about("shows a list of commands or help for one command"), ) + .subcommand(SubCommand::with_name("iptables").about("")) .subcommand( SubCommand::with_name("metrics") - .about("gather metrics associated with infrastructure used to run a sandbox") + .about("gather metrics associated with infrastructure used to run a sandbox"), ) - .subcommand( - SubCommand::with_name("version") - .about("display version details") - - ); + .subcommand(SubCommand::with_name("version").about("display version details")); let args = app.get_matches(); @@ -131,7 +114,6 @@ fn real_main() -> Result<()> { } _ => return Err(anyhow!(format!("invalid sub-command: {:?}", subcmd))), } - } fn main() { From 7c9f9a5a1dae3f9c2c16748b6d5af9fc134abe65 Mon Sep 17 00:00:00 2001 From: "James O. D. Hunt" Date: Wed, 17 Aug 2022 18:06:29 +0100 Subject: [PATCH 15/42] kata-ctl: Make arch test run at compile time Changed the `panic!()` call to a `compile_error!()` one to ensure it fires at compile time rather than runtime. Signed-off-by: James O. D. Hunt --- src/tools/kata-ctl/src/arch/mod.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/tools/kata-ctl/src/arch/mod.rs b/src/tools/kata-ctl/src/arch/mod.rs index ee6f926f75..c18fb0c094 100644 --- a/src/tools/kata-ctl/src/arch/mod.rs +++ b/src/tools/kata-ctl/src/arch/mod.rs @@ -3,7 +3,7 @@ // SPDX-License-Identifier: Apache-2.0 // -use anyhow::{Result}; +use anyhow::Result; #[cfg(target_arch = "aarch64")] pub mod aarch64; @@ -36,7 +36,7 @@ pub fn check(global_args: clap::ArgMatches) -> Result<()> { target_arch = "s390x", target_arch = "x86_64" )))] - panic!("unknown architecture"); + compile_error!("unknown architecture"); result } From 018aa899cb81c8e041454c200ada22ffced63245 Mon Sep 17 00:00:00 2001 From: Chelsea Mafrica Date: Wed, 24 Aug 2022 08:25:22 -0700 Subject: [PATCH 16/42] 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 --- src/tools/kata-ctl/src/arch/x86_64/mod.rs | 38 +++++++- src/tools/kata-ctl/src/check.rs | 103 +++++++++++++++++++++- 2 files changed, 139 insertions(+), 2 deletions(-) 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 2f27dc2a44..5618a44512 100644 --- a/src/tools/kata-ctl/src/arch/x86_64/mod.rs +++ b/src/tools/kata-ctl/src/arch/x86_64/mod.rs @@ -7,11 +7,47 @@ pub use 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<()> { 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/check.rs b/src/tools/kata-ctl/src/check.rs index be39e31e06..9317b903a1 100644 --- a/src/tools/kata-ctl/src/check.rs +++ b/src/tools/kata-ctl/src/check.rs @@ -5,8 +5,109 @@ // 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 { + 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 { + 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 { + 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> { + let data_vec: Vec <&str> = data.split_whitespace().collect(); + + let mut missing: Vec = 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> { + 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> { + 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<()> { 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); + } +} + From eb5423cb7fd2b1d0655f5b58427834e5c6a322f7 Mon Sep 17 00:00:00 2001 From: David Esparza Date: Wed, 14 Sep 2022 07:32:21 -0500 Subject: [PATCH 17/42] kata-ctl: switch to use clap derive for CLI handling Switch from the functional version of `clap` to the declarative methodology. Signed-off-by: David Esparza Commit-edited-by: James O. D. Hunt --- src/tools/kata-ctl/Cargo.toml | 3 +- src/tools/kata-ctl/Makefile | 2 +- src/tools/kata-ctl/src/arch/mod.rs | 4 +- src/tools/kata-ctl/src/arch/x86_64/mod.rs | 2 +- src/tools/kata-ctl/src/args.rs | 90 ++++++++++++ src/tools/kata-ctl/src/check.rs | 7 +- src/tools/kata-ctl/src/main.rs | 130 ++++-------------- src/tools/kata-ctl/src/{utils.rs => ops.rs} | 3 + src/tools/kata-ctl/src/ops/check_ops.rs | 75 ++++++++++ .../kata-ctl/src/{ => ops}/version.rs.in | 10 +- 10 files changed, 216 insertions(+), 110 deletions(-) create mode 100644 src/tools/kata-ctl/src/args.rs rename src/tools/kata-ctl/src/{utils.rs => ops.rs} (69%) create mode 100644 src/tools/kata-ctl/src/ops/check_ops.rs rename src/tools/kata-ctl/src/{ => ops}/version.rs.in (65%) diff --git a/src/tools/kata-ctl/Cargo.toml b/src/tools/kata-ctl/Cargo.toml index 303335cbaa..eef1f5fbb9 100644 --- a/src/tools/kata-ctl/Cargo.toml +++ b/src/tools/kata-ctl/Cargo.toml @@ -11,7 +11,8 @@ edition = "2021" [dependencies] anyhow = "1.0.31" -clap = "2.33.0" +clap = { version = "3.2.20", features = ["derive", "cargo"] } +thiserror = "1.0.35" [dev-dependencies] semver = "1.0.12" diff --git a/src/tools/kata-ctl/Makefile b/src/tools/kata-ctl/Makefile index 23d16e385a..e11af38457 100644 --- a/src/tools/kata-ctl/Makefile +++ b/src/tools/kata-ctl/Makefile @@ -20,7 +20,7 @@ COMMIT := $(if $(shell git status --porcelain --untracked-files=no 2>/dev/null | # Exported to allow cargo to see it export KATA_CTL_VERSION := $(if $(COMMIT),$(VERSION)-$(COMMIT),$(VERSION)) -GENERATED_CODE = src/version.rs +GENERATED_CODE = src/ops/version.rs GENERATED_REPLACEMENTS= \ KATA_CTL_VERSION diff --git a/src/tools/kata-ctl/src/arch/mod.rs b/src/tools/kata-ctl/src/arch/mod.rs index c18fb0c094..e72bcc4537 100644 --- a/src/tools/kata-ctl/src/arch/mod.rs +++ b/src/tools/kata-ctl/src/arch/mod.rs @@ -17,7 +17,7 @@ pub mod s390x; #[cfg(target_arch = "x86_64")] pub mod x86_64; -pub fn check(global_args: clap::ArgMatches) -> Result<()> { +pub fn check() -> Result<()> { #[cfg(target_arch = "aarch64")] let result = aarch64::check(); @@ -28,7 +28,7 @@ pub fn check(global_args: clap::ArgMatches) -> Result<()> { let result = s390x::check(); #[cfg(target_arch = "x86_64")] - let result = x86_64::check(global_args); + let result = x86_64::check(); #[cfg(not(any( target_arch = "aarch64", 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 5618a44512..9c761d1187 100644 --- a/src/tools/kata-ctl/src/arch/x86_64/mod.rs +++ b/src/tools/kata-ctl/src/arch/x86_64/mod.rs @@ -41,7 +41,7 @@ mod arch_specific { } - pub fn check(_global_args: clap::ArgMatches) -> Result<()> { + pub fn check() -> Result<()> { println!("INFO: check: x86_64"); let _cpu_result = check_cpu(); diff --git a/src/tools/kata-ctl/src/args.rs b/src/tools/kata-ctl/src/args.rs new file mode 100644 index 0000000000..4c8bf51fcd --- /dev/null +++ b/src/tools/kata-ctl/src/args.rs @@ -0,0 +1,90 @@ +// Copyright (c) 2022 Intel Corporation +// +// SPDX-License-Identifier: Apache-2.0 +// + +use clap::{ + Args, + Parser, + Subcommand +}; + +use thiserror::Error; + +#[derive(Parser, Debug)] +#[clap(name = "kata-ctl", author, about="Kata Containers control tool")] +pub struct KataCtlCli { + #[clap(subcommand)] + pub command: Commands, +} + +#[derive(Debug, Subcommand)] +pub enum Commands { + /// Tests if system can run Kata Containers + Check(CheckArgument), + + /// Directly assign a volume to Kata Containers to manage + DirectVolume, + + /// Display settings + Env, + + /// Enter into guest by debug console + Exec, + + /// Manage vm factory + Factory, + + /// Manages iptables + Iptables(IptablesCommand), + + /// Gather metrics associated with infrastructure used to run a sandbox + Metrics(MetricsCommand), + + /// Display version details + Version, +} + +#[derive(Debug,Args,Error)] +#[error("Argument is not valid")] +pub struct CheckArgument { + #[clap(subcommand)] + pub command: CheckSubCommand, +} + +#[derive(Debug, Subcommand)] +pub enum CheckSubCommand { + /// Runs all checks + All, + + /// Runs all checks but excluding network checks. + NoNetworkChecks, + + /// Only compare the current and latest available versions + CheckVersionOnly, +} + +#[derive(Debug,Args)] +pub struct MetricsCommand { + #[clap(subcommand)] + pub metrics_cmd: MetricsSubCommand, +} + +#[derive(Debug, Subcommand)] +pub enum MetricsSubCommand { + /// Arguments for metrics + MetricsArgs, +} + +// #[derive(Parser, Debug)] +#[derive(Debug, Args)] +pub struct IptablesCommand { + #[clap(subcommand)] + pub iptables: IpTablesArguments, +} + +#[derive(Debug, Subcommand)] +pub enum IpTablesArguments { + /// Configure iptables + Metrics, +} diff --git a/src/tools/kata-ctl/src/check.rs b/src/tools/kata-ctl/src/check.rs index 9317b903a1..6a3788d959 100644 --- a/src/tools/kata-ctl/src/check.rs +++ b/src/tools/kata-ctl/src/check.rs @@ -86,7 +86,11 @@ pub fn check_cpu_attribs(cpu_info: &str, required_attribs: &'static [&'static st } pub fn run_network_checks() -> Result<()> { - unimplemented!("Tests using network checks not implemented"); + Ok(()) +} + +pub fn check_version() -> Result<()> { + Ok(()) } #[cfg(test)] @@ -110,4 +114,3 @@ mod tests { assert_eq!(expected, actual); } } - diff --git a/src/tools/kata-ctl/src/main.rs b/src/tools/kata-ctl/src/main.rs index 484c78a8aa..5fb21b049c 100644 --- a/src/tools/kata-ctl/src/main.rs +++ b/src/tools/kata-ctl/src/main.rs @@ -3,116 +3,44 @@ // SPDX-License-Identifier: Apache-2.0 // -use anyhow::{anyhow, Result}; -use clap::{crate_name, App, Arg, SubCommand}; -use std::process::exit; - +mod args; mod arch; mod check; -mod utils; -mod version; +mod ops; -const DESCRIPTION_TEXT: &str = r#"DESCRIPTION: - kata-ctl description placeholder."#; +use clap::Parser; +use anyhow::Result; +use std::process::exit; -const ABOUT_TEXT: &str = "Kata Containers control tool"; +use args::{ + KataCtlCli, + Commands +}; -const NAME: &str = "kata-ctl"; - -fn run_checks(global_args: clap::ArgMatches) -> Result<()> { - let args = global_args - .subcommand_matches("check") - .ok_or_else(|| anyhow!("BUG: missing sub-command arguments"))?; - - let no_network_check = args.is_present("no-network-checks"); - - // run architecture-agnostic tests - if !no_network_check { - // run code that uses network checks - let _network_checks = check::run_network_checks(); - } - - // run architecture-specific tests - let _all_checks = arch::check(global_args); - - Ok(()) -} +use ops::check_ops::{ + handle_check, + handle_check_volume, + handle_env, + handle_exec, + handle_factory, + handle_iptables, + handle_metrics, + handle_version +}; fn real_main() -> Result<()> { - let name = crate_name!(); - let version = version::get(); - let app = App::new(name) - .version(&*version) - .about(ABOUT_TEXT) - .long_about(DESCRIPTION_TEXT) - .subcommand( - SubCommand::with_name("check") - .about("tests if system can run Kata Containers") - .arg( - Arg::with_name("no-network-checks") - .long("no-network-checks") - .help("run check with no network checks") - .takes_value(false), - ), - ) - .subcommand( - SubCommand::with_name("direct-volume") - .about("directly assign a volume to Kata Containers to manage"), - ) - .subcommand(SubCommand::with_name("env").about("display settings. Default to TOML")) - .subcommand(SubCommand::with_name("exec").about("enter into guest by debug console")) - .subcommand(SubCommand::with_name("factory").about("manage vm factory")) - .subcommand( - SubCommand::with_name("help").about("shows a list of commands or help for one command"), - ) - .subcommand(SubCommand::with_name("iptables").about("")) - .subcommand( - SubCommand::with_name("metrics") - .about("gather metrics associated with infrastructure used to run a sandbox"), - ) - .subcommand(SubCommand::with_name("version").about("display version details")); + let args = KataCtlCli::parse(); - let args = app.get_matches(); - - let subcmd = args - .subcommand_name() - .ok_or_else(|| anyhow!("need sub-command"))?; - - match subcmd { - "check" => { - match run_checks(args) { - Ok(_result) => println!("check may not be fully implemented"), - Err(err) => println!("{}", err), - } - Ok(()) - } - "direct-volume" => { - unimplemented!("Not implemented"); - } - "env" => { - unimplemented!("Not implemented"); - } - "exec" => { - unimplemented!("Not implemented"); - } - "factory" => { - unimplemented!("Not implemented"); - } - "help" => { - unimplemented!("Not implemented"); - } - "iptables" => { - unimplemented!("Not implemented"); - } - "metrics" => { - unimplemented!("Not implemented"); - } - "version" => { - println!("{} version {} (type: rust)", NAME, version); - Ok(()) - } - _ => return Err(anyhow!(format!("invalid sub-command: {:?}", subcmd))), + match args.command { + Commands::Check(args) => handle_check(args), + Commands::DirectVolume => handle_check_volume(), + Commands::Env => handle_env(), + Commands::Exec => handle_exec(), + Commands::Factory => handle_factory(), + Commands::Iptables(args) => handle_iptables(args), + Commands::Metrics(args) => handle_metrics(args), + Commands::Version => handle_version(), } } diff --git a/src/tools/kata-ctl/src/utils.rs b/src/tools/kata-ctl/src/ops.rs similarity index 69% rename from src/tools/kata-ctl/src/utils.rs rename to src/tools/kata-ctl/src/ops.rs index 59289ad4a9..3e0f9a4e32 100644 --- a/src/tools/kata-ctl/src/utils.rs +++ b/src/tools/kata-ctl/src/ops.rs @@ -2,3 +2,6 @@ // // SPDX-License-Identifier: Apache-2.0 // + +pub mod check_ops; +pub mod version; diff --git a/src/tools/kata-ctl/src/ops/check_ops.rs b/src/tools/kata-ctl/src/ops/check_ops.rs new file mode 100644 index 0000000000..a35c2c15d5 --- /dev/null +++ b/src/tools/kata-ctl/src/ops/check_ops.rs @@ -0,0 +1,75 @@ +// Copyright (c) 2022 Intel Corporation +// +// SPDX-License-Identifier: Apache-2.0 +// + +use crate::arch; +use crate::check; +use crate::ops::version; + +use crate::args::{ + CheckArgument, + CheckSubCommand, + IptablesCommand, + MetricsCommand +}; + +use anyhow::Result; + +const NAME: &str = "kata-ctl"; + +pub fn handle_check(checkcmd: CheckArgument) -> Result<()> { + let command = checkcmd.command; + + match command { + CheckSubCommand::All => { + // run architecture-specific tests + arch::check()?; + + // run code that uses network checks + check::run_network_checks()?; + } + + CheckSubCommand::NoNetworkChecks => { + // run architecture-specific tests + arch::check()?; + } + + CheckSubCommand::CheckVersionOnly => { + // retrieve latest release + check::check_version()?; + } + } + + Ok(()) +} + +pub fn handle_check_volume() -> Result<()> { + Ok(()) +} + +pub fn handle_env() -> Result<()> { + Ok(()) +} + +pub fn handle_exec() -> Result<()> { + Ok(()) +} + +pub fn handle_factory() -> Result<()> { + Ok(()) +} + +pub fn handle_iptables(args: IptablesCommand) -> Result<()> { + Ok(()) +} + +pub fn handle_metrics(args: MetricsCommand) -> Result<()> { + Ok(()) +} + +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/version.rs.in b/src/tools/kata-ctl/src/ops/version.rs.in similarity index 65% rename from src/tools/kata-ctl/src/version.rs.in rename to src/tools/kata-ctl/src/ops/version.rs.in index b17824a1c7..16b3c7e7f3 100644 --- a/src/tools/kata-ctl/src/version.rs.in +++ b/src/tools/kata-ctl/src/ops/version.rs.in @@ -11,8 +11,14 @@ use clap::crate_version; const KATA_CTL_VERSION: &str = "@KATA_CTL_VERSION@"; -pub fn get() -> String { - format!("{}-{}", KATA_CTL_VERSION, crate_version!()) +pub fn get() -> Result { + if KATA_CTL_VERSION.trim().is_empty() { + return Err("Unable to retrieve kata Version. Check that Kata is properly installed".to_string()); + } + else { + let version=format!("{}-{}", KATA_CTL_VERSION, crate_version!()); + return Ok(version); + } } #[cfg(test)] From 133690434cdc16394a86ec02aee1d25865aebfcd Mon Sep 17 00:00:00 2001 From: David Esparza Date: Wed, 5 Oct 2022 09:09:47 -0500 Subject: [PATCH 18/42] kata-ctl: implement CLI argument --check-version-only This kata-ctl argument returns the latest stable Kata release by hitting github.com. Adds check-version unit tests. Fixes: #11 Signed-off-by: David Esparza --- src/tools/kata-ctl/Cargo.toml | 2 + src/tools/kata-ctl/src/check.rs | 79 +++++++++++++++++++++++- src/tools/kata-ctl/src/ops/version.rs.in | 2 +- 3 files changed, 81 insertions(+), 2 deletions(-) diff --git a/src/tools/kata-ctl/Cargo.toml b/src/tools/kata-ctl/Cargo.toml index eef1f5fbb9..ba73db270a 100644 --- a/src/tools/kata-ctl/Cargo.toml +++ b/src/tools/kata-ctl/Cargo.toml @@ -12,6 +12,8 @@ edition = "2021" [dependencies] anyhow = "1.0.31" clap = { version = "3.2.20", features = ["derive", "cargo"] } +reqwest = { version = "0.11", features = ["json", "blocking"] } +serde_json = "1.0.85" thiserror = "1.0.35" [dev-dependencies] diff --git a/src/tools/kata-ctl/src/check.rs b/src/tools/kata-ctl/src/check.rs index 6a3788d959..7900ed364c 100644 --- a/src/tools/kata-ctl/src/check.rs +++ b/src/tools/kata-ctl/src/check.rs @@ -5,8 +5,14 @@ // Contains checks that are not architecture-specific -use anyhow::{anyhow, Result}; + use std::fs; +use serde_json::Value; +use std::collections::HashMap; +use anyhow::{anyhow, Result}; +use reqwest::header::{CONTENT_TYPE,USER_AGENT}; + +const KATA_GITHUB_URL: &str = "https://api.github.com/repos/kata-containers/kata-containers/releases/latest"; fn get_cpu_info(cpu_info_file: &str) -> Result { let contents = fs::read_to_string(cpu_info_file)?; @@ -89,13 +95,50 @@ 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, "application/json") + .header(USER_AGENT, "kata") + .send()? + .json::>()?; + + let version = content["tag_name"].as_str().unwrap(); + Ok(version.to_string()) +} + +fn handle_reqwest_error(e: reqwest::Error) -> anyhow::Error { + if e.is_connect() { + return anyhow!(e).context("http connection failure: connection refused"); + } + + if e.is_timeout() { + return anyhow!(e).context("http connection failure: connection timeout"); + } + + if e.is_builder() { + return anyhow!(e).context("http connection failure: url malformed"); + } + + if e.is_decode() { + return anyhow!(e).context("http connection failure: unable to decode response body"); + } + + anyhow!(e).context("unknown http connection failure: {:?}") +} + pub fn check_version() -> Result<()> { + let version = get_kata_version_by_url(KATA_GITHUB_URL).map_err(|e| handle_reqwest_error(e))?; + + println!("Version: {}", version); + Ok(()) } #[cfg(test)] mod tests { use super::*; + use semver::Version; #[test] fn test_get_cpu_info_empty_input() { @@ -113,4 +156,38 @@ mod tests { let actual = get_cpu_flags("", "").err().unwrap().to_string(); assert_eq!(expected, actual); } + + #[test] + fn check_version_by_empty_url() { + const TEST_URL: &str = "http:"; + let expected = "builder error: empty host"; + let actual = get_kata_version_by_url(TEST_URL).err().unwrap().to_string(); + assert_eq!(expected, actual); + } + + #[test] + fn check_version_by_garbage_url() { + const TEST_URL: &str = "_localhost_"; + let expected = "builder error: relative URL without a base"; + let actual = get_kata_version_by_url(TEST_URL).err().unwrap().to_string(); + assert_eq!(expected, actual); + } + + #[test] + fn check_version_by_invalid_url() { + const TEST_URL: &str = "http://localhost :80"; + let expected = "builder error: invalid domain character"; + let actual = get_kata_version_by_url(TEST_URL).err().unwrap().to_string(); + assert_eq!(expected, actual); + } + + #[test] + fn check_latest_version() { + let version = get_kata_version_by_url(KATA_GITHUB_URL).unwrap(); + + let v = Version::parse(&version).unwrap(); + assert!(!v.major.to_string().is_empty()); + assert!(!v.minor.to_string().is_empty()); + assert!(!v.patch.to_string().is_empty()); + } } diff --git a/src/tools/kata-ctl/src/ops/version.rs.in b/src/tools/kata-ctl/src/ops/version.rs.in index 16b3c7e7f3..c207b0ea3e 100644 --- a/src/tools/kata-ctl/src/ops/version.rs.in +++ b/src/tools/kata-ctl/src/ops/version.rs.in @@ -28,7 +28,7 @@ mod tests { #[test] fn test_get() { - let version = get(); + let version = get().unwrap(); let v = Version::parse(&version).unwrap(); assert!(!v.major.to_string().is_empty()); From c23584994a8dc2f594d60e775f4d8ee4e45b08b0 Mon Sep 17 00:00:00 2001 From: "James O. D. Hunt" Date: Mon, 10 Oct 2022 09:46:36 +0100 Subject: [PATCH 19/42] kata-ctl: clippy: Resolve warnings and reformat Resolved a couple of clippy warnings and applied standard `rustfmt`. Signed-off-by: James O. D. Hunt --- src/tools/kata-ctl/src/arch/x86_64/mod.rs | 8 ++-- src/tools/kata-ctl/src/args.rs | 14 +++---- src/tools/kata-ctl/src/check.rs | 45 ++++++++++++++--------- src/tools/kata-ctl/src/main.rs | 20 +++------- src/tools/kata-ctl/src/ops/check_ops.rs | 11 ++---- 5 files changed, 45 insertions(+), 53 deletions(-) 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 9c761d1187..379f8b6e5a 100644 --- a/src/tools/kata-ctl/src/arch/x86_64/mod.rs +++ b/src/tools/kata-ctl/src/arch/x86_64/mod.rs @@ -7,8 +7,8 @@ pub use arch_specific::*; mod arch_specific { - use anyhow::{anyhow, Result}; use crate::check; + use anyhow::{anyhow, Result}; const PROC_CPUINFO: &str = "/proc/cpuinfo"; const CPUINFO_DELIMITER: &str = "\nprocessor"; @@ -30,7 +30,10 @@ mod arch_specific { // 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); + 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 { @@ -40,7 +43,6 @@ mod arch_specific { Ok(()) } - pub fn check() -> Result<()> { println!("INFO: check: x86_64"); diff --git a/src/tools/kata-ctl/src/args.rs b/src/tools/kata-ctl/src/args.rs index 4c8bf51fcd..449bcb5e9d 100644 --- a/src/tools/kata-ctl/src/args.rs +++ b/src/tools/kata-ctl/src/args.rs @@ -3,16 +3,12 @@ // SPDX-License-Identifier: Apache-2.0 // -use clap::{ - Args, - Parser, - Subcommand -}; +use clap::{Args, Parser, Subcommand}; use thiserror::Error; #[derive(Parser, Debug)] -#[clap(name = "kata-ctl", author, about="Kata Containers control tool")] +#[clap(name = "kata-ctl", author, about = "Kata Containers control tool")] pub struct KataCtlCli { #[clap(subcommand)] pub command: Commands, @@ -45,7 +41,7 @@ pub enum Commands { Version, } -#[derive(Debug,Args,Error)] +#[derive(Debug, Args, Error)] #[error("Argument is not valid")] pub struct CheckArgument { #[clap(subcommand)] @@ -64,7 +60,7 @@ pub enum CheckSubCommand { CheckVersionOnly, } -#[derive(Debug,Args)] +#[derive(Debug, Args)] pub struct MetricsCommand { #[clap(subcommand)] pub metrics_cmd: MetricsSubCommand, @@ -73,7 +69,7 @@ pub struct MetricsCommand { #[derive(Debug, Subcommand)] pub enum MetricsSubCommand { /// Arguments for metrics - MetricsArgs, + MetricsArgs, } // #[derive(Parser, Debug)] diff --git a/src/tools/kata-ctl/src/check.rs b/src/tools/kata-ctl/src/check.rs index 7900ed364c..4e96eee5b9 100644 --- a/src/tools/kata-ctl/src/check.rs +++ b/src/tools/kata-ctl/src/check.rs @@ -5,14 +5,14 @@ // Contains checks that are not architecture-specific - -use std::fs; +use anyhow::{anyhow, Result}; +use reqwest::header::{CONTENT_TYPE, USER_AGENT}; use serde_json::Value; use std::collections::HashMap; -use anyhow::{anyhow, Result}; -use reqwest::header::{CONTENT_TYPE,USER_AGENT}; +use std::fs; -const KATA_GITHUB_URL: &str = "https://api.github.com/repos/kata-containers/kata-containers/releases/latest"; +const KATA_GITHUB_URL: &str = + "https://api.github.com/repos/kata-containers/kata-containers/releases/latest"; fn get_cpu_info(cpu_info_file: &str) -> Result { let contents = fs::read_to_string(cpu_info_file)?; @@ -22,7 +22,7 @@ fn get_cpu_info(cpu_info_file: &str) -> Result { // 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 { - let contents = get_cpu_info(cpu_info_file)?; + let contents = get_cpu_info(cpu_info_file)?; if contents.is_empty() { return Err(anyhow!("cpu_info string is empty"))?; @@ -64,9 +64,9 @@ pub fn get_cpu_flags(cpu_info: &str, cpu_flags_tag: &str) -> Result { // 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> { - let data_vec: Vec <&str> = data.split_whitespace().collect(); + let data_vec: Vec<&str> = data.split_whitespace().collect(); - let mut missing: Vec = Vec::new(); + let mut missing: Vec = Vec::new(); for item in required { if !data_vec.contains(&item) { @@ -77,13 +77,19 @@ fn get_missing_strings(data: &str, required: &'static [&'static str]) -> Result< Ok(missing) } -pub fn check_cpu_flags(retrieved_flags: &str, required_flags: &'static [&'static str]) -> Result> { +pub fn check_cpu_flags( + retrieved_flags: &str, + required_flags: &'static [&'static str], +) -> Result> { 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> { +pub fn check_cpu_attribs( + cpu_info: &str, + required_attribs: &'static [&'static str], +) -> Result> { let mut cpu_info_processed = cpu_info.replace("\t", ""); cpu_info_processed = cpu_info_processed.replace("\n", " "); @@ -146,7 +152,10 @@ mod tests { let actual = get_cpu_info("").err().unwrap().to_string(); assert_eq!(expected, actual); - let actual = get_single_cpu_info("", "\nprocessor").err().unwrap().to_string(); + let actual = get_single_cpu_info("", "\nprocessor") + .err() + .unwrap() + .to_string(); assert_eq!(expected, actual); } @@ -162,7 +171,7 @@ mod tests { const TEST_URL: &str = "http:"; let expected = "builder error: empty host"; let actual = get_kata_version_by_url(TEST_URL).err().unwrap().to_string(); - assert_eq!(expected, actual); + assert_eq!(expected, actual); } #[test] @@ -170,7 +179,7 @@ mod tests { const TEST_URL: &str = "_localhost_"; let expected = "builder error: relative URL without a base"; let actual = get_kata_version_by_url(TEST_URL).err().unwrap().to_string(); - assert_eq!(expected, actual); + assert_eq!(expected, actual); } #[test] @@ -178,16 +187,16 @@ mod tests { const TEST_URL: &str = "http://localhost :80"; let expected = "builder error: invalid domain character"; let actual = get_kata_version_by_url(TEST_URL).err().unwrap().to_string(); - assert_eq!(expected, actual); + assert_eq!(expected, actual); } #[test] fn check_latest_version() { let version = get_kata_version_by_url(KATA_GITHUB_URL).unwrap(); - let v = Version::parse(&version).unwrap(); - assert!(!v.major.to_string().is_empty()); - assert!(!v.minor.to_string().is_empty()); - assert!(!v.patch.to_string().is_empty()); + let v = Version::parse(&version).unwrap(); + assert!(!v.major.to_string().is_empty()); + assert!(!v.minor.to_string().is_empty()); + assert!(!v.patch.to_string().is_empty()); } } diff --git a/src/tools/kata-ctl/src/main.rs b/src/tools/kata-ctl/src/main.rs index 5fb21b049c..30e4b5eb7a 100644 --- a/src/tools/kata-ctl/src/main.rs +++ b/src/tools/kata-ctl/src/main.rs @@ -3,33 +3,23 @@ // SPDX-License-Identifier: Apache-2.0 // -mod args; mod arch; +mod args; mod check; mod ops; -use clap::Parser; use anyhow::Result; +use clap::Parser; use std::process::exit; -use args::{ - KataCtlCli, - Commands -}; +use args::{Commands, KataCtlCli}; use ops::check_ops::{ - handle_check, - handle_check_volume, - handle_env, - handle_exec, - handle_factory, - handle_iptables, - handle_metrics, - handle_version + handle_check, handle_check_volume, handle_env, handle_exec, handle_factory, handle_iptables, + handle_metrics, handle_version, }; fn real_main() -> Result<()> { - let args = KataCtlCli::parse(); match args.command { diff --git a/src/tools/kata-ctl/src/ops/check_ops.rs b/src/tools/kata-ctl/src/ops/check_ops.rs index a35c2c15d5..b97cb6b05d 100644 --- a/src/tools/kata-ctl/src/ops/check_ops.rs +++ b/src/tools/kata-ctl/src/ops/check_ops.rs @@ -7,12 +7,7 @@ use crate::arch; use crate::check; use crate::ops::version; -use crate::args::{ - CheckArgument, - CheckSubCommand, - IptablesCommand, - MetricsCommand -}; +use crate::args::{CheckArgument, CheckSubCommand, IptablesCommand, MetricsCommand}; use anyhow::Result; @@ -60,11 +55,11 @@ pub fn handle_factory() -> Result<()> { Ok(()) } -pub fn handle_iptables(args: IptablesCommand) -> Result<()> { +pub fn handle_iptables(_args: IptablesCommand) -> Result<()> { Ok(()) } -pub fn handle_metrics(args: MetricsCommand) -> Result<()> { +pub fn handle_metrics(_args: MetricsCommand) -> Result<()> { Ok(()) } From 15c343cbf2f441daf9da7acda09c361566610828 Mon Sep 17 00:00:00 2001 From: "James O. D. Hunt" Date: Mon, 10 Oct 2022 10:26:25 +0100 Subject: [PATCH 20/42] kata-ctl: Don't rely on system ssl libs Build using the rust TLS implementation rather than the system ones. This resolves the `reqwest` crate build failure: it doesn't appear to build against the native libssl libraries due to Kata defaulting to using the musl libc. Fixes: #5387. Signed-off-by: James O. D. Hunt --- src/tools/kata-ctl/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tools/kata-ctl/Cargo.toml b/src/tools/kata-ctl/Cargo.toml index ba73db270a..bf42c93584 100644 --- a/src/tools/kata-ctl/Cargo.toml +++ b/src/tools/kata-ctl/Cargo.toml @@ -12,7 +12,7 @@ edition = "2021" [dependencies] anyhow = "1.0.31" clap = { version = "3.2.20", features = ["derive", "cargo"] } -reqwest = { version = "0.11", features = ["json", "blocking"] } +reqwest = { version = "0.11", default-features = false, features = ["json", "blocking", "rustls-tls"] } serde_json = "1.0.85" thiserror = "1.0.35" From 781e604c39d85ffad476b03ef5ca2dd8f6e48bd3 Mon Sep 17 00:00:00 2001 From: "James O. D. Hunt" Date: Mon, 10 Oct 2022 16:49:21 +0100 Subject: [PATCH 21/42] docs: Reference kata-ctl README Add a link to the `kata-ctl` tool's README. Signed-off-by: James O. D. Hunt --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 2b0759a2c0..d2b27b97c4 100644 --- a/README.md +++ b/README.md @@ -135,6 +135,7 @@ The table below lists the remaining parts of the project: | [kernel](https://www.kernel.org) | kernel | Linux kernel used by the hypervisor to boot the guest image. Patches are stored [here](tools/packaging/kernel). | | [osbuilder](tools/osbuilder) | infrastructure | Tool to create "mini O/S" rootfs and initrd images and kernel for the hypervisor. | | [`agent-ctl`](src/tools/agent-ctl) | utility | Tool that provides low-level access for testing the agent. | +| [`kata-ctl`](src/tools/kata-ctl) | utility | Tool that provides advanced commands and debug facilities. | | [`trace-forwarder`](src/tools/trace-forwarder) | utility | Agent tracing helper. | | [`runk`](src/tools/runk) | utility | Standard OCI container runtime based on the agent. | | [`ci`](https://github.com/kata-containers/ci) | CI | Continuous Integration configuration files and scripts. | From 26c043dee72ea4a4482d1344176024d71e010795 Mon Sep 17 00:00:00 2001 From: wllenyj Date: Mon, 10 Oct 2022 16:43:25 +0800 Subject: [PATCH 22/42] ci: Add dragonball test Enhanced Static-Check of CI to support nested virtualization. Fixes: #5378 Signed-off-by: wllenyj --- .github/workflows/static-checks.yaml | 24 ++++++++++++++++++++++++ src/dragonball/Makefile | 3 +-- 2 files changed, 25 insertions(+), 2 deletions(-) diff --git a/.github/workflows/static-checks.yaml b/.github/workflows/static-checks.yaml index cc6a7149c7..c4c78551e8 100644 --- a/.github/workflows/static-checks.yaml +++ b/.github/workflows/static-checks.yaml @@ -94,3 +94,27 @@ jobs: if: ${{ !contains(github.event.pull_request.labels.*.name, 'force-skip-ci') }} run: | cd ${GOPATH}/src/github.com/${{ github.repository }} && sudo -E PATH="$PATH" make test + + test-dragonball: + runs-on: self-hosted + env: + RUST_BACKTRACE: "1" + steps: + - uses: actions/checkout@v3 + - name: Set env + if: ${{ !contains(github.event.pull_request.labels.*.name, 'force-skip-ci') }} + run: | + echo "GOPATH=${{ github.workspace }}" >> $GITHUB_ENV + - name: Install Rust + if: ${{ !contains(github.event.pull_request.labels.*.name, 'force-skip-ci') }} + run: | + ./ci/install_rust.sh + PATH=$PATH:"$HOME/.cargo/bin" + - name: Run Unit Test + if: ${{ !contains(github.event.pull_request.labels.*.name, 'force-skip-ci') }} + run: | + cd src/dragonball + /root/.cargo/bin/cargo version + rustc --version + # TODO: Using the cargo command directly will get `sudo: cargo: command not found` error. + sudo -E /root/.cargo/bin/cargo test --all-features -- --nocapture diff --git a/src/dragonball/Makefile b/src/dragonball/Makefile index c4955cf856..f98367f92c 100644 --- a/src/dragonball/Makefile +++ b/src/dragonball/Makefile @@ -26,5 +26,4 @@ clean: cargo clean test: - @echo "INFO: testing dragonball for development build" - cargo test --all-features -- --nocapture + @echo "INFO: skip testing dragonball" From 862eaef86328f347dd3f5ebf1312ebeac7a7061b Mon Sep 17 00:00:00 2001 From: chmod100 Date: Tue, 11 Oct 2022 02:29:20 +0000 Subject: [PATCH 23/42] docs: fix a typo in rust-runtime-installation-guide Fixes: #5392 Signed-off-by: chmod100 --- .../kata-containers-3.0-rust-runtime-installation-guide.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/install/kata-containers-3.0-rust-runtime-installation-guide.md b/docs/install/kata-containers-3.0-rust-runtime-installation-guide.md index 2675a55996..cf9eee456c 100644 --- a/docs/install/kata-containers-3.0-rust-runtime-installation-guide.md +++ b/docs/install/kata-containers-3.0-rust-runtime-installation-guide.md @@ -83,7 +83,7 @@ $ git clone https://github.com/kata-containers/kata-containers.git $ cd kata-containers/src/runtime-rs $ make && sudo make install ``` -After running the command above, the default config file `configuration.toml` will be installed under `/usr/share/defaults/kata-containers/`, the binary file `containerd-shim-kata-v2` will be installed under `/user/local/bin` . +After running the command above, the default config file `configuration.toml` will be installed under `/usr/share/defaults/kata-containers/`, the binary file `containerd-shim-kata-v2` will be installed under `/usr/local/bin/` . ### Build Kata Containers Kernel Follow the [Kernel installation guide](/tools/packaging/kernel/README.md). From f7010b80614d0858e21bd661f95a4847ee00c77a Mon Sep 17 00:00:00 2001 From: "James O. D. Hunt" Date: Mon, 10 Oct 2022 10:09:56 +0100 Subject: [PATCH 24/42] kata-ctl: docs: Write basic documentation Provide a basic document explaining a little about the `kata-ctl` command. Fixes: #5351. Signed-off-by: James O. D. Hunt --- src/tools/kata-ctl/README.md | 42 ++++++++++++++++++++++++++++++++---- 1 file changed, 38 insertions(+), 4 deletions(-) diff --git a/src/tools/kata-ctl/README.md b/src/tools/kata-ctl/README.md index 1e441d58b2..bf908f60d0 100644 --- a/src/tools/kata-ctl/README.md +++ b/src/tools/kata-ctl/README.md @@ -2,14 +2,48 @@ ## Overview +The `kata-ctl` tool is a rust rewrite of the +[`kata-runtime`](../../runtime/cmd/kata-runtime) +[utility program](../../../docs/design/architecture/README.md#utility-program). + +The program provides a number of utility commands for: + +- Using advanced Kata Containers features. +- Problem determination and debugging. + ## Audience and environment -## History +Users and administrators. -## Full details +## Build the tool -## Code summary +```bash +$ make +``` + +## Install the tool + +```bash +$ make install +``` ## Run the tool -### Prerequisites +```bash +$ kata-ctl ... +``` + +For example, to determine if your system is capable of running Kata +Containers, run: + +```bash +$ kata-ctl check all +``` + +### Full details + +For a usage statement, run: + +```bash +$ kata-ctl --help +``` From 2b345ba29d9ec6d3783f9573a430c66059c31c52 Mon Sep 17 00:00:00 2001 From: "James O. D. Hunt" Date: Tue, 11 Oct 2022 10:03:55 +0100 Subject: [PATCH 25/42] build: Add kata-ctl to tools list Update the top-level Makefile to build the `kata-ctl` tool by default. Fixes: #4499, #5334. Signed-off-by: James O. D. Hunt --- Makefile | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/Makefile b/Makefile index 4d2be6b4d8..e30cf1d980 100644 --- a/Makefile +++ b/Makefile @@ -15,9 +15,10 @@ COMPONENTS += runtime-rs TOOLS = TOOLS += agent-ctl -TOOLS += trace-forwarder -TOOLS += runk +TOOLS += kata-ctl TOOLS += log-parser +TOOLS += runk +TOOLS += trace-forwarder STANDARD_TARGETS = build check clean install test vendor From a743e37daf7e4001caf291672ae2fdb97524b3d7 Mon Sep 17 00:00:00 2001 From: Chao Wu Date: Tue, 11 Oct 2022 19:41:47 +0800 Subject: [PATCH 26/42] Dragonball: delete redundant comments in blk_dev_mgr delete redundent derive part for BlockDeviceMgr. fixes: #5396 Signed-off-by: Chao Wu --- src/dragonball/src/device_manager/blk_dev_mgr.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/src/dragonball/src/device_manager/blk_dev_mgr.rs b/src/dragonball/src/device_manager/blk_dev_mgr.rs index a34b951653..0493a818a4 100644 --- a/src/dragonball/src/device_manager/blk_dev_mgr.rs +++ b/src/dragonball/src/device_manager/blk_dev_mgr.rs @@ -285,7 +285,6 @@ impl std::fmt::Debug for BlockDeviceInfo { pub type BlockDeviceInfo = DeviceConfigInfo; /// Wrapper for the collection that holds all the Block Devices Configs -//#[derive(Clone, Debug, Deserialize, PartialEq, Serialize)] #[derive(Clone)] pub struct BlockDeviceMgr { /// A list of `BlockDeviceInfo` objects. From 6a64fb0eb3dd298e0864aa45bc9f92fd28ef54bd Mon Sep 17 00:00:00 2001 From: wllenyj Date: Tue, 11 Oct 2022 16:50:38 +0800 Subject: [PATCH 27/42] ci: skip s390x for dragonball. Currently, Dragonball only supports x86_64 and aarch64 platforms. Fixes: #4381 Signed-off-by: wllenyj --- src/dragonball/Makefile | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/dragonball/Makefile b/src/dragonball/Makefile index f98367f92c..90ab19fc07 100644 --- a/src/dragonball/Makefile +++ b/src/dragonball/Makefile @@ -2,6 +2,14 @@ # Copyright (c) 2019-2022 Ant Group. All rights reserved. # SPDX-License-Identifier: Apache-2.0 +include ../../utils.mk + +ifeq ($(ARCH), s390x) +default build check test clippy: + @echo "s390x not support currently" + exit 0 +else + default: build build: @@ -27,3 +35,5 @@ clean: test: @echo "INFO: skip testing dragonball" + +endif # ifeq ($(ARCH), s390x) From a343c570e43a76e5c7d26e2d30a742537da385a8 Mon Sep 17 00:00:00 2001 From: wllenyj Date: Wed, 12 Oct 2022 14:59:38 +0800 Subject: [PATCH 28/42] dragonball: enhance dragonball ci Unified use of Makefile instead of calling `cargo test` directly. Signed-off-by: wllenyj --- .github/workflows/static-checks.yaml | 3 +-- src/dragonball/Makefile | 12 ++++++++++-- utils.mk | 1 + 3 files changed, 12 insertions(+), 4 deletions(-) diff --git a/.github/workflows/static-checks.yaml b/.github/workflows/static-checks.yaml index c4c78551e8..0471a099bb 100644 --- a/.github/workflows/static-checks.yaml +++ b/.github/workflows/static-checks.yaml @@ -116,5 +116,4 @@ jobs: cd src/dragonball /root/.cargo/bin/cargo version rustc --version - # TODO: Using the cargo command directly will get `sudo: cargo: command not found` error. - sudo -E /root/.cargo/bin/cargo test --all-features -- --nocapture + sudo -E env PATH=$PATH LIBC=gnu SUPPORT_VIRTUALIZATION=true make test diff --git a/src/dragonball/Makefile b/src/dragonball/Makefile index 90ab19fc07..279d872bbc 100644 --- a/src/dragonball/Makefile +++ b/src/dragonball/Makefile @@ -13,7 +13,8 @@ else default: build build: - cargo build --all-features + @echo "INFO: cargo build..." + cargo build --all-features --target $(TRIPLE) check: clippy format @@ -34,6 +35,13 @@ clean: cargo clean test: - @echo "INFO: skip testing dragonball" +ifdef SUPPORT_VIRTUALIZATION + cargo test --all-features --target $(TRIPLE) -- --nocapture +else + @echo "INFO: skip testing dragonball, it need virtualization support." + exit 0 +endif endif # ifeq ($(ARCH), s390x) + +.DEFAULT_GOAL := default diff --git a/utils.mk b/utils.mk index a52bb7362d..bc4aa392c9 100644 --- a/utils.mk +++ b/utils.mk @@ -173,6 +173,7 @@ TRIPLE = $(ARCH)-unknown-linux-$(LIBC) CWD := $(shell dirname $(realpath $(firstword $(MAKEFILE_LIST)))) standard_rust_check: + @echo "standard rust check..." cargo fmt -- --check cargo clippy --all-targets --all-features --release \ -- \ From 1f1901e059444b0a560117b5f448102bb3d39834 Mon Sep 17 00:00:00 2001 From: wllenyj Date: Wed, 12 Oct 2022 15:22:10 +0800 Subject: [PATCH 29/42] dragonball: fix clippy warning for aarch64 Added aarch64 check. Signed-off-by: wllenyj --- src/dragonball/src/device_manager/mod.rs | 15 ++++++++------- src/dragonball/src/vcpu/aarch64.rs | 1 + src/dragonball/src/vcpu/vcpu_impl.rs | 2 +- src/dragonball/src/vcpu/vcpu_manager.rs | 2 +- src/dragonball/src/vm/aarch64.rs | 4 +++- 5 files changed, 14 insertions(+), 10 deletions(-) diff --git a/src/dragonball/src/device_manager/mod.rs b/src/dragonball/src/device_manager/mod.rs index 75eaef6ac3..09689ca52c 100644 --- a/src/dragonball/src/device_manager/mod.rs +++ b/src/dragonball/src/device_manager/mod.rs @@ -795,13 +795,14 @@ impl DeviceManager { fn allocate_mmio_device_resource( &self, ) -> std::result::Result { - let mut requests = Vec::new(); - requests.push(ResourceConstraint::MmioAddress { - range: None, - align: MMIO_DEFAULT_CFG_SIZE, - size: MMIO_DEFAULT_CFG_SIZE, - }); - requests.push(ResourceConstraint::LegacyIrq { irq: None }); + let requests = vec![ + ResourceConstraint::MmioAddress { + range: None, + align: MMIO_DEFAULT_CFG_SIZE, + size: MMIO_DEFAULT_CFG_SIZE, + }, + ResourceConstraint::LegacyIrq { irq: None }, + ]; self.res_manager .allocate_device_resources(&requests, false) diff --git a/src/dragonball/src/vcpu/aarch64.rs b/src/dragonball/src/vcpu/aarch64.rs index 054a1f65d4..dc4b9c61a6 100644 --- a/src/dragonball/src/vcpu/aarch64.rs +++ b/src/dragonball/src/vcpu/aarch64.rs @@ -39,6 +39,7 @@ impl Vcpu { /// vcpu thread to vmm thread. /// * `create_ts` - A timestamp used by the vcpu to calculate its lifetime. /// * `support_immediate_exit` - whether kvm uses supports immediate_exit flag. + #[allow(clippy::too_many_arguments)] pub fn new_aarch64( id: u8, vcpu_fd: Arc, diff --git a/src/dragonball/src/vcpu/vcpu_impl.rs b/src/dragonball/src/vcpu/vcpu_impl.rs index 85f2888ced..ff3f9e44fe 100644 --- a/src/dragonball/src/vcpu/vcpu_impl.rs +++ b/src/dragonball/src/vcpu/vcpu_impl.rs @@ -851,7 +851,7 @@ pub mod tests { let kvm = Kvm::new().unwrap(); let vm = Arc::new(kvm.create_vm().unwrap()); - let kvm_context = KvmContext::new(Some(kvm.as_raw_fd())).unwrap(); + let _kvm_context = KvmContext::new(Some(kvm.as_raw_fd())).unwrap(); let vcpu_fd = Arc::new(vm.create_vcpu(0).unwrap()); let io_manager = IoManagerCached::new(Arc::new(ArcSwap::new(Arc::new(IoManager::new())))); let reset_event_fd = EventFd::new(libc::EFD_NONBLOCK).unwrap(); diff --git a/src/dragonball/src/vcpu/vcpu_manager.rs b/src/dragonball/src/vcpu/vcpu_manager.rs index f6f3e93ffa..51a790c4db 100644 --- a/src/dragonball/src/vcpu/vcpu_manager.rs +++ b/src/dragonball/src/vcpu/vcpu_manager.rs @@ -774,7 +774,7 @@ impl VcpuManager { self.reset_event_fd.as_ref().unwrap().try_clone().unwrap(), self.vcpu_state_event.try_clone().unwrap(), self.vcpu_state_sender.clone(), - request_ts.clone(), + request_ts, self.support_immediate_exit, ) .map_err(VcpuManagerError::Vcpu) diff --git a/src/dragonball/src/vm/aarch64.rs b/src/dragonball/src/vm/aarch64.rs index 8206920ce7..fddbf9516a 100644 --- a/src/dragonball/src/vm/aarch64.rs +++ b/src/dragonball/src/vm/aarch64.rs @@ -35,6 +35,7 @@ use crate::event_manager::EventManager; /// * `device_info` - A hashmap containing the attached devices for building FDT device nodes. /// * `gic_device` - The GIC device. /// * `initrd` - Information about an optional initrd. +#[allow(clippy::borrowed_box)] fn configure_system( guest_mem: &M, cmdline: &str, @@ -58,8 +59,9 @@ fn configure_system( #[cfg(target_arch = "aarch64")] impl Vm { /// Gets a reference to the irqchip of the VM + #[allow(clippy::borrowed_box)] pub fn get_irqchip(&self) -> &Box { - &self.irqchip_handle.as_ref().unwrap() + self.irqchip_handle.as_ref().unwrap() } /// Creates the irq chip in-kernel device model. From fb63274747daf1b23544347427d1554ee6ba2f59 Mon Sep 17 00:00:00 2001 From: "James O. D. Hunt" Date: Wed, 12 Oct 2022 09:58:44 +0100 Subject: [PATCH 30/42] kata-ctl: rustfmt + clippy fixes Make this file conform to the standard rust layout conventions and simplify the code as recommended by `clippy`. Signed-off-by: James O. D. Hunt --- src/tools/kata-ctl/src/arch/x86_64/mod.rs | 8 ++++---- src/tools/kata-ctl/src/check.rs | 14 ++++++-------- src/tools/kata-ctl/src/ops/version.rs.in | 22 +++++++++++----------- 3 files changed, 21 insertions(+), 23 deletions(-) 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 379f8b6e5a..95817981e1 100644 --- a/src/tools/kata-ctl/src/arch/x86_64/mod.rs +++ b/src/tools/kata-ctl/src/arch/x86_64/mod.rs @@ -13,8 +13,8 @@ mod arch_specific { 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"]; + const CPU_FLAGS_INTEL: &[&str] = &["lm", "sse4_1", "vmx"]; + const CPU_ATTRIBS_INTEL: &[&str] = &["GenuineIntel"]; // check cpu fn check_cpu() -> Result<()> { @@ -29,14 +29,14 @@ mod arch_specific { // 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 { + if !missing_cpu_attributes.is_empty() { 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 { + if !missing_cpu_flags.is_empty() { eprintln!("WARNING: Missing CPU flags {:?}", missing_cpu_flags); } diff --git a/src/tools/kata-ctl/src/check.rs b/src/tools/kata-ctl/src/check.rs index 4e96eee5b9..28febb307c 100644 --- a/src/tools/kata-ctl/src/check.rs +++ b/src/tools/kata-ctl/src/check.rs @@ -45,10 +45,10 @@ pub fn get_cpu_flags(cpu_info: &str, cpu_flags_tag: &str) -> Result { return Err(anyhow!("cpu_info string is empty"))?; } - let subcontents: Vec<&str> = cpu_info.split("\n").collect(); + 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 line_data: Vec<&str> = line.split(':').collect(); let flags = line_data .last() .ok_or("error splitting flags in cpuinfo") @@ -64,12 +64,10 @@ pub fn get_cpu_flags(cpu_info: &str, cpu_flags_tag: &str) -> Result { // 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> { - let data_vec: Vec<&str> = data.split_whitespace().collect(); - let mut missing: Vec = Vec::new(); for item in required { - if !data_vec.contains(&item) { + if !data.split_whitespace().any(|x| x == *item) { missing.push(item.to_string()); } } @@ -90,8 +88,8 @@ pub fn check_cpu_attribs( cpu_info: &str, required_attribs: &'static [&'static str], ) -> Result> { - let mut cpu_info_processed = cpu_info.replace("\t", ""); - cpu_info_processed = cpu_info_processed.replace("\n", " "); + 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) @@ -134,7 +132,7 @@ fn handle_reqwest_error(e: reqwest::Error) -> anyhow::Error { } pub fn check_version() -> Result<()> { - let version = get_kata_version_by_url(KATA_GITHUB_URL).map_err(|e| handle_reqwest_error(e))?; + let version = get_kata_version_by_url(KATA_GITHUB_URL).map_err(handle_reqwest_error)?; println!("Version: {}", version); diff --git a/src/tools/kata-ctl/src/ops/version.rs.in b/src/tools/kata-ctl/src/ops/version.rs.in index c207b0ea3e..052eccf168 100644 --- a/src/tools/kata-ctl/src/ops/version.rs.in +++ b/src/tools/kata-ctl/src/ops/version.rs.in @@ -13,27 +13,27 @@ const KATA_CTL_VERSION: &str = "@KATA_CTL_VERSION@"; pub fn get() -> Result { if KATA_CTL_VERSION.trim().is_empty() { - return Err("Unable to retrieve kata Version. Check that Kata is properly installed".to_string()); - } - else { - let version=format!("{}-{}", KATA_CTL_VERSION, crate_version!()); - return Ok(version); + Err("Unable to retrieve kata Version. Check that Kata is properly installed".to_string()) + } else { + let version = format!("{}-{}", KATA_CTL_VERSION, crate_version!()); + + Ok(version) } } #[cfg(test)] mod tests { use super::*; - use semver::{Version}; + use semver::Version; #[test] fn test_get() { let version = get().unwrap(); - let v = Version::parse(&version).unwrap(); + let v = Version::parse(&version).unwrap(); - assert!(!v.major.to_string().is_empty()); - assert!(!v.minor.to_string().is_empty()); - assert!(!v.patch.to_string().is_empty()); - assert!(!v.pre.to_string().is_empty()); + assert!(!v.major.to_string().is_empty()); + assert!(!v.minor.to_string().is_empty()); + assert!(!v.patch.to_string().is_empty()); + assert!(!v.pre.to_string().is_empty()); } } From 00a42f69c09a43248339f3aa961a46bce0e45ed6 Mon Sep 17 00:00:00 2001 From: "James O. D. Hunt" Date: Wed, 12 Oct 2022 09:59:49 +0100 Subject: [PATCH 31/42] kata-ctl: cargo: 2021 -> 2018 Revert to the 2018 edition of rust for consistency with other rust components. Signed-off-by: James O. D. Hunt --- src/tools/kata-ctl/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tools/kata-ctl/Cargo.toml b/src/tools/kata-ctl/Cargo.toml index bf42c93584..094613c343 100644 --- a/src/tools/kata-ctl/Cargo.toml +++ b/src/tools/kata-ctl/Cargo.toml @@ -7,7 +7,7 @@ name = "kata-ctl" version = "0.0.1" authors = ["The Kata Containers community "] -edition = "2021" +edition = "2018" [dependencies] anyhow = "1.0.31" From 9eb73d543ac3780661c57b00e4cbd78d5da5776a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fabiano=20Fid=C3=AAncio?= Date: Wed, 12 Oct 2022 13:14:17 +0200 Subject: [PATCH 32/42] versions: Update TDX kernel MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The previously used repo has been removed by Intel. As this happened, the TDX team worked on providing the patches that were hosted atop of the v5.15 kernel as a tarball present in the https://github.com/intel/tdx-tools repos, see https://github.com/intel/tdx-tools/pull/161. On the Kata Containers side, in order to simplify the process and to avoid adding ~1400 kernel patches to our repo, we've revived the https://github.com/kata-containers/linux repo, and created a branch and a tag with those ~1400 patches atop of the v5.15. The branch is called v5.15-plus-TDX, and the tag is called 5.15-plus-TDX (in order to avoid having to change how the kernel builder script deals with versioning). Knowing the whole background, let's switch the repo we're getting the TDX kernel from. Fixes: #5326 Signed-off-by: Fabiano Fidêncio --- tools/packaging/kernel/patches/5.15-plus-TDX.x/no_patches.txt | 0 versions.yaml | 4 ++-- 2 files changed, 2 insertions(+), 2 deletions(-) create mode 100644 tools/packaging/kernel/patches/5.15-plus-TDX.x/no_patches.txt diff --git a/tools/packaging/kernel/patches/5.15-plus-TDX.x/no_patches.txt b/tools/packaging/kernel/patches/5.15-plus-TDX.x/no_patches.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/versions.yaml b/versions.yaml index 61994a52a2..611bca508f 100644 --- a/versions.yaml +++ b/versions.yaml @@ -161,8 +161,8 @@ assets: version: "v5.19.2" tdx: description: "Linux kernel that supports TDX" - url: "https://github.com/intel/linux-kernel-dcp/archive/refs/tags" - tag: "SPR-BKC-PC-v9.6" + url: "https://github.com/kata-containers/linux/archive/refs/tags" + tag: "5.15-plus-TDX" sev: description: "Linux kernel that supports SEV" url: "https://cdn.kernel.org/pub/linux/kernel/v5.x/" From 70676d4a991201166acc8f94ac0303b7d88d21db Mon Sep 17 00:00:00 2001 From: Tingzhou Yuan Date: Thu, 13 Oct 2022 02:53:06 +0000 Subject: [PATCH 33/42] kata-ctl: improve command descriptions for consistency This change improves the command descriptions for kata-ctl and can avoid certain confusions in command functionality. Fixes #5411 Signed-off-by: Tingzhou Yuan --- src/tools/kata-ctl/src/args.rs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/tools/kata-ctl/src/args.rs b/src/tools/kata-ctl/src/args.rs index 449bcb5e9d..5cbd56caac 100644 --- a/src/tools/kata-ctl/src/args.rs +++ b/src/tools/kata-ctl/src/args.rs @@ -16,7 +16,7 @@ pub struct KataCtlCli { #[derive(Debug, Subcommand)] pub enum Commands { - /// Tests if system can run Kata Containers + /// Test if system can run Kata Containers Check(CheckArgument), /// Directly assign a volume to Kata Containers to manage @@ -25,13 +25,13 @@ pub enum Commands { /// Display settings Env, - /// Enter into guest by debug console + /// Enter into guest VM by debug console Exec, - /// Manage vm factory + /// Manage VM factory Factory, - /// Manages iptables + /// Manage guest VM iptables Iptables(IptablesCommand), /// Gather metrics associated with infrastructure used to run a sandbox @@ -50,10 +50,10 @@ pub struct CheckArgument { #[derive(Debug, Subcommand)] pub enum CheckSubCommand { - /// Runs all checks + /// Run all checks All, - /// Runs all checks but excluding network checks. + /// Run all checks but excluding network checks. NoNetworkChecks, /// Only compare the current and latest available versions From 4d9dd8790d8df63022e3dc730cf0ff2970025818 Mon Sep 17 00:00:00 2001 From: Bin Liu Date: Thu, 13 Oct 2022 17:12:43 +0800 Subject: [PATCH 34/42] runtime-rs: fix typo get_contaier_type to get_container_type Change get_contaier_type to get_container_type Fixes: #5415 Signed-off-by: Bin Liu --- src/libs/kata-sys-util/src/spec.rs | 4 ++-- src/runtime-rs/crates/shim/src/shim_delete.rs | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/libs/kata-sys-util/src/spec.rs b/src/libs/kata-sys-util/src/spec.rs index 1d41900f6b..b606d1194d 100644 --- a/src/libs/kata-sys-util/src/spec.rs +++ b/src/libs/kata-sys-util/src/spec.rs @@ -49,7 +49,7 @@ pub enum ShimIdInfo { } /// get container type -pub fn get_contaier_type(spec: &oci::Spec) -> Result { +pub fn get_container_type(spec: &oci::Spec) -> Result { for k in CRI_CONTAINER_TYPE_KEY_LIST.iter() { if let Some(type_value) = spec.annotations.get(*k) { match type_value.as_str() { @@ -67,7 +67,7 @@ pub fn get_contaier_type(spec: &oci::Spec) -> Result { /// get shim id info pub fn get_shim_id_info() -> Result { let spec = load_oci_spec()?; - match get_contaier_type(&spec)? { + match get_container_type(&spec)? { ContainerType::PodSandbox => Ok(ShimIdInfo::Sandbox), ContainerType::PodContainer => { for k in CRI_SANDBOX_ID_KEY_LIST { diff --git a/src/runtime-rs/crates/shim/src/shim_delete.rs b/src/runtime-rs/crates/shim/src/shim_delete.rs index acaa0d83e2..89d65b6101 100644 --- a/src/runtime-rs/crates/shim/src/shim_delete.rs +++ b/src/runtime-rs/crates/shim/src/shim_delete.rs @@ -6,7 +6,7 @@ use anyhow::{Context, Result}; use containerd_shim_protos::api; -use kata_sys_util::spec::{get_bundle_path, get_contaier_type, load_oci_spec}; +use kata_sys_util::spec::{get_bundle_path, get_container_type, load_oci_spec}; use kata_types::container::ContainerType; use nix::{sys::signal::kill, sys::signal::SIGKILL, unistd::Pid}; use protobuf::Message; @@ -53,7 +53,7 @@ impl ShimExecutor { let bundle_path = get_bundle_path().context("get bundle path")?; if let Ok(spec) = load_oci_spec() { - if let Ok(ContainerType::PodSandbox) = get_contaier_type(&spec) { + if let Ok(ContainerType::PodSandbox) = get_container_type(&spec) { // only force shutdown for sandbox container if let Ok(shim_pid) = self.read_pid_file(&bundle_path) { info!(sl!(), "force to shutdown shim process {}", shim_pid); From 35d52d30fd21529e2e71b7b53eda3f611d7753aa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fabiano=20Fid=C3=AAncio?= Date: Thu, 13 Oct 2022 11:53:29 +0200 Subject: [PATCH 35/42] versions: Update TDX QEMU MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The previously used repo will be removed by Intel, as done with the one used for TDX kernel. The TDX team has already worked on providing the patches that were hosted atop of the QEMU commit with the following hash 4c127fdbe81d66e7cafed90908d0fd1f6f2a6cd0 as a tarball in the https://github.com/intel/tdx-tools repo, see https://github.com/intel/tdx-tools/pull/162. On the Kata Containers side, in order to simplify the process and to avoid adding hundreds of patches to our repo, we've revived the https://github.com/kata-containers/qemu repo, and created a branch and a tag with those hundreds of patches atop of the QEMU commit hash 4c127fdbe81d66e7cafed90908d0fd1f6f2a6cd0. The branch is called 4c127fdbe81d66e7cafed90908d0fd1f6f2a6cd0-plus-TDX-v3.1 and the tag is called TDX-v3.1. Knowing the whole background, let's switch the repo we're getting the TDX QEMU from. Fixes: #5419 Signed-off-by: Fabiano Fidêncio --- .../qemu/patches/tag_patches/TDX-v3.1/no_patches.txt | 0 versions.yaml | 4 ++-- 2 files changed, 2 insertions(+), 2 deletions(-) create mode 100644 tools/packaging/qemu/patches/tag_patches/TDX-v3.1/no_patches.txt diff --git a/tools/packaging/qemu/patches/tag_patches/TDX-v3.1/no_patches.txt b/tools/packaging/qemu/patches/tag_patches/TDX-v3.1/no_patches.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/versions.yaml b/versions.yaml index 611bca508f..a4836a11ce 100644 --- a/versions.yaml +++ b/versions.yaml @@ -100,8 +100,8 @@ assets: .*/v?(\d\S+)\.tar\.gz tdx: description: "VMM that uses KVM and supports TDX" - url: "https://github.com/intel/qemu-dcp" - tag: "SPR-BKC-QEMU-v2.5" + url: "https://github.com/kata-containers/qemu" + tag: "TDX-v3.1" snp: description: "VMM that uses KVM and supports AMD SEV-SNP" url: "https://github.com/AMDESE/qemu" From 7e5941c578b1d70894640924e62924eb8944d7fc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fabiano=20Fid=C3=AAncio?= Date: Thu, 13 Oct 2022 21:53:15 +0200 Subject: [PATCH 36/42] virtiofsd: Build inside a container MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When moving to building the CI artefacts using the kata-deploy scripts, we've noticed that the build would fail on any machine where the tarball wasn't officially provided. This happens as rust is missing from the 1st layer container. However, it's a very common practice to leave the 1st layer container with the minimum possible dependencies and install whatever is needed for building a specific component in a 2nd layer container, which virtiofsd never had. In this commit we introduce the second layer containers (yes, comtainers), one for building virtiofsd using musl, and one for building virtiofsd using glibc. The reason for taking this approach was to actually simplify the scripts and avoid building the dependencies (libseccomp, libcap-ng) using musl libc. Fixes: #5425 Signed-off-by: Fabiano Fidêncio --- .../local-build/kata-deploy-binaries.sh | 2 +- .../virtiofsd/build-static-virtiofsd.sh | 19 +++--- .../packaging/static-build/virtiofsd/build.sh | 61 +++++++++++++++++++ .../static-build/virtiofsd/gnu/Dockerfile | 19 ++++++ .../static-build/virtiofsd/musl/Dockerfile | 16 +++++ 5 files changed, 109 insertions(+), 8 deletions(-) create mode 100755 tools/packaging/static-build/virtiofsd/build.sh create mode 100644 tools/packaging/static-build/virtiofsd/gnu/Dockerfile create mode 100644 tools/packaging/static-build/virtiofsd/musl/Dockerfile diff --git a/tools/packaging/kata-deploy/local-build/kata-deploy-binaries.sh b/tools/packaging/kata-deploy/local-build/kata-deploy-binaries.sh index 78fb8326b4..e1e7250788 100755 --- a/tools/packaging/kata-deploy/local-build/kata-deploy-binaries.sh +++ b/tools/packaging/kata-deploy/local-build/kata-deploy-binaries.sh @@ -26,7 +26,7 @@ readonly firecracker_builder="${static_build_dir}/firecracker/build-static-firec readonly kernel_builder="${static_build_dir}/kernel/build.sh" readonly qemu_builder="${static_build_dir}/qemu/build-static-qemu.sh" readonly shimv2_builder="${static_build_dir}/shim-v2/build.sh" -readonly virtiofsd_builder="${static_build_dir}/virtiofsd/build-static-virtiofsd.sh" +readonly virtiofsd_builder="${static_build_dir}/virtiofsd/build.sh" readonly rootfs_builder="${repo_root_dir}/tools/packaging/guest-image/build_image.sh" diff --git a/tools/packaging/static-build/virtiofsd/build-static-virtiofsd.sh b/tools/packaging/static-build/virtiofsd/build-static-virtiofsd.sh index 30eb14a952..90d6d6fa57 100755 --- a/tools/packaging/static-build/virtiofsd/build-static-virtiofsd.sh +++ b/tools/packaging/static-build/virtiofsd/build-static-virtiofsd.sh @@ -16,10 +16,13 @@ script_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" source "${script_dir}/../../scripts/lib.sh" +virtiofsd_repo="${virtiofsd_repo:-}" virtiofsd_version="${virtiofsd_version:-}" +virtiofsd_zip="${virtiofsd_zip:-}" -[ -n "$virtiofsd_version" ] || virtiofsd_version=$(get_from_kata_deps "externals.virtiofsd.version") +[ -n "$virtiofsd_repo" ] || die "failed to get virtiofsd repo" [ -n "$virtiofsd_version" ] || die "failed to get virtiofsd version" +[ -n "${virtiofsd_zip}" ] || die "failed to get virtiofsd binary URL" [ -d "virtiofsd" ] && rm -r virtiofsd @@ -28,8 +31,6 @@ pull_virtiofsd_released_binary() { info "Only x86_64 binaries are distributed as part of the virtiofsd releases" && return 1 fi info "Download virtiofsd version: ${virtiofsd_version}" - virtiofsd_zip=$(get_from_kata_deps "externals.virtiofsd.meta.binary") - [ -n "${virtiofsd_zip}" ] || die "failed to get virtiofsd binary URL" mkdir -p virtiofsd @@ -44,31 +45,35 @@ pull_virtiofsd_released_binary() { } init_env() { + source "$HOME/.cargo/env" + case ${ARCH} in "aarch64") LIBC="musl" + ARCH_LIBC="" ;; "ppc64le") LIBC="gnu" ARCH="powerpc64le" + ARCH_LIBC=${ARCH}-linux-${LIBC} ;; "s390x") LIBC="gnu" + ARCH_LIBC=${ARCH}-linux-${LIBC} ;; "x86_64") LIBC="musl" + ARCH_LIBC="" + ;; esac - ARCH_LIBC=${ARCH}-linux-${LIBC} } build_virtiofsd_from_source() { echo "build viriofsd from source" init_env - virtiofsd_url=$(get_from_kata_deps "externals.virtiofsd.url") - - git clone --depth 1 --branch ${virtiofsd_version} ${virtiofsd_url} virtiofsd + git clone --depth 1 --branch ${virtiofsd_version} ${virtiofsd_repo} virtiofsd pushd virtiofsd export RUSTFLAGS='-C target-feature=+crt-static -C link-self-contained=yes' diff --git a/tools/packaging/static-build/virtiofsd/build.sh b/tools/packaging/static-build/virtiofsd/build.sh new file mode 100755 index 0000000000..64441d2aef --- /dev/null +++ b/tools/packaging/static-build/virtiofsd/build.sh @@ -0,0 +1,61 @@ +#!/usr/bin/env bash +# +# Copyright (c) 2022 Intel +# +# SPDX-License-Identifier: Apache-2.0 + +set -o errexit +set -o nounset +set -o pipefail + +script_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +readonly repo_root_dir="$(cd "${script_dir}/../../../.." && pwd)" +readonly virtiofsd_builder="${script_dir}/build-static-virtiofsd.sh" + +source "${script_dir}/../../scripts/lib.sh" + +DESTDIR=${DESTDIR:-${PWD}} +PREFIX=${PREFIX:-/opt/kata} +container_image="kata-virtiofsd-builder" +kata_version="${kata_version:-}" +virtiofsd_repo="${virtiofsd_repo:-}" +virtiofsd_version="${virtiofsd_version:-}" +virtiofsd_zip="${virtiofsd_zip:-}" +package_output_dir="${package_output_dir:-}" + +[ -n "${virtiofsd_repo}" ] || virtiofsd_repo=$(get_from_kata_deps "externals.virtiofsd.url") +[ -n "${virtiofsd_version}" ] || virtiofsd_version=$(get_from_kata_deps "externals.virtiofsd.version") +[ -n "${virtiofsd_zip}" ] || virtiofsd_zip=$(get_from_kata_deps "externals.virtiofsd.meta.binary") + +[ -n "${virtiofsd_repo}" ] || die "Failed to get virtiofsd repo" +[ -n "${virtiofsd_version}" ] || die "Failed to get virtiofsd version or commit" +[ -n "${virtiofsd_zip}" ] || die "Failed to get virtiofsd binary URL" + +ARCH=$(uname -m) +case ${ARCH} in + "aarch64") + libc="musl" + ;; + "ppc64le") + libc="gnu" + ;; + "s390x") + libc="gnu" + ;; + "x86_64") + libc="musl" + ;; +esac + +sudo docker build \ + -t "${container_image}" "${script_dir}/${libc}" + +sudo docker run --rm -i -v "${repo_root_dir}:${repo_root_dir}" \ + -w "${PWD}" \ + --env DESTDIR="${DESTDIR}" \ + --env PREFIX="${PREFIX}" \ + --env virtiofsd_repo="${virtiofsd_repo}" \ + --env virtiofsd_version="${virtiofsd_version}" \ + --env virtiofsd_zip="${virtiofsd_zip}" \ + "${container_image}" \ + bash -c "${virtiofsd_builder}" diff --git a/tools/packaging/static-build/virtiofsd/gnu/Dockerfile b/tools/packaging/static-build/virtiofsd/gnu/Dockerfile new file mode 100644 index 0000000000..c214dfc415 --- /dev/null +++ b/tools/packaging/static-build/virtiofsd/gnu/Dockerfile @@ -0,0 +1,19 @@ +# Copyright (c) 2022 Intel +# +# SPDX-License-Identifier: Apache-2.0 + +FROM ubuntu:20.04 +ENV DEBIAN_FRONTEND=noninteractive +SHELL ["/bin/bash", "-o", "pipefail", "-c"] + +RUN apt-get update && \ + apt-get install -y --no-install-recommends \ + build-essential \ + ca-certificates \ + curl \ + git \ + libcap-ng-dev \ + libseccomp-dev \ + unzip && \ + apt-get clean && rm -rf /var/lib/lists/ && \ + curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y diff --git a/tools/packaging/static-build/virtiofsd/musl/Dockerfile b/tools/packaging/static-build/virtiofsd/musl/Dockerfile new file mode 100644 index 0000000000..9b9bb93b90 --- /dev/null +++ b/tools/packaging/static-build/virtiofsd/musl/Dockerfile @@ -0,0 +1,16 @@ +# Copyright (c) 2022 Intel +# +# SPDX-License-Identifier: Apache-2.0 + +FROM alpine:3.16.2 + +SHELL ["/bin/ash", "-o", "pipefail", "-c"] +RUN apk --no-cache add \ + bash \ + curl \ + gcc \ + git \ + libcap-ng-static \ + libseccomp-static \ + musl-dev && \ + curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y From cb4ef4734fba7aaf48b4cb067b5a11ed932d809b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fabiano=20Fid=C3=AAncio?= Date: Fri, 14 Oct 2022 10:56:26 +0200 Subject: [PATCH 37/42] snap: Create a task for installing docker MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Let's have the docker installation / configuration as part of its own task, which can be set as a dependency of other tasks whcih may or may not depend on docker. Signed-off-by: Fabiano Fidêncio --- snap/snapcraft.yaml | 51 ++++++++++++++++++++++++++------------------- 1 file changed, 30 insertions(+), 21 deletions(-) diff --git a/snap/snapcraft.yaml b/snap/snapcraft.yaml index b6ac1338db..e27783aefd 100644 --- a/snap/snapcraft.yaml +++ b/snap/snapcraft.yaml @@ -82,8 +82,36 @@ parts: fi rustup component add rustfmt + docker: + after: [metadata] + plugin: nil + prime: + - -* + build-packages: + - curl + override-build: | + source "${SNAPCRAFT_PROJECT_DIR}/snap/local/snap-common.sh" + + sudo apt-get -y update + sudo apt-get -y install ca-certificates curl gnupg lsb-release + curl -fsSL https://download.docker.com/linux/ubuntu/gpg |\ + sudo gpg --batch --yes --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg + distro_codename=$(lsb_release -cs) + echo "deb [arch=${dpkg_arch} signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/ubuntu ${distro_codename} stable" |\ + sudo tee /etc/apt/sources.list.d/docker.list > /dev/null + sudo apt-get -y update + sudo apt-get -y install docker-ce docker-ce-cli containerd.io + + echo "Unmasking docker service" + sudo -E systemctl unmask docker.service || true + sudo -E systemctl unmask docker.socket || true + echo "Adding $USER into docker group" + sudo -E gpasswd -a $USER docker + echo "Starting docker" + sudo -E systemctl start docker || true + image: - after: [godeps, qemu, kernel] + after: [godeps, docker, qemu, kernel] plugin: nil build-packages: - docker.io @@ -107,14 +135,6 @@ parts: # Copy yq binary. It's used in the container cp -a "${yq}" "${GOPATH}/bin/" - echo "Unmasking docker service" - sudo -E systemctl unmask docker.service || true - sudo -E systemctl unmask docker.socket || true - echo "Adding $USER into docker group" - sudo -E gpasswd -a $USER docker - echo "Starting docker" - sudo -E systemctl start docker || true - cd "${kata_dir}/tools/osbuilder" # build image @@ -333,22 +353,11 @@ parts: cloud-hypervisor: plugin: nil - after: [godeps] + after: [godeps, docker] override-build: | source "${SNAPCRAFT_PROJECT_DIR}/snap/local/snap-common.sh" if [ "${arch}" == "aarch64" ] || [ "${arch}" == "x86_64" ]; then - sudo apt-get -y update - sudo apt-get -y install ca-certificates curl gnupg lsb-release - curl -fsSL https://download.docker.com/linux/ubuntu/gpg |\ - sudo gpg --batch --yes --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg - distro_codename=$(lsb_release -cs) - echo "deb [arch=${dpkg_arch} signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/ubuntu ${distro_codename} stable" |\ - sudo tee /etc/apt/sources.list.d/docker.list > /dev/null - sudo apt-get -y update - sudo apt-get -y install docker-ce docker-ce-cli containerd.io - sudo systemctl start docker.socket - cd "${SNAPCRAFT_PROJECT_DIR}" sudo -E NO_TTY=true make cloud-hypervisor-tarball From 0bc5baafb9481822449f34fce08b3b2ca5fd9319 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fabiano=20Fid=C3=AAncio?= Date: Fri, 14 Oct 2022 10:58:31 +0200 Subject: [PATCH 38/42] snap: Build virtiofsd using the kata-deploy scripts MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Let's build virtiofsd using the kata-deploy build scripts, which simplifies and unifies the way we build our components. Signed-off-by: Fabiano Fidêncio --- snap/snapcraft.yaml | 24 ++++++------------------ 1 file changed, 6 insertions(+), 18 deletions(-) diff --git a/snap/snapcraft.yaml b/snap/snapcraft.yaml index e27783aefd..a2fdcc0ba2 100644 --- a/snap/snapcraft.yaml +++ b/snap/snapcraft.yaml @@ -321,35 +321,23 @@ parts: virtiofsd: plugin: nil - after: [godeps, rustdeps] + after: [godeps, rustdeps, docker] override-build: | source "${SNAPCRAFT_PROJECT_DIR}/snap/local/snap-common.sh" - # Currently, powerpc makes use of the QEMU's C implementation. - # The other platforms make use of the new rust virtiofsd. - # - # See "tools/packaging/scripts/configure-hypervisor.sh". - if [ "${arch}" == "ppc64le" ] - then - echo "INFO: Building QEMU's C version of virtiofsd" - # Handled by the 'qemu' part, so nothing more to do here. - exit 0 - else - echo "INFO: Building rust version of virtiofsd" - fi + echo "INFO: Building rust version of virtiofsd" - cd "${kata_dir}" + cd "${SNAPCRAFT_PROJECT_DIR}" + # Clean-up build dir in case it already exists + sudo -E NO_TTY=true make virtiofsd-tarball - export PATH=${PATH}:${HOME}/.cargo/bin - # Download the rust implementation of virtiofsd - tools/packaging/static-build/virtiofsd/build-static-virtiofsd.sh sudo install \ --owner='root' \ --group='root' \ --mode=0755 \ -D \ --target-directory="${SNAPCRAFT_PART_INSTALL}/usr/libexec/" \ - virtiofsd/virtiofsd + build/virtiofsd/builddir/virtiofsd/virtiofsd cloud-hypervisor: plugin: nil From c322d1d12a9a949233dbfc411d9426537f99db6d Mon Sep 17 00:00:00 2001 From: "James O. D. Hunt" Date: Sat, 15 Oct 2022 11:40:31 +0100 Subject: [PATCH 39/42] kata-ctl: arch: Improve check call Rework the architecture-specific `check()` call by moving all the conditional logic out of the function. Fixes: #5402. Signed-off-by: James O. D. Hunt --- src/tools/kata-ctl/src/arch/mod.rs | 38 +++++++++++++----------------- 1 file changed, 17 insertions(+), 21 deletions(-) diff --git a/src/tools/kata-ctl/src/arch/mod.rs b/src/tools/kata-ctl/src/arch/mod.rs index e72bcc4537..b85811a0ca 100644 --- a/src/tools/kata-ctl/src/arch/mod.rs +++ b/src/tools/kata-ctl/src/arch/mod.rs @@ -7,36 +7,32 @@ use anyhow::Result; #[cfg(target_arch = "aarch64")] pub mod aarch64; +#[cfg(target_arch = "aarch64")] +pub use aarch64 as arch_specific; #[cfg(target_arch = "powerpc64le")] pub mod powerpc64le; +#[cfg(target_arch = "powerpc64le")] +pub use powerpc64le as arch_specific; #[cfg(target_arch = "s390x")] pub mod s390x; +#[cfg(target_arch = "s390x")] +pub use s390x as arch_specific; #[cfg(target_arch = "x86_64")] pub mod x86_64; +#[cfg(target_arch = "x86_64")] +pub use x86_64 as arch_specific; + +#[cfg(not(any( + target_arch = "aarch64", + target_arch = "powerpc64le", + target_arch = "s390x", + target_arch = "x86_64" +)))] +compile_error!("unknown architecture"); pub fn check() -> Result<()> { - #[cfg(target_arch = "aarch64")] - let result = aarch64::check(); - - #[cfg(target_arch = "powerpc64le")] - let result = powerpc64le::check(); - - #[cfg(target_arch = "s390x")] - let result = s390x::check(); - - #[cfg(target_arch = "x86_64")] - let result = x86_64::check(); - - #[cfg(not(any( - target_arch = "aarch64", - target_arch = "powerpc64le", - target_arch = "s390x", - target_arch = "x86_64" - )))] - compile_error!("unknown architecture"); - - result + arch_specific::check() } From 00981b3c0a705e26691e519e4062689a1d6a258a Mon Sep 17 00:00:00 2001 From: "James O. D. Hunt" Date: Sat, 15 Oct 2022 12:07:05 +0100 Subject: [PATCH 40/42] kata-ctl: Disable network check on s390x s390x apparently does not support rust-tls, which is required by the network check (due to the `reqwest` crate dependency). Disable the network check on s390x until we can find a solution to the problem. > **Note:** > > This fix is assumed to be a temporary one until we find a solution. > Hence, I have not moved the network check code (which should be entirely > generic) into an architecture specific module. Fixes: #5435. Signed-off-by: James O. D. Hunt --- src/tools/kata-ctl/Cargo.toml | 5 ++- src/tools/kata-ctl/src/check.rs | 46 +++++++++++++++++++++++++ src/tools/kata-ctl/src/ops/check_ops.rs | 9 +++++ 3 files changed, 59 insertions(+), 1 deletion(-) diff --git a/src/tools/kata-ctl/Cargo.toml b/src/tools/kata-ctl/Cargo.toml index 094613c343..b92491ecd9 100644 --- a/src/tools/kata-ctl/Cargo.toml +++ b/src/tools/kata-ctl/Cargo.toml @@ -12,9 +12,12 @@ edition = "2018" [dependencies] anyhow = "1.0.31" clap = { version = "3.2.20", features = ["derive", "cargo"] } -reqwest = { version = "0.11", default-features = false, features = ["json", "blocking", "rustls-tls"] } serde_json = "1.0.85" thiserror = "1.0.35" +# See: https://github.com/kata-containers/kata-containers/issues/5438 +[target.'cfg(not(target_arch = "s390x"))'.dependencies] +reqwest = { version = "0.11", default-features = false, features = ["json", "blocking", "rustls-tls"] } + [dev-dependencies] semver = "1.0.12" diff --git a/src/tools/kata-ctl/src/check.rs b/src/tools/kata-ctl/src/check.rs index 28febb307c..2dbadeb545 100644 --- a/src/tools/kata-ctl/src/check.rs +++ b/src/tools/kata-ctl/src/check.rs @@ -6,8 +6,19 @@ // Contains checks that are not architecture-specific use anyhow::{anyhow, Result}; +// See: https://github.com/kata-containers/kata-containers/issues/5438 +#[cfg(any( + target_arch = "aarch64", + target_arch = "powerpc64le", + target_arch = "x86_64" +))] use reqwest::header::{CONTENT_TYPE, USER_AGENT}; use serde_json::Value; +#[cfg(any( + target_arch = "aarch64", + target_arch = "powerpc64le", + target_arch = "x86_64" +))] use std::collections::HashMap; use std::fs; @@ -99,6 +110,11 @@ pub fn run_network_checks() -> Result<()> { Ok(()) } +#[cfg(any( + target_arch = "aarch64", + target_arch = "powerpc64le", + target_arch = "x86_64" +))] fn get_kata_version_by_url(url: &str) -> std::result::Result { let content = reqwest::blocking::Client::new() .get(url) @@ -111,6 +127,11 @@ fn get_kata_version_by_url(url: &str) -> std::result::Result anyhow::Error { if e.is_connect() { return anyhow!(e).context("http connection failure: connection refused"); @@ -131,6 +152,11 @@ fn handle_reqwest_error(e: reqwest::Error) -> anyhow::Error { anyhow!(e).context("unknown http connection failure: {:?}") } +#[cfg(any( + target_arch = "aarch64", + target_arch = "powerpc64le", + target_arch = "x86_64" +))] pub fn check_version() -> Result<()> { let version = get_kata_version_by_url(KATA_GITHUB_URL).map_err(handle_reqwest_error)?; @@ -164,6 +190,11 @@ mod tests { assert_eq!(expected, actual); } + #[cfg(any( + target_arch = "aarch64", + target_arch = "powerpc64le", + target_arch = "x86_64" + ))] #[test] fn check_version_by_empty_url() { const TEST_URL: &str = "http:"; @@ -172,6 +203,11 @@ mod tests { assert_eq!(expected, actual); } + #[cfg(any( + target_arch = "aarch64", + target_arch = "powerpc64le", + target_arch = "x86_64" + ))] #[test] fn check_version_by_garbage_url() { const TEST_URL: &str = "_localhost_"; @@ -180,6 +216,11 @@ mod tests { assert_eq!(expected, actual); } + #[cfg(any( + target_arch = "aarch64", + target_arch = "powerpc64le", + target_arch = "x86_64" + ))] #[test] fn check_version_by_invalid_url() { const TEST_URL: &str = "http://localhost :80"; @@ -188,6 +229,11 @@ mod tests { assert_eq!(expected, actual); } + #[cfg(any( + target_arch = "aarch64", + target_arch = "powerpc64le", + target_arch = "x86_64" + ))] #[test] fn check_latest_version() { let version = get_kata_version_by_url(KATA_GITHUB_URL).unwrap(); diff --git a/src/tools/kata-ctl/src/ops/check_ops.rs b/src/tools/kata-ctl/src/ops/check_ops.rs index b97cb6b05d..80556894c8 100644 --- a/src/tools/kata-ctl/src/ops/check_ops.rs +++ b/src/tools/kata-ctl/src/ops/check_ops.rs @@ -32,7 +32,16 @@ pub fn handle_check(checkcmd: CheckArgument) -> Result<()> { CheckSubCommand::CheckVersionOnly => { // retrieve latest release + #[cfg(any( + target_arch = "aarch64", + target_arch = "powerpc64le", + target_arch = "x86_64" + ))] check::check_version()?; + + // See: https://github.com/kata-containers/kata-containers/issues/5438 + #[cfg(target_arch = "s390x")] + unimplemented!("Network check not implemented on s390x") } } From ac403cfa5a84e1132d6c56dc2fd3007a57dbe562 Mon Sep 17 00:00:00 2001 From: Zvonko Kaiser Date: Thu, 13 Oct 2022 10:39:49 +0200 Subject: [PATCH 41/42] doc: Update how-to-run-kata-containers-with-SNP-VMs.md If the needed libraries (for virtfs) are installed on the host, QEMU will pick it up and enable it. If not installed and you do not enable the flag, QEMU will just ignore it, and you end up without 9p support. Enabling it explicitly will fail if the needed libs are not installed so this way we can be sure that it gets build. Fixes: #5418 Signed-off-by: Zvonko Kaiser --- docs/how-to/how-to-run-kata-containers-with-SNP-VMs.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/how-to/how-to-run-kata-containers-with-SNP-VMs.md b/docs/how-to/how-to-run-kata-containers-with-SNP-VMs.md index bc4e14a10d..a87c9be62b 100644 --- a/docs/how-to/how-to-run-kata-containers-with-SNP-VMs.md +++ b/docs/how-to/how-to-run-kata-containers-with-SNP-VMs.md @@ -50,7 +50,7 @@ $ qemu_commit="$(get_from_kata_deps "assets.hypervisor.qemu.snp.commit")" $ git clone -b "${qemu_branch}" "${qemu_url}" $ pushd qemu $ git checkout "${qemu_commit}" -$ ./configure --target-list=x86_64-softmmu --enable-debug +$ ./configure --enable-virtfs --target-list=x86_64-softmmu --enable-debug $ make -j "$(nproc)" $ popd ``` From f205472b01bf32f604bc100dc890670d6a37109f Mon Sep 17 00:00:00 2001 From: Chao Wu Date: Wed, 19 Oct 2022 12:12:50 +0800 Subject: [PATCH 42/42] Makefile: regulate the comment style for the runtime-rs comments In runtime-rs makefile, we use ``` ``` to let make help print out help information for variables and targets, but later commits forgot this rule. So we need to follow the previous rule and change the current comments. fixes: #5413 Signed-off-by: Chao Wu --- src/runtime-rs/Makefile | 31 +++++++++++++++---------------- 1 file changed, 15 insertions(+), 16 deletions(-) diff --git a/src/runtime-rs/Makefile b/src/runtime-rs/Makefile index 482517b3d7..b04f778808 100644 --- a/src/runtime-rs/Makefile +++ b/src/runtime-rs/Makefile @@ -31,7 +31,7 @@ test: else ##TARGET default: build code default: runtime show-header -#TARGET test: run cargo tests +##TARGET test: run cargo tests test: @cargo test --all --target $(TRIPLE) $(EXTRA_RUSTFEATURES) -- --nocapture endif @@ -50,7 +50,6 @@ EXEC_PREFIX := $(PREFIX)/local BINDIR := $(EXEC_PREFIX)/bin else EXEC_PREFIX := $(PREFIX) -##VAR BINDIR= is a directory for installing executable programs # when creating the kata-deploy image, the default installation path for go runtime is $(EXEC_PREFIX)/bin, so we put it here for multiple runtime BINDIR := $(EXEC_PREFIX)/runtime-rs/bin/ endif @@ -73,7 +72,7 @@ HYPERVISOR_CLH = cloud-hypervisor DEFAULT_HYPERVISOR ?= $(HYPERVISOR_DB) -# List of hypervisors this build system can generate configuration for. +##VAR HYPERVISOR= List of hypervisors this build system can generate configuration for. HYPERVISORS := $(HYPERVISOR_DB) $(HYPERVISOR_ACRN) $(HYPERVISOR_FC) $(HYPERVISOR_QEMU) $(HYPERVISOR_CLH) DBVALIDHYPERVISORPATHS := [] @@ -84,28 +83,28 @@ PKGLIBEXECDIR := $(LIBEXECDIR)/$(PROJECT_DIR) FIRMWAREPATH := FIRMWAREVOLUMEPATH := -# Default number of vCPUs +##VAR DEFVCPUS= Default number of vCPUs DEFVCPUS := 1 -# Default maximum number of vCPUs +##VAR DEFMAXVCPUS= Default maximum number of vCPUs DEFMAXVCPUS := 0 -# Default memory size in MiB +##VAR DEFMEMSZ= Default memory size in MiB DEFMEMSZ := 2048 -# Default memory slots +##VAR DEFMEMSLOTS= Default memory slots # Cases to consider : # - nvdimm rootfs image # - preallocated memory # - vm template memory # - hugepage memory DEFMEMSLOTS := 10 -#Default number of bridges +##VAR DEFBRIDGES= Default number of bridges DEFBRIDGES := 0 DEFENABLEANNOTATIONS := [] DEFDISABLEGUESTSECCOMP := true DEFDISABLEGUESTEMPTYDIR := false -#Default experimental features enabled +##VAR DEFAULTEXPFEATURES=[features] Default experimental features enabled DEFAULTEXPFEATURES := [] DEFDISABLESELINUX := false -#Default entropy source +##VAR DEFENTROPYSOURCE=[entropy_source] Default entropy source DEFENTROPYSOURCE := /dev/urandom DEFVALIDENTROPYSOURCES := [\"/dev/urandom\",\"/dev/random\",\"\"] DEFDISABLEBLOCK := false @@ -116,8 +115,8 @@ ifeq ($(ARCH),x86_64) DEFVIRTIOFSDAEMON := $(LIBEXECDIR)/virtiofsd endif DEFVALIDVIRTIOFSDAEMONPATHS := [\"$(DEFVIRTIOFSDAEMON)\"] -# Default DAX mapping cache size in MiB -#if value is 0, DAX is not enabled +##VAR DEFVIRTIOFSCACHESIZE= Default DAX mapping cache size in MiB +# if value is 0, DAX is not enabled DEFVIRTIOFSCACHESIZE ?= 0 DEFVIRTIOFSCACHE ?= auto # Format example: @@ -134,7 +133,7 @@ DEFFILEMEMBACKEND := "" DEFVALIDFILEMEMBACKENDS := [\"$(DEFFILEMEMBACKEND)\"] DEFMSIZE9P := 8192 DEFVFIOMODE := guest-kernel -# Default cgroup model +##VAR DEFSANDBOXCGROUPONLY= Default cgroup model DEFSANDBOXCGROUPONLY ?= false DEFSTATICRESOURCEMGMT_DB ?= false DEFBINDMOUNTS := [] @@ -160,9 +159,9 @@ KNOWN_HYPERVISORS = CONFDIR := $(DEFAULTSDIR)/$(PROJECT_DIR) SYSCONFDIR := $(SYSCONFDIR)/$(PROJECT_DIR) -# Main configuration file location for stateless systems +##VAR CONFIG_PATH= Main configuration file location for stateless systems CONFIG_PATH := $(abspath $(CONFDIR)/$(CONFIG_FILE)) -# Secondary configuration file location. Note that this takes precedence +##VAR SYSCONFIG= Secondary configuration file location. Note that this takes precedence # over CONFIG_PATH. SYSCONFIG := $(abspath $(SYSCONFDIR)/$(CONFIG_FILE)) SHAREDIR := $(SHAREDIR) @@ -454,7 +453,7 @@ endif @printf "\tassets path (PKGDATADIR) : %s\n" $(abspath $(PKGDATADIR)) @printf "\tshim path (PKGLIBEXECDIR) : %s\n" $(abspath $(PKGLIBEXECDIR)) @printf "\n" -## help: Show help comments that start with `##VAR` and `##TARGET` +##TARGET help: Show help comments that start with `##VAR` and `##TARGET` in runtime-rs makefile help: Makefile show-summary @echo "========================== Help =============================" @echo "Variables:"