diff --git a/src/runtime_service/run_pod_sandbox.rs b/src/runtime_service/run_pod_sandbox.rs index 18f6bb00..c36158f4 100644 --- a/src/runtime_service/run_pod_sandbox.rs +++ b/src/runtime_service/run_pod_sandbox.rs @@ -70,9 +70,7 @@ impl CRIService { debug!("Created pod sandbox {:?}", sandbox); // Run the sandbox - sandbox - .run() - .map_err(|e| Status::internal(format!("run pod sandbox: {}", e)))?; + sandbox.run().await.map_err(|e| Status::internal(format!("run pod sandbox: {}", e)))?; info!("Started pod sandbox {}", sandbox); // Build and return the response diff --git a/src/sandbox/mod.rs b/src/sandbox/mod.rs index efb6a3de..826f5d8f 100644 --- a/src/sandbox/mod.rs +++ b/src/sandbox/mod.rs @@ -2,6 +2,7 @@ pub mod pinned; +use async_trait::async_trait; use anyhow::Result; use bitflags::bitflags; use derive_builder::Builder; @@ -76,9 +77,10 @@ pub struct SandboxData { annotations: HashMap, } +#[async_trait] pub trait Pod { /// Run a previously created sandbox. - fn run(&mut self, _: &SandboxData) -> Result<()> { + async fn run(&mut self, _: &SandboxData) -> Result<()> { Ok(()) } @@ -102,7 +104,7 @@ pub trait Pod { impl Sandbox where - T: Default + Pod, + T: Default + Pod + Send, { /// Retrieve the unique identifier for the sandbox pub fn id(&self) -> &str { @@ -110,8 +112,8 @@ where } /// Wrapper for the implementations `run` method - pub fn run(&mut self) -> Result<()> { - self.implementation.run(&self.data) + pub async fn run(&mut self) -> Result<()> { + Ok(self.implementation.run(&self.data).await?) } #[allow(dead_code)] @@ -187,8 +189,10 @@ pub mod tests { remove_called: bool, ready: bool, } + + #[async_trait] impl Pod for Mock { - fn run(&mut self, _: &SandboxData) -> Result<()> { + async fn run(&mut self, _: &SandboxData) -> Result<()> { self.run_called = true; self.ready = true; Ok(()) diff --git a/src/sandbox/pinned.rs b/src/sandbox/pinned.rs index f46c45f4..0e2e01f6 100644 --- a/src/sandbox/pinned.rs +++ b/src/sandbox/pinned.rs @@ -1,8 +1,69 @@ -//! A pod sandbox implementation which does pin it's namespaces to file descriptors. +//! A pod sandbox implementation which does pin its namespaces to file descriptors. -use crate::sandbox::Pod; +use crate::sandbox::{LinuxNamespaces, Pod, SandboxData}; +use async_trait::async_trait; +use anyhow::{bail, Context, Result}; +use tokio::process::Command; +use which::which; +use std::path::PathBuf; #[derive(Default)] -pub struct PinnedSandbox {} +pub struct PinnedSandbox { + pinner_path: PathBuf, + namespaces_dir: String, + ready: bool, +} -impl Pod for PinnedSandbox {} +impl PinnedSandbox { + pub fn new(pinner: &str) -> Result { + let path = which(pinner) + .with_context(|| format!("failed to find {} in PATH", pinner))?; + let ps = PinnedSandbox { + pinner_path: path, + // TODO: Make this configurable + namespaces_dir: String::from("/var/run/cri"), + ready: false, + }; + Ok(ps) + } +} + +#[async_trait] +impl Pod for PinnedSandbox { + async fn run(&mut self, sd: &SandboxData) -> Result<()> { + let mut args = Vec::new(); + args.push("-d"); + args.push(&self.namespaces_dir); + args.push("-f"); + args.push(&sd.id); + let linux_namespaces = sd.linux_namespaces.context("linux namespaces not set")?; + if linux_namespaces.contains(LinuxNamespaces::NET) { + args.push("-n"); + } + if linux_namespaces.contains(LinuxNamespaces::IPC) { + args.push("-i"); + } + if linux_namespaces.contains(LinuxNamespaces::UTS) { + args.push("-u"); + } + let output = Command::new(&self.pinner_path).args(&args[..]).output().await?; + if !output.status.success() { + bail!("Failed to pin namespaces for sandbox") + } + self.ready = true; + Ok(()) + } + + fn stop(&mut self, _: &SandboxData) -> Result<()> { + self.ready = false; + Ok(()) + } + + fn remove(&mut self, _: &SandboxData) -> Result<()> { + Ok(()) + } + + fn ready(&mut self, _: &SandboxData) -> Result { + Ok(false) + } +}