mirror of
https://github.com/kata-containers/kata-containers.git
synced 2025-07-16 08:26:16 +00:00
Merge pull request #5097 from openanolis/dbg-console
runtime-rs: debug console support in runtime
This commit is contained in:
commit
319caa8e74
@ -18,9 +18,11 @@ lazy_static! {
|
||||
"/usr/share/defaults/kata-containers/configuration.toml",
|
||||
];
|
||||
}
|
||||
|
||||
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_AGENT_DBG_CONSOLE_PORT: u32 = 1026;
|
||||
pub const DEFAULT_AGENT_TYPE_NAME: &str = AGENT_NAME_KATA;
|
||||
|
||||
pub const DEFAULT_RUNTIME_NAME: &str = RUNTIME_NAME_VIRTCONTAINER;
|
||||
|
@ -50,6 +50,8 @@ const VIRTIO_FS: &str = "virtio-fs";
|
||||
const VIRTIO_FS_INLINE: &str = "inline-virtio-fs";
|
||||
const MAX_BRIDGE_SIZE: u32 = 5;
|
||||
|
||||
const KERNEL_PARAM_DELIMITER: &str = " ";
|
||||
|
||||
lazy_static! {
|
||||
static ref HYPERVISOR_PLUGINS: Mutex<HashMap<String, Arc<dyn ConfigPlugin>>> =
|
||||
Mutex::new(HashMap::new());
|
||||
@ -237,6 +239,16 @@ impl BootInfo {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Add kernel parameters to bootinfo. It is always added before the original
|
||||
/// to let the original one takes priority
|
||||
pub fn add_kernel_params(&mut self, params: Vec<String>) {
|
||||
let mut p = params;
|
||||
if !self.kernel_params.is_empty() {
|
||||
p.push(self.kernel_params.clone()); // [new_params0, new_params1, ..., original_params]
|
||||
}
|
||||
self.kernel_params = p.join(KERNEL_PARAM_DELIMITER);
|
||||
}
|
||||
|
||||
/// Validate guest kernel image annotaion
|
||||
pub fn validate_boot_path(&self, path: &str) -> Result<()> {
|
||||
validate_path!(path, "path {} is invalid{}")?;
|
||||
@ -1067,4 +1079,31 @@ mod tests {
|
||||
assert!(get_hypervisor_plugin("dragonball").is_some());
|
||||
assert!(get_hypervisor_plugin("dragonball2").is_none());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_add_kernel_params() {
|
||||
let mut boot_info = BootInfo {
|
||||
..Default::default()
|
||||
};
|
||||
let params = vec![
|
||||
String::from("foo"),
|
||||
String::from("bar"),
|
||||
String::from("baz=faz"),
|
||||
];
|
||||
boot_info.add_kernel_params(params);
|
||||
|
||||
assert_eq!(boot_info.kernel_params, String::from("foo bar baz=faz"));
|
||||
|
||||
let new_params = vec![
|
||||
String::from("boo=far"),
|
||||
String::from("a"),
|
||||
String::from("b=c"),
|
||||
];
|
||||
boot_info.add_kernel_params(new_params);
|
||||
|
||||
assert_eq!(
|
||||
boot_info.kernel_params,
|
||||
String::from("boo=far a b=c foo bar baz=faz")
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -23,6 +23,7 @@ mod drop_in;
|
||||
pub mod hypervisor;
|
||||
|
||||
pub use self::agent::Agent;
|
||||
use self::default::DEFAULT_AGENT_DBG_CONSOLE_PORT;
|
||||
pub use self::hypervisor::{
|
||||
BootInfo, DragonballConfig, Hypervisor, QemuConfig, HYPERVISOR_NAME_DRAGONBALL,
|
||||
HYPERVISOR_NAME_QEMU,
|
||||
@ -33,6 +34,24 @@ pub use self::runtime::{Runtime, RuntimeVendor, RUNTIME_NAME_VIRTCONTAINER};
|
||||
|
||||
pub use self::agent::AGENT_NAME_KATA;
|
||||
|
||||
// TODO: let agent use the constants here for consistency
|
||||
/// Debug console enabled flag for agent
|
||||
pub const DEBUG_CONSOLE_FLAG: &str = "agent.debug_console";
|
||||
/// Tracing enabled flag for agent
|
||||
pub const TRACE_MODE_OPTION: &str = "agent.trace";
|
||||
/// Tracing enabled
|
||||
pub const TRACE_MODE_ENABLE: &str = "true";
|
||||
/// Log level setting key for agent, if debugged mode on, set to debug
|
||||
pub const LOG_LEVEL_OPTION: &str = "agent.log";
|
||||
/// logging level: debug
|
||||
pub const LOG_LEVEL_DEBUG: &str = "debug";
|
||||
/// Option of which port will the debug console connect to
|
||||
pub const DEBUG_CONSOLE_VPORT_OPTION: &str = "agent.debug_console_vport";
|
||||
/// Option of which port the agent's log will connect to
|
||||
pub const LOG_VPORT_OPTION: &str = "agent.log_vport";
|
||||
/// Option of setting the container's pipe size
|
||||
pub const CONTAINER_PIPE_SIZE_OPTION: &str = "agent.container_pipe_size";
|
||||
|
||||
/// Trait to manipulate global Kata configuration information.
|
||||
pub trait ConfigPlugin: Send + Sync {
|
||||
/// Get the plugin name.
|
||||
@ -151,7 +170,32 @@ impl TomlConfig {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Probe configuration file according to the default configuration file list.
|
||||
/// Get agent-specfic kernel parameters for further Hypervisor config revision
|
||||
pub fn get_agent_kernel_params(&self) -> Result<HashMap<String, String>> {
|
||||
let mut kv = HashMap::new();
|
||||
if let Some(cfg) = self.agent.get(&self.runtime.agent_name) {
|
||||
if cfg.debug {
|
||||
kv.insert(LOG_LEVEL_OPTION.to_string(), LOG_LEVEL_DEBUG.to_string());
|
||||
}
|
||||
if cfg.enable_tracing {
|
||||
kv.insert(TRACE_MODE_OPTION.to_string(), TRACE_MODE_ENABLE.to_string());
|
||||
}
|
||||
if cfg.container_pipe_size > 0 {
|
||||
let container_pipe_size = cfg.container_pipe_size.to_string();
|
||||
kv.insert(CONTAINER_PIPE_SIZE_OPTION.to_string(), container_pipe_size);
|
||||
}
|
||||
if cfg.debug_console_enabled {
|
||||
kv.insert(DEBUG_CONSOLE_FLAG.to_string(), "".to_string());
|
||||
kv.insert(
|
||||
DEBUG_CONSOLE_VPORT_OPTION.to_string(),
|
||||
DEFAULT_AGENT_DBG_CONSOLE_PORT.to_string(),
|
||||
);
|
||||
}
|
||||
}
|
||||
Ok(kv)
|
||||
}
|
||||
|
||||
/// Probe configuration file according to the default configuration file list.
|
||||
fn get_default_config_file() -> Result<PathBuf> {
|
||||
for f in default::DEFAULT_RUNTIME_CONFIGURATIONS.iter() {
|
||||
if let Ok(path) = fs::canonicalize(f) {
|
||||
@ -303,4 +347,28 @@ mod tests {
|
||||
let patterns = ["/usr/share".to_string(), "/bin/*".to_string()];
|
||||
validate_path_pattern(&patterns, "/bin/ls").unwrap();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_get_agent_kernel_params() {
|
||||
let mut config = TomlConfig {
|
||||
..Default::default()
|
||||
};
|
||||
let agent_config = Agent {
|
||||
debug: true,
|
||||
enable_tracing: true,
|
||||
container_pipe_size: 20,
|
||||
debug_console_enabled: true,
|
||||
..Default::default()
|
||||
};
|
||||
let agent_name = "test_agent";
|
||||
config.runtime.agent_name = agent_name.to_string();
|
||||
config.agent.insert(agent_name.to_owned(), agent_config);
|
||||
|
||||
let kv = config.get_agent_kernel_params().unwrap();
|
||||
assert_eq!(kv.get("agent.log").unwrap(), "debug");
|
||||
assert_eq!(kv.get("agent.trace").unwrap(), "true");
|
||||
assert_eq!(kv.get("agent.container_pipe_size").unwrap(), "20");
|
||||
kv.get("agent.debug_console").unwrap();
|
||||
assert_eq!(kv.get("agent.debug_console_vport").unwrap(), "1026"); // 1026 is the default port
|
||||
}
|
||||
}
|
||||
|
@ -91,6 +91,7 @@ impl DragonballInner {
|
||||
kernel_params.append(&mut KernelParams::from_string(
|
||||
&self.config.boot_info.kernel_params,
|
||||
));
|
||||
info!(sl!(), "prepared kernel_params={:?}", kernel_params);
|
||||
|
||||
// set boot source
|
||||
let kernel_path = self.config.boot_info.kernel.clone();
|
||||
|
@ -7,6 +7,7 @@
|
||||
use anyhow::{anyhow, Result};
|
||||
|
||||
use crate::{VM_ROOTFS_DRIVER_BLK, VM_ROOTFS_DRIVER_PMEM};
|
||||
use kata_types::config::LOG_VPORT_OPTION;
|
||||
|
||||
// Port where the agent will send the logs. Logs are sent through the vsock in cases
|
||||
// where the hypervisor has no console.sock, i.e dragonball
|
||||
@ -28,6 +29,18 @@ impl Param {
|
||||
value: value.to_owned(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn to_string(&self) -> Result<String> {
|
||||
if self.key.is_empty() && self.value.is_empty() {
|
||||
Err(anyhow!("Empty key and value"))
|
||||
} else if self.key.is_empty() {
|
||||
Err(anyhow!("Empty key"))
|
||||
} else if self.value.is_empty() {
|
||||
Ok(self.key.to_string())
|
||||
} else {
|
||||
Ok(format!("{}{}{}", self.key, KERNEL_KV_DELIMITER, self.value))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq)]
|
||||
@ -48,7 +61,7 @@ impl KernelParams {
|
||||
];
|
||||
|
||||
if debug {
|
||||
params.push(Param::new("agent.log_vport", VSOCK_LOGS_PORT));
|
||||
params.push(Param::new(LOG_VPORT_OPTION, VSOCK_LOGS_PORT));
|
||||
}
|
||||
|
||||
Self { params }
|
||||
@ -129,18 +142,7 @@ impl KernelParams {
|
||||
let mut parameters: Vec<String> = Vec::new();
|
||||
|
||||
for param in &self.params {
|
||||
if param.key.is_empty() && param.value.is_empty() {
|
||||
return Err(anyhow!("Empty key and value"));
|
||||
} else if param.key.is_empty() {
|
||||
return Err(anyhow!("Empty key"));
|
||||
} else if param.value.is_empty() {
|
||||
parameters.push(param.key.to_string());
|
||||
} else {
|
||||
parameters.push(format!(
|
||||
"{}{}{}",
|
||||
param.key, KERNEL_KV_DELIMITER, param.value
|
||||
));
|
||||
}
|
||||
parameters.push(param.to_string()?);
|
||||
}
|
||||
|
||||
Ok(parameters.join(KERNEL_PARAM_DELIMITER))
|
||||
@ -153,6 +155,20 @@ mod tests {
|
||||
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn test_params() {
|
||||
let param1 = Param::new("", "");
|
||||
let param2 = Param::new("", "foo");
|
||||
let param3 = Param::new("foo", "");
|
||||
|
||||
assert!(param1.to_string().is_err());
|
||||
assert!(param2.to_string().is_err());
|
||||
assert_eq!(param3.to_string().unwrap(), String::from("foo"));
|
||||
|
||||
let param4 = Param::new("foo", "bar");
|
||||
assert_eq!(param4.to_string().unwrap(), String::from("foo=bar"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_kernel_params() -> Result<()> {
|
||||
let expect_params_string = "k1=v1 k2=v2 k3=v3".to_string();
|
||||
|
@ -19,6 +19,7 @@ kata-types = { path = "../../../libs/kata-types" }
|
||||
logging = { path = "../../../libs/logging"}
|
||||
oci = { path = "../../../libs/oci" }
|
||||
persist = { path = "../persist" }
|
||||
hypervisor = { path = "../hypervisor" }
|
||||
# runtime handler
|
||||
linux_container = { path = "./linux_container", optional = true }
|
||||
virt_container = { path = "./virt_container", optional = true }
|
||||
|
@ -14,6 +14,7 @@ use common::{
|
||||
types::{Request, Response},
|
||||
RuntimeHandler, RuntimeInstance, Sandbox,
|
||||
};
|
||||
use hypervisor::Param;
|
||||
use kata_types::{annotations::Annotation, config::TomlConfig};
|
||||
#[cfg(feature = "linux")]
|
||||
use linux_container::LinuxContainer;
|
||||
@ -335,6 +336,7 @@ fn load_config(spec: &oci::Spec, option: &Option<Vec<u8>>) -> Result<TomlConfig>
|
||||
let (mut toml_config, _) =
|
||||
TomlConfig::load_from_file(&config_path).context("load toml config")?;
|
||||
annotation.update_config_by_annotation(&mut toml_config)?;
|
||||
update_agent_kernel_params(&mut toml_config)?;
|
||||
|
||||
// validate configuration and return the error
|
||||
toml_config.validate()?;
|
||||
@ -358,3 +360,20 @@ fn load_config(spec: &oci::Spec, option: &Option<Vec<u8>>) -> Result<TomlConfig>
|
||||
info!(sl!(), "get config content {:?}", &toml_config);
|
||||
Ok(toml_config)
|
||||
}
|
||||
|
||||
// this update the agent-specfic kernel parameters into hypervisor's bootinfo
|
||||
// the agent inside the VM will read from file cmdline to get the params and function
|
||||
fn update_agent_kernel_params(config: &mut TomlConfig) -> Result<()> {
|
||||
let mut params = vec![];
|
||||
if let Ok(kv) = config.get_agent_kernel_params() {
|
||||
for (k, v) in kv.into_iter() {
|
||||
if let Ok(s) = Param::new(k.as_str(), v.as_str()).to_string() {
|
||||
params.push(s);
|
||||
}
|
||||
}
|
||||
if let Some(h) = config.hypervisor.get_mut(&config.runtime.hypervisor_name) {
|
||||
h.boot_info.add_kernel_params(params);
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user