runtime-rs: Support agent policy

Signed-off-by: Alex Lyn <alex.lyn@antgroup.com>
Signed-off-by: stevenhorsman <steven@uk.ibm.com>
This commit is contained in:
Alex Lyn 2025-08-13 13:13:54 +08:00 committed by stevenhorsman
parent 54bcb64d23
commit 7d43e4497f
8 changed files with 69 additions and 3 deletions

View File

@ -80,6 +80,9 @@ pub const KATA_ANNO_CFG_AGENT_CONTAINER_PIPE_SIZE: &str =
/// An annotation key to specify the size of the pipes created for containers. /// An annotation key to specify the size of the pipes created for containers.
pub const CONTAINER_PIPE_SIZE_KERNEL_PARAM: &str = "agent.container_pipe_size"; pub const CONTAINER_PIPE_SIZE_KERNEL_PARAM: &str = "agent.container_pipe_size";
/// Policy is an annotation containing the contents of an agent policy file, base64 encoded.
pub const KATA_ANNO_CFG_AGENT_POLICY: &str = "io.katacontainers.config.agent.policy";
// Hypervisor related annotations // Hypervisor related annotations
/// Prefix for Hypervisor configurations. /// Prefix for Hypervisor configurations.
pub const KATA_ANNO_CFG_HYPERVISOR_PREFIX: &str = "io.katacontainers.config.hypervisor."; pub const KATA_ANNO_CFG_HYPERVISOR_PREFIX: &str = "io.katacontainers.config.hypervisor.";
@ -990,6 +993,25 @@ impl Annotation {
return Err(u32_err); return Err(u32_err);
} }
}, },
KATA_ANNO_CFG_AGENT_POLICY => {
// Base64 decode the annotation value
if let Ok(b64_decoded) = base64::decode_config(&value, base64::STANDARD) {
match String::from_utf8(b64_decoded) {
Ok(policy) => ag.policy = policy,
Err(_e) => {
return Err(io::Error::new(
io::ErrorKind::InvalidData,
format!(
"agent policy {:?} specified in annotation",
&value
),
))
}
}
} else {
ag.policy = "".to_string()
}
}
KATA_ANNO_CFG_RUNTIME_CREATE_CONTAINTER_TIMEOUT => { KATA_ANNO_CFG_RUNTIME_CREATE_CONTAINTER_TIMEOUT => {
match self.get_value::<u32>(key) { match self.get_value::<u32>(key) {
Ok(v) => { Ok(v) => {

View File

@ -146,6 +146,10 @@ pub struct Agent {
/// Memory agent configuration /// Memory agent configuration
#[serde(default)] #[serde(default)]
pub mem_agent: MemAgent, pub mem_agent: MemAgent,
/// Agent policy
#[serde(default)]
pub policy: String,
} }
impl std::default::Default for Agent { impl std::default::Default for Agent {
@ -165,6 +169,7 @@ impl std::default::Default for Agent {
kernel_modules: Default::default(), kernel_modules: Default::default(),
container_pipe_size: 0, container_pipe_size: 0,
mem_agent: MemAgent::default(), mem_agent: MemAgent::default(),
policy: Default::default(),
} }
} }
} }

View File

@ -125,5 +125,6 @@ impl_agent!(
get_metrics | crate::Empty | crate::MetricsResponse | None, get_metrics | crate::Empty | crate::MetricsResponse | None,
get_guest_details | crate::GetGuestDetailsRequest | crate::GuestDetailsResponse | None, get_guest_details | crate::GetGuestDetailsRequest | crate::GuestDetailsResponse | None,
add_swap | crate::AddSwapRequest | crate::Empty | None, add_swap | crate::AddSwapRequest | crate::Empty | None,
add_swap_path | crate::AddSwapPathRequest | crate::Empty | None add_swap_path | crate::AddSwapPathRequest | crate::Empty | None,
set_policy | crate::SetPolicyRequest | crate::Empty | None
); );

View File

@ -28,7 +28,8 @@ use crate::{
VersionCheckResponse, VolumeStatsRequest, VolumeStatsResponse, WaitProcessRequest, VersionCheckResponse, VolumeStatsRequest, VolumeStatsResponse, WaitProcessRequest,
WriteStreamRequest, WriteStreamRequest,
}, },
GetGuestDetailsRequest, OomEventResponse, WaitProcessResponse, WriteStreamResponse, GetGuestDetailsRequest, OomEventResponse, SetPolicyRequest, WaitProcessResponse,
WriteStreamResponse,
}; };
fn trans_vec<F: Sized + Clone, T: From<F>>(from: Vec<F>) -> Vec<T> { fn trans_vec<F: Sized + Clone, T: From<F>>(from: Vec<F>) -> Vec<T> {
@ -744,6 +745,15 @@ impl From<GetGuestDetailsRequest> for agent::GuestDetailsRequest {
} }
} }
impl From<SetPolicyRequest> for agent::SetPolicyRequest {
fn from(from: SetPolicyRequest) -> Self {
Self {
policy: from.policy,
..Default::default()
}
}
}
impl From<agent::AgentDetails> for AgentDetails { impl From<agent::AgentDetails> for AgentDetails {
fn from(src: agent::AgentDetails) -> Self { fn from(src: agent::AgentDetails) -> Self {
Self { Self {

View File

@ -33,6 +33,8 @@ use async_trait::async_trait;
use kata_types::config::Agent as AgentConfig; use kata_types::config::Agent as AgentConfig;
use crate::types::SetPolicyRequest;
pub const AGENT_KATA: &str = "kata"; pub const AGENT_KATA: &str = "kata";
#[async_trait] #[async_trait]
@ -96,4 +98,5 @@ pub trait Agent: AgentManager + HealthService + Send + Sync {
async fn get_guest_details(&self, req: GetGuestDetailsRequest) -> Result<GuestDetailsResponse>; async fn get_guest_details(&self, req: GetGuestDetailsRequest) -> Result<GuestDetailsResponse>;
async fn add_swap(&self, req: AddSwapRequest) -> Result<Empty>; async fn add_swap(&self, req: AddSwapRequest) -> Result<Empty>;
async fn add_swap_path(&self, req: AddSwapPathRequest) -> Result<Empty>; async fn add_swap_path(&self, req: AddSwapPathRequest) -> Result<Empty>;
async fn set_policy(&self, req: SetPolicyRequest) -> Result<Empty>;
} }

View File

@ -615,6 +615,11 @@ pub struct AddSwapPathRequest {
pub path: String, pub path: String,
} }
#[derive(PartialEq, Clone, Default, Debug)]
pub struct SetPolicyRequest {
pub policy: String,
}
#[cfg(test)] #[cfg(test)]
mod test { mod test {
use std::convert::TryFrom; use std::convert::TryFrom;

View File

@ -45,6 +45,7 @@ pub(crate) async fn handler_mux(
direct_volume_resize_handler(sandbox, req).await direct_volume_resize_handler(sandbox, req).await
} }
(&Method::GET, METRICS_URL) => metrics_url_handler(sandbox, req).await, (&Method::GET, METRICS_URL) => metrics_url_handler(sandbox, req).await,
// TODO: implement policy related method
_ => Ok(not_found(req).await), _ => Ok(not_found(req).await),
} }
} }

View File

@ -6,7 +6,7 @@
use crate::health_check::HealthCheck; use crate::health_check::HealthCheck;
use agent::kata::KataAgent; use agent::kata::KataAgent;
use agent::types::KernelModule; use agent::types::{KernelModule, SetPolicyRequest};
use agent::{ use agent::{
self, Agent, GetGuestDetailsRequest, GetIPTablesRequest, SetIPTablesRequest, VolumeStatsRequest, self, Agent, GetGuestDetailsRequest, GetIPTablesRequest, SetIPTablesRequest, VolumeStatsRequest,
}; };
@ -345,6 +345,24 @@ impl VirtSandbox {
})) }))
} }
async fn set_agent_policy(&self) -> Result<()> {
// TODO: Exclude policy-related items from the annotations.
let toml_config = self.resource_manager.config().await;
if let Some(agent_config) = toml_config.agent.get(&toml_config.runtime.agent_name) {
// If a Policy has been specified, send it to the agent.
if !agent_config.policy.is_empty() {
self.agent
.set_policy(SetPolicyRequest {
policy: agent_config.policy.clone(),
})
.await
.context("sandbox: set policy failed")?;
}
}
Ok(())
}
async fn prepare_vm_socket_config(&self) -> Result<ResourceConfig> { async fn prepare_vm_socket_config(&self) -> Result<ResourceConfig> {
// It will check the hypervisor's capabilities to see if it supports hybrid-vsock. // It will check the hypervisor's capabilities to see if it supports hybrid-vsock.
// If it does not, it'll assume that it only supports legacy vsock. // If it does not, it'll assume that it only supports legacy vsock.
@ -592,6 +610,7 @@ impl Sandbox for VirtSandbox {
.start(&address) .start(&address)
.await .await
.context(format!("connect to address {:?}", &address))?; .context(format!("connect to address {:?}", &address))?;
self.set_agent_policy().await.context("set agent policy")?;
self.resource_manager self.resource_manager
.setup_after_start_vm() .setup_after_start_vm()