mirror of
https://github.com/kata-containers/kata-containers.git
synced 2025-07-16 16:32:03 +00:00
Merge pull request #4892 from openanolis/shuoyu/runtime-rs
runtime-rs: support loading kernel modules in guest vm
This commit is contained in:
commit
a7e64b1ca9
1
src/agent/Cargo.lock
generated
1
src/agent/Cargo.lock
generated
@ -625,6 +625,7 @@ dependencies = [
|
||||
"futures",
|
||||
"ipnetwork",
|
||||
"kata-sys-util",
|
||||
"kata-types",
|
||||
"lazy_static",
|
||||
"libc",
|
||||
"log",
|
||||
|
@ -21,6 +21,7 @@ thiserror = "1.0.26"
|
||||
regex = "1.5.6"
|
||||
serial_test = "0.5.1"
|
||||
kata-sys-util = { path = "../libs/kata-sys-util" }
|
||||
kata-types = { path = "../libs/kata-types" }
|
||||
sysinfo = "0.23.0"
|
||||
|
||||
# Async helpers
|
||||
|
@ -12,6 +12,8 @@ use std::str::FromStr;
|
||||
use std::time;
|
||||
use tracing::instrument;
|
||||
|
||||
use kata_types::config::default::DEFAULT_AGENT_VSOCK_PORT;
|
||||
|
||||
const DEBUG_CONSOLE_FLAG: &str = "agent.debug_console";
|
||||
const DEV_MODE_FLAG: &str = "agent.devmode";
|
||||
const TRACE_MODE_OPTION: &str = "agent.trace";
|
||||
@ -28,7 +30,6 @@ const DEFAULT_LOG_LEVEL: slog::Level = slog::Level::Info;
|
||||
const DEFAULT_HOTPLUG_TIMEOUT: time::Duration = time::Duration::from_secs(3);
|
||||
const DEFAULT_CONTAINER_PIPE_SIZE: i32 = 0;
|
||||
const VSOCK_ADDR: &str = "vsock://-1";
|
||||
const VSOCK_PORT: u16 = 1024;
|
||||
|
||||
// Environment variables used for development and testing
|
||||
const SERVER_ADDR_ENV_VAR: &str = "KATA_AGENT_SERVER_ADDR";
|
||||
@ -147,7 +148,7 @@ impl Default for AgentConfig {
|
||||
debug_console_vport: 0,
|
||||
log_vport: 0,
|
||||
container_pipe_size: DEFAULT_CONTAINER_PIPE_SIZE,
|
||||
server_addr: format!("{}:{}", VSOCK_ADDR, VSOCK_PORT),
|
||||
server_addr: format!("{}:{}", VSOCK_ADDR, DEFAULT_AGENT_VSOCK_PORT),
|
||||
unified_cgroup_hierarchy: false,
|
||||
tracing: false,
|
||||
endpoints: Default::default(),
|
||||
|
@ -9,8 +9,10 @@ use crate::config::{ConfigOps, TomlConfig};
|
||||
|
||||
pub use vendor::AgentVendor;
|
||||
|
||||
use super::default::{DEFAULT_AGENT_LOG_PORT, DEFAULT_AGENT_VSOCK_PORT};
|
||||
|
||||
/// Kata agent configuration information.
|
||||
#[derive(Debug, Default, Deserialize, Serialize)]
|
||||
#[derive(Debug, Default, Deserialize, Serialize, Clone)]
|
||||
pub struct Agent {
|
||||
/// If enabled, the agent will log additional debug messages to the system log.
|
||||
#[serde(default, rename = "enable_debug")]
|
||||
@ -34,11 +36,11 @@ pub struct Agent {
|
||||
pub debug_console_enabled: bool,
|
||||
|
||||
/// Agent server port
|
||||
#[serde(default)]
|
||||
#[serde(default = "default_server_port")]
|
||||
pub server_port: u32,
|
||||
|
||||
/// Agent log port
|
||||
#[serde(default)]
|
||||
#[serde(default = "default_log_port")]
|
||||
pub log_port: u32,
|
||||
|
||||
/// Agent connection dialing timeout value in millisecond
|
||||
@ -75,23 +77,31 @@ pub struct Agent {
|
||||
pub container_pipe_size: u32,
|
||||
}
|
||||
|
||||
fn default_server_port() -> u32 {
|
||||
DEFAULT_AGENT_VSOCK_PORT
|
||||
}
|
||||
|
||||
fn default_log_port() -> u32 {
|
||||
DEFAULT_AGENT_LOG_PORT
|
||||
}
|
||||
|
||||
fn default_dial_timeout() -> u32 {
|
||||
// 10ms
|
||||
// ms
|
||||
10
|
||||
}
|
||||
|
||||
fn default_reconnect_timeout() -> u32 {
|
||||
// 3s
|
||||
// ms
|
||||
3_000
|
||||
}
|
||||
|
||||
fn default_request_timeout() -> u32 {
|
||||
// 30s
|
||||
// ms
|
||||
30_000
|
||||
}
|
||||
|
||||
fn default_health_check_timeout() -> u32 {
|
||||
// 90s
|
||||
// ms
|
||||
90_000
|
||||
}
|
||||
|
||||
|
@ -16,6 +16,8 @@ lazy_static! {
|
||||
];
|
||||
}
|
||||
pub const DEFAULT_AGENT_NAME: &str = "kata-agent";
|
||||
pub const DEFAULT_AGENT_VSOCK_PORT: u32 = 1024;
|
||||
pub const DEFAULT_AGENT_LOG_PORT: u32 = 1025;
|
||||
|
||||
pub const DEFAULT_INTERNETWORKING_MODEL: &str = "tcfilter";
|
||||
|
||||
|
@ -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
|
||||
|
@ -98,13 +98,11 @@ pub fn signame_to_signum(name: &str) -> Result<u8> {
|
||||
return Ok(n);
|
||||
}
|
||||
|
||||
let mut search_term: String;
|
||||
|
||||
if name.starts_with("SIG") {
|
||||
search_term = name.to_string();
|
||||
let mut search_term = if name.starts_with("SIG") {
|
||||
name.to_string()
|
||||
} else {
|
||||
search_term = format!("SIG{}", name);
|
||||
}
|
||||
format!("SIG{}", name)
|
||||
};
|
||||
|
||||
search_term = search_term.to_uppercase();
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user