mirror of
https://github.com/aljazceru/kata-containers.git
synced 2025-12-19 07:14:22 +01:00
runtime-rs: support loading kernel modules in guest vm
Users can specify the kernel module to be loaded through the agent configuration in kata configuration file or in pod anotation file. And information of those modules will be sent to kata agent when sandbox is created. Fixes: #4894 Signed-off-by: Yushuo <y-shuo@linux.alibaba.com>
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());
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user