mirror of
https://github.com/kata-containers/kata-containers.git
synced 2025-08-23 18:21:27 +00:00
agent: Append the container OCI spec with the image bundle one
We do not get a root filesystem path from the agent when creating a new container for which the container image was not pulled by containerd. That prevents the agent from creating the container. To fix that, we populate the container root path with the internal rootfs path by fetching the containerd added image name annotation and mapping it back to a path through our image hash map. Fixes #3009 Signed-off-by: wllenyj <wllenyj@linux.alibaba.com> Signed-off-by: Samuel Ortiz <s.ortiz@apple.com>
This commit is contained in:
parent
5691e66e1b
commit
ab6b1cbfe9
@ -79,6 +79,8 @@ use std::path::PathBuf;
|
|||||||
|
|
||||||
pub const CONTAINER_BASE: &str = "/run/kata-containers";
|
pub const CONTAINER_BASE: &str = "/run/kata-containers";
|
||||||
const MODPROBE_PATH: &str = "/sbin/modprobe";
|
const MODPROBE_PATH: &str = "/sbin/modprobe";
|
||||||
|
const ANNO_K8S_IMAGE_NAME: &str = "io.kubernetes.cri.image-name";
|
||||||
|
const CONFIG_JSON: &str = "config.json";
|
||||||
|
|
||||||
// Convenience macro to obtain the scope logger
|
// Convenience macro to obtain the scope logger
|
||||||
macro_rules! sl {
|
macro_rules! sl {
|
||||||
@ -124,6 +126,19 @@ pub fn verify_cid(id: &str) -> Result<()> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Partially merge an OCI process specification into another one.
|
||||||
|
fn merge_oci_process(target: &mut oci::Process, source: &oci::Process) {
|
||||||
|
if target.args.is_empty() && !source.args.is_empty() {
|
||||||
|
target.args.append(&mut source.args.clone());
|
||||||
|
}
|
||||||
|
|
||||||
|
if target.cwd.is_empty() && !source.cwd.is_empty() {
|
||||||
|
target.cwd = String::from(&source.cwd);
|
||||||
|
}
|
||||||
|
|
||||||
|
target.env.append(&mut source.env.clone());
|
||||||
|
}
|
||||||
|
|
||||||
impl AgentService {
|
impl AgentService {
|
||||||
#[instrument]
|
#[instrument]
|
||||||
async fn do_create_container(
|
async fn do_create_container(
|
||||||
@ -150,6 +165,9 @@ impl AgentService {
|
|||||||
|
|
||||||
info!(sl!(), "receive createcontainer, spec: {:?}", &oci);
|
info!(sl!(), "receive createcontainer, spec: {:?}", &oci);
|
||||||
|
|
||||||
|
// Merge the image bundle OCI spec into the container creation request OCI spec.
|
||||||
|
self.merge_bundle_oci(&mut oci).await?;
|
||||||
|
|
||||||
// Some devices need some extra processing (the ones invoked with
|
// Some devices need some extra processing (the ones invoked with
|
||||||
// --device for instance), and that's what this call is doing. It
|
// --device for instance), and that's what this call is doing. It
|
||||||
// updates the devices listed in the OCI spec, so that they actually
|
// updates the devices listed in the OCI spec, so that they actually
|
||||||
@ -537,6 +555,54 @@ impl AgentService {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// When being passed an image name through a container annotation, merge its
|
||||||
|
// corresponding bundle OCI specification into the passed container creation one.
|
||||||
|
async fn merge_bundle_oci(&self, container_oci: &mut oci::Spec) -> Result<()> {
|
||||||
|
if let Some(image_name) = container_oci
|
||||||
|
.annotations
|
||||||
|
.get(&ANNO_K8S_IMAGE_NAME.to_string())
|
||||||
|
{
|
||||||
|
if let Some(container_id) = self.sandbox.clone().lock().await.images.get(image_name) {
|
||||||
|
let image_oci_config_path = Path::new(CONTAINER_BASE)
|
||||||
|
.join(container_id)
|
||||||
|
.join(CONFIG_JSON);
|
||||||
|
debug!(
|
||||||
|
sl!(),
|
||||||
|
"Image bundle config path: {:?}", image_oci_config_path
|
||||||
|
);
|
||||||
|
|
||||||
|
let image_oci =
|
||||||
|
oci::Spec::load(image_oci_config_path.to_str().ok_or_else(|| {
|
||||||
|
anyhow!(
|
||||||
|
"Invalid container image OCI config path {:?}",
|
||||||
|
image_oci_config_path
|
||||||
|
)
|
||||||
|
})?)
|
||||||
|
.context("load image bundle")?;
|
||||||
|
|
||||||
|
if let Some(container_root) = container_oci.root.as_mut() {
|
||||||
|
if let Some(image_root) = image_oci.root.as_ref() {
|
||||||
|
let root_path = Path::new(CONTAINER_BASE)
|
||||||
|
.join(container_id)
|
||||||
|
.join(image_root.path.clone());
|
||||||
|
container_root.path =
|
||||||
|
String::from(root_path.to_str().ok_or_else(|| {
|
||||||
|
anyhow!("Invalid container image root path {:?}", root_path)
|
||||||
|
})?);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(container_process) = container_oci.process.as_mut() {
|
||||||
|
if let Some(image_process) = image_oci.process.as_ref() {
|
||||||
|
merge_oci_process(container_process, image_process);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[async_trait]
|
#[async_trait]
|
||||||
@ -1620,7 +1686,7 @@ fn setup_bundle(cid: &str, spec: &mut Spec) -> Result<PathBuf> {
|
|||||||
let spec_root = spec.root.as_ref().unwrap();
|
let spec_root = spec.root.as_ref().unwrap();
|
||||||
|
|
||||||
let bundle_path = Path::new(CONTAINER_BASE).join(cid);
|
let bundle_path = Path::new(CONTAINER_BASE).join(cid);
|
||||||
let config_path = bundle_path.join("config.json");
|
let config_path = bundle_path.join(CONFIG_JSON);
|
||||||
let rootfs_path = bundle_path.join("rootfs");
|
let rootfs_path = bundle_path.join("rootfs");
|
||||||
|
|
||||||
let rootfs_exists = Path::new(&rootfs_path).exists();
|
let rootfs_exists = Path::new(&rootfs_path).exists();
|
||||||
|
Loading…
Reference in New Issue
Block a user