diff --git a/src/runtime-rs/crates/hypervisor/src/lib.rs b/src/runtime-rs/crates/hypervisor/src/lib.rs index 6b499d0bac..23697eaf25 100644 --- a/src/runtime-rs/crates/hypervisor/src/lib.rs +++ b/src/runtime-rs/crates/hypervisor/src/lib.rs @@ -14,6 +14,7 @@ pub mod hypervisor_persist; pub use device::*; pub mod dragonball; mod kernel_param; +pub mod qemu; pub use kernel_param::Param; mod utils; use std::collections::HashMap; @@ -28,6 +29,8 @@ const VM_ROOTFS_DRIVER_BLK: &str = "virtio-blk"; const VM_ROOTFS_DRIVER_PMEM: &str = "virtio-pmem"; pub const HYPERVISOR_DRAGONBALL: &str = "dragonball"; +pub const HYPERVISOR_QEMU: &str = "qemu"; + #[derive(PartialEq)] pub(crate) enum VmmState { NotReady, diff --git a/src/runtime-rs/crates/hypervisor/src/qemu/inner.rs b/src/runtime-rs/crates/hypervisor/src/qemu/inner.rs new file mode 100644 index 0000000000..a290855136 --- /dev/null +++ b/src/runtime-rs/crates/hypervisor/src/qemu/inner.rs @@ -0,0 +1,125 @@ +// Copyright (c) 2022 Red Hat +// +// SPDX-License-Identifier: Apache-2.0 +// + +use anyhow::Result; + +use crate::{HypervisorConfig, VcpuThreadIds}; +use kata_types::capabilities::{Capabilities, CapabilityBits}; + +const VSOCK_SCHEME: &str = "vsock"; +const VSOCK_AGENT_CID: u32 = 3; +const VSOCK_AGENT_PORT: u32 = 1024; + +unsafe impl Send for QemuInner {} +unsafe impl Sync for QemuInner {} + +pub struct QemuInner { + config: HypervisorConfig, +} + +impl QemuInner { + pub fn new() -> QemuInner { + QemuInner { + config: Default::default(), + } + } + + pub(crate) async fn prepare_vm(&mut self, _id: &str, _netns: Option) -> Result<()> { + info!(sl!(), "Preparing QEMU VM"); + Ok(()) + } + + pub(crate) async fn start_vm(&mut self, _timeout: i32) -> Result<()> { + info!(sl!(), "Starting QEMU VM"); + Ok(()) + } + + pub(crate) fn stop_vm(&mut self) -> Result<()> { + info!(sl!(), "Stopping QEMU VM"); + todo!() + } + + pub(crate) fn pause_vm(&self) -> Result<()> { + info!(sl!(), "Pausing QEMU VM"); + todo!() + } + + pub(crate) fn resume_vm(&self) -> Result<()> { + info!(sl!(), "Resuming QEMU VM"); + todo!() + } + + pub(crate) async fn save_vm(&self) -> Result<()> { + todo!() + } + + /// TODO: using a single hardcoded CID is clearly not adequate in the long + /// run. Use the recently added VsockConfig infrastructure to fix this. + pub(crate) async fn get_agent_socket(&self) -> Result { + info!(sl!(), "QemuInner::get_agent_socket()"); + Ok(format!( + "{}://{}:{}", + VSOCK_SCHEME, VSOCK_AGENT_CID, VSOCK_AGENT_PORT + )) + } + + pub(crate) async fn disconnect(&mut self) { + info!(sl!(), "QemuInner::disconnect()"); + todo!() + } + + pub(crate) async fn get_thread_ids(&self) -> Result { + info!(sl!(), "QemuInner::get_thread_ids()"); + todo!() + } + + pub(crate) async fn cleanup(&self) -> Result<()> { + info!(sl!(), "QemuInner::cleanup()"); + todo!() + } + + pub(crate) async fn get_pids(&self) -> Result> { + info!(sl!(), "QemuInner::get_pids()"); + todo!() + } + + pub(crate) async fn check(&self) -> Result<()> { + todo!() + } + + pub(crate) async fn get_jailer_root(&self) -> Result { + todo!() + } + + pub(crate) async fn capabilities(&self) -> Result { + let mut caps = Capabilities::default(); + caps.set(CapabilityBits::FsSharingSupport); + Ok(caps) + } + + pub fn set_hypervisor_config(&mut self, config: HypervisorConfig) { + self.config = config; + } + + pub fn hypervisor_config(&self) -> HypervisorConfig { + info!(sl!(), "QemuInner::hypervisor_config()"); + self.config.clone() + } +} + +use crate::device::Device; + +// device manager part of Hypervisor +impl QemuInner { + pub(crate) async fn add_device(&mut self, device: Device) -> Result<()> { + info!(sl!(), "QemuInner::add_device() {}", device); + todo!() + } + + pub(crate) async fn remove_device(&mut self, device: Device) -> Result<()> { + info!(sl!(), "QemuInner::remove_device() {} ", device); + todo!() + } +} diff --git a/src/runtime-rs/crates/hypervisor/src/qemu/mod.rs b/src/runtime-rs/crates/hypervisor/src/qemu/mod.rs new file mode 100644 index 0000000000..6df3869236 --- /dev/null +++ b/src/runtime-rs/crates/hypervisor/src/qemu/mod.rs @@ -0,0 +1,134 @@ +// Copyright (c) 2022 Red Hat +// +// SPDX-License-Identifier: Apache-2.0 +// + +mod inner; + +use crate::device::Device; +use crate::hypervisor_persist::HypervisorState; +use crate::Hypervisor; +use crate::{HypervisorConfig, VcpuThreadIds}; +use inner::QemuInner; +use kata_types::capabilities::Capabilities; + +use anyhow::Result; +use async_trait::async_trait; + +use std::sync::Arc; +use tokio::sync::RwLock; + +pub struct Qemu { + inner: Arc>, +} + +impl Default for Qemu { + fn default() -> Self { + Self::new() + } +} + +impl Qemu { + pub fn new() -> Self { + Self { + inner: Arc::new(RwLock::new(QemuInner::new())), + } + } + + pub async fn set_hypervisor_config(&mut self, config: HypervisorConfig) { + let mut inner = self.inner.write().await; + inner.set_hypervisor_config(config) + } +} + +#[async_trait] +impl Hypervisor for Qemu { + async fn prepare_vm(&self, id: &str, netns: Option) -> Result<()> { + let mut inner = self.inner.write().await; + inner.prepare_vm(id, netns).await + } + + async fn start_vm(&self, timeout: i32) -> Result<()> { + let mut inner = self.inner.write().await; + inner.start_vm(timeout).await + } + + async fn stop_vm(&self) -> Result<()> { + let mut inner = self.inner.write().await; + inner.stop_vm() + } + + async fn pause_vm(&self) -> Result<()> { + let inner = self.inner.read().await; + inner.pause_vm() + } + + async fn resume_vm(&self) -> Result<()> { + let inner = self.inner.read().await; + inner.resume_vm() + } + + async fn save_vm(&self) -> Result<()> { + let inner = self.inner.read().await; + inner.save_vm().await + } + + async fn add_device(&self, device: Device) -> Result<()> { + let mut inner = self.inner.write().await; + inner.add_device(device).await + } + + async fn remove_device(&self, device: Device) -> Result<()> { + let mut inner = self.inner.write().await; + inner.remove_device(device).await + } + + async fn get_agent_socket(&self) -> Result { + let inner = self.inner.read().await; + inner.get_agent_socket().await + } + + async fn disconnect(&self) { + let mut inner = self.inner.write().await; + inner.disconnect().await + } + + async fn hypervisor_config(&self) -> HypervisorConfig { + let inner = self.inner.read().await; + inner.hypervisor_config() + } + + async fn get_thread_ids(&self) -> Result { + let inner = self.inner.read().await; + inner.get_thread_ids().await + } + + async fn cleanup(&self) -> Result<()> { + let inner = self.inner.read().await; + inner.cleanup().await + } + + async fn get_pids(&self) -> Result> { + let inner = self.inner.read().await; + inner.get_pids().await + } + + async fn check(&self) -> Result<()> { + let inner = self.inner.read().await; + inner.check().await + } + + async fn get_jailer_root(&self) -> Result { + let inner = self.inner.read().await; + inner.get_jailer_root().await + } + + async fn save_state(&self) -> Result { + todo!() + } + + async fn capabilities(&self) -> Result { + let inner = self.inner.read().await; + inner.capabilities().await + } +}