mirror of
https://github.com/aljazceru/kata-containers.git
synced 2025-12-17 14:24:27 +01:00
Merge pull request #4892 from openanolis/shuoyu/runtime-rs
runtime-rs: support loading kernel modules in guest vm
This commit is contained in:
@@ -8,6 +8,8 @@ use anyhow::{Context, Result};
|
||||
use async_trait::async_trait;
|
||||
use ttrpc::context as ttrpc_ctx;
|
||||
|
||||
use kata_types::config::Agent as AgentConfig;
|
||||
|
||||
use crate::{kata::KataAgent, Agent, AgentManager, HealthService};
|
||||
|
||||
/// millisecond to nanosecond
|
||||
@@ -37,6 +39,10 @@ impl AgentManager for KataAgent {
|
||||
async fn stop(&self) {
|
||||
self.stop_log_forwarder().await;
|
||||
}
|
||||
|
||||
async fn agent_config(&self) -> AgentConfig {
|
||||
self.agent_config().await
|
||||
}
|
||||
}
|
||||
|
||||
// implement for health service
|
||||
|
||||
@@ -126,4 +126,9 @@ impl KataAgent {
|
||||
let mut inner = self.inner.lock().await;
|
||||
inner.log_forwarder.stop();
|
||||
}
|
||||
|
||||
pub(crate) async fn agent_config(&self) -> AgentConfig {
|
||||
let inner = self.inner.lock().await;
|
||||
inner.config.clone()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -29,10 +29,16 @@ pub use types::{
|
||||
use anyhow::Result;
|
||||
use async_trait::async_trait;
|
||||
|
||||
use kata_types::config::Agent as AgentConfig;
|
||||
|
||||
pub const AGENT_KATA: &str = "kata";
|
||||
|
||||
#[async_trait]
|
||||
pub trait AgentManager: Send + Sync {
|
||||
async fn start(&self, address: &str) -> Result<()>;
|
||||
async fn stop(&self);
|
||||
|
||||
async fn agent_config(&self) -> AgentConfig;
|
||||
}
|
||||
|
||||
#[async_trait]
|
||||
|
||||
@@ -4,6 +4,9 @@
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
//
|
||||
|
||||
use anyhow::{anyhow, Result};
|
||||
use std::convert::TryFrom;
|
||||
|
||||
use serde::Deserialize;
|
||||
|
||||
#[derive(PartialEq, Clone, Default)]
|
||||
@@ -390,6 +393,56 @@ pub struct KernelModule {
|
||||
pub parameters: Vec<String>,
|
||||
}
|
||||
|
||||
impl KernelModule {
|
||||
pub fn set_kernel_modules(modules: Vec<String>) -> Result<Vec<Self>> {
|
||||
let mut kernel_modules = Vec::new();
|
||||
for module_string in modules {
|
||||
if module_string.is_empty() {
|
||||
continue;
|
||||
}
|
||||
let kernel_module = Self::try_from(module_string)?;
|
||||
kernel_modules.push(kernel_module);
|
||||
}
|
||||
Ok(kernel_modules)
|
||||
}
|
||||
}
|
||||
|
||||
impl TryFrom<String> for KernelModule {
|
||||
type Error = anyhow::Error;
|
||||
// input string: " ModuleName Param1 Param2 ... "
|
||||
// NOTICE: " ModuleName Param1="spaces in here" " => KernelModule { name: ModuleName, parameters: Param1="spaces in here" }
|
||||
fn try_from(str: String) -> Result<Self> {
|
||||
let split: Vec<&str> = str.split(' ').collect();
|
||||
let mut name = String::new();
|
||||
let mut parameters = Vec::new();
|
||||
|
||||
let mut flag = false;
|
||||
for (index, info) in split.iter().enumerate() {
|
||||
if index == 0 {
|
||||
name = info.to_string();
|
||||
} else if flag {
|
||||
// a former param's string contains \"
|
||||
if let Some(former_param) = parameters.pop() {
|
||||
let cur_param = format!("{} {}", former_param, info);
|
||||
parameters.push(cur_param);
|
||||
}
|
||||
} else {
|
||||
parameters.push(info.to_string());
|
||||
}
|
||||
|
||||
if info.contains('\"') {
|
||||
flag = !flag;
|
||||
}
|
||||
}
|
||||
|
||||
if flag {
|
||||
return Err(anyhow!("\" not match"));
|
||||
}
|
||||
|
||||
Ok(KernelModule { name, parameters })
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(PartialEq, Clone, Default)]
|
||||
pub struct CreateSandboxRequest {
|
||||
pub hostname: String,
|
||||
@@ -486,3 +539,44 @@ pub struct VersionCheckResponse {
|
||||
pub struct OomEventResponse {
|
||||
pub container_id: String,
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use std::convert::TryFrom;
|
||||
|
||||
use super::KernelModule;
|
||||
|
||||
#[test]
|
||||
fn test_new_kernel_module() {
|
||||
let kernel_module_str1 = "ModuleName Param1 Param2";
|
||||
let kernel_module1 = KernelModule::try_from(kernel_module_str1.to_string()).unwrap();
|
||||
assert!(kernel_module1.name == "ModuleName");
|
||||
assert!(kernel_module1.parameters[0] == "Param1");
|
||||
assert!(kernel_module1.parameters[1] == "Param2");
|
||||
|
||||
let kernel_module_str2 = "ModuleName Param1=\"spaces in here\"";
|
||||
let kernel_module2 = KernelModule::try_from(kernel_module_str2.to_string()).unwrap();
|
||||
assert!(kernel_module2.name == "ModuleName");
|
||||
assert!(kernel_module2.parameters[0] == "Param1=\"spaces in here\"");
|
||||
|
||||
// exception case
|
||||
let kernel_module_str3 = "ModuleName \"Param1";
|
||||
let kernel_module3 = KernelModule::try_from(kernel_module_str3.to_string());
|
||||
assert!(kernel_module3.is_err());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_kernel_modules() {
|
||||
let kernel_module_str1 = "ModuleName1 Param1 Param2".to_string();
|
||||
let kernel_module_str2 = "".to_string();
|
||||
let kernel_module_str3 = "ModuleName2".to_string();
|
||||
let kernel_modules_str = vec![kernel_module_str1, kernel_module_str2, kernel_module_str3];
|
||||
|
||||
let kernel_modules = KernelModule::set_kernel_modules(kernel_modules_str).unwrap();
|
||||
assert!(kernel_modules.len() == 2);
|
||||
assert!(kernel_modules[0].name == "ModuleName1");
|
||||
assert!(kernel_modules[0].parameters.len() == 2);
|
||||
assert!(kernel_modules[1].name == "ModuleName2");
|
||||
assert!(kernel_modules[1].parameters.is_empty());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,7 +16,7 @@ pub mod sandbox_persist;
|
||||
|
||||
use std::sync::Arc;
|
||||
|
||||
use agent::kata::KataAgent;
|
||||
use agent::{kata::KataAgent, AGENT_KATA};
|
||||
use anyhow::{anyhow, Context, Result};
|
||||
use async_trait::async_trait;
|
||||
use common::{message::Message, RuntimeHandler, RuntimeInstance};
|
||||
@@ -55,20 +55,7 @@ impl RuntimeHandler for VirtContainer {
|
||||
let hypervisor = new_hypervisor(&config).await.context("new hypervisor")?;
|
||||
|
||||
// get uds from hypervisor and get config from toml_config
|
||||
let agent = Arc::new(KataAgent::new(kata_types::config::Agent {
|
||||
debug: true,
|
||||
enable_tracing: false,
|
||||
server_port: 1024,
|
||||
log_port: 1025,
|
||||
dial_timeout_ms: 10,
|
||||
reconnect_timeout_ms: 3_000,
|
||||
request_timeout_ms: 30_000,
|
||||
health_check_request_timeout_ms: 90_000,
|
||||
kernel_modules: Default::default(),
|
||||
container_pipe_size: 0,
|
||||
debug_console_enabled: false,
|
||||
}));
|
||||
|
||||
let agent = new_agent(&config).context("new agent")?;
|
||||
let resource_manager = Arc::new(ResourceManager::new(
|
||||
sid,
|
||||
agent.clone(),
|
||||
@@ -121,3 +108,44 @@ async fn new_hypervisor(toml_config: &TomlConfig) -> Result<Arc<dyn Hypervisor>>
|
||||
_ => Err(anyhow!("Unsupported hypervisor {}", &hypervisor_name)),
|
||||
}
|
||||
}
|
||||
|
||||
fn new_agent(toml_config: &TomlConfig) -> Result<Arc<KataAgent>> {
|
||||
let agent_name = &toml_config.runtime.agent_name;
|
||||
let agent_config = toml_config
|
||||
.agent
|
||||
.get(agent_name)
|
||||
.ok_or_else(|| anyhow!("failed to get agent for {}", &agent_name))
|
||||
.context("get agent")?;
|
||||
match agent_name.as_str() {
|
||||
AGENT_KATA => {
|
||||
let agent = KataAgent::new(agent_config.clone());
|
||||
Ok(Arc::new(agent))
|
||||
}
|
||||
_ => Err(anyhow!("Unsupported agent {}", &agent_name)),
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
|
||||
use super::*;
|
||||
|
||||
fn default_toml_config_agent() -> Result<TomlConfig> {
|
||||
let config_content = r#"
|
||||
[agent.kata]
|
||||
container_pipe_size=1
|
||||
|
||||
[runtime]
|
||||
agent_name="kata"
|
||||
"#;
|
||||
TomlConfig::load(config_content).map_err(|e| anyhow!("can not load config toml: {}", e))
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_new_agent() {
|
||||
let toml_config = default_toml_config_agent().unwrap();
|
||||
|
||||
let res = new_agent(&toml_config);
|
||||
assert!(res.is_ok());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
|
||||
use std::sync::Arc;
|
||||
|
||||
use agent::{self, kata::KataAgent, Agent};
|
||||
use agent::{self, kata::KataAgent, types::KernelModule, Agent};
|
||||
use anyhow::{anyhow, Context, Result};
|
||||
use async_trait::async_trait;
|
||||
use common::{
|
||||
@@ -159,6 +159,8 @@ impl Sandbox for VirtSandbox {
|
||||
.context("setup device after start vm")?;
|
||||
|
||||
// create sandbox in vm
|
||||
let agent_config = self.agent.agent_config().await;
|
||||
let kernel_modules = KernelModule::set_kernel_modules(agent_config.kernel_modules)?;
|
||||
let req = agent::CreateSandboxRequest {
|
||||
hostname: "".to_string(),
|
||||
dns: vec![],
|
||||
@@ -175,7 +177,7 @@ impl Sandbox for VirtSandbox {
|
||||
.await
|
||||
.security_info
|
||||
.guest_hook_path,
|
||||
kernel_modules: vec![],
|
||||
kernel_modules,
|
||||
};
|
||||
|
||||
self.agent
|
||||
|
||||
Reference in New Issue
Block a user