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 33ab6098b8
commit 93824e1aa6
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.
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
/// Prefix for Hypervisor configurations.
pub const KATA_ANNO_CFG_HYPERVISOR_PREFIX: &str = "io.katacontainers.config.hypervisor.";
@ -990,6 +993,25 @@ impl Annotation {
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 => {
match self.get_value::<u32>(key) {
Ok(v) => {

View File

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

View File

@ -125,5 +125,6 @@ impl_agent!(
get_metrics | crate::Empty | crate::MetricsResponse | None,
get_guest_details | crate::GetGuestDetailsRequest | crate::GuestDetailsResponse | 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,
WriteStreamRequest,
},
GetGuestDetailsRequest, OomEventResponse, WaitProcessResponse, WriteStreamResponse,
GetGuestDetailsRequest, OomEventResponse, SetPolicyRequest, WaitProcessResponse,
WriteStreamResponse,
};
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 {
fn from(src: agent::AgentDetails) -> Self {
Self {

View File

@ -33,6 +33,8 @@ use async_trait::async_trait;
use kata_types::config::Agent as AgentConfig;
use crate::types::SetPolicyRequest;
pub const AGENT_KATA: &str = "kata";
#[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 add_swap(&self, req: AddSwapRequest) -> 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,
}
#[derive(PartialEq, Clone, Default, Debug)]
pub struct SetPolicyRequest {
pub policy: String,
}
#[cfg(test)]
mod test {
use std::convert::TryFrom;

View File

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

View File

@ -6,7 +6,7 @@
use crate::health_check::HealthCheck;
use agent::kata::KataAgent;
use agent::types::KernelModule;
use agent::types::{KernelModule, SetPolicyRequest};
use agent::{
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> {
// 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.
@ -593,6 +611,7 @@ impl Sandbox for VirtSandbox {
.start(&address)
.await
.context(format!("connect to address {:?}", &address))?;
self.set_agent_policy().await.context("set agent policy")?;
self.resource_manager
.setup_after_start_vm()