diff --git a/containerd-shim-lunatic-v1/Cargo.lock b/containerd-shim-lunatic-v1/Cargo.lock index 86905e7f..ec762c10 100644 --- a/containerd-shim-lunatic-v1/Cargo.lock +++ b/containerd-shim-lunatic-v1/Cargo.lock @@ -588,7 +588,7 @@ dependencies = [ "containerd-shim", "containerd-shim-wasm", "libc", - "libcontainer", + "libcontainer 0.1.0", "log", "lunatic-distributed", "lunatic-process", @@ -618,7 +618,7 @@ dependencies = [ [[package]] name = "containerd-shim-wasm" version = "0.2.1" -source = "git+https://github.com/containerd/runwasi?rev=7e978edeaf34b54efb895738357c805cf888b76d#7e978edeaf34b54efb895738357c805cf888b76d" +source = "git+https://github.com/containerd/runwasi?rev=4d212b968d24d42a27952e8b04979382b543a613#4d212b968d24d42a27952e8b04979382b543a613" dependencies = [ "anyhow", "caps", @@ -628,7 +628,7 @@ dependencies = [ "containerd-shim", "crossbeam", "libc", - "libcontainer", + "libcontainer 0.2.0", "log", "nix 0.26.4", "oci-spec", @@ -637,6 +637,7 @@ dependencies = [ "serde_json", "thiserror", "ttrpc", + "wat", "windows-sys 0.48.0", ] @@ -1725,6 +1726,21 @@ dependencies = [ "tracing", ] +[[package]] +name = "libcgroups" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ebc75981724e1f7e065582ddfb1ef41bbe82c2d3afa130777fc41d75f386a0c6" +dependencies = [ + "fixedbitset 0.4.2", + "nix 0.26.4", + "oci-spec", + "procfs", + "serde", + "thiserror", + "tracing", +] + [[package]] name = "libcontainer" version = "0.1.0" @@ -1736,7 +1752,34 @@ dependencies = [ "fastrand", "futures", "libc", - "libcgroups", + "libcgroups 0.1.0", + "nix 0.26.4", + "oci-spec", + "once_cell", + "prctl", + "procfs", + "regex", + "rust-criu", + "safe-path", + "serde", + "serde_json", + "thiserror", + "tracing", +] + +[[package]] +name = "libcontainer" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0a122c3ce58c5a705d3e71809816ab6726dfd37621d8e55bfd5f33dac213c713" +dependencies = [ + "bitflags 2.4.0", + "caps", + "chrono", + "fastrand", + "futures", + "libc", + "libcgroups 0.2.0", "nix 0.26.4", "oci-spec", "once_cell", diff --git a/containerd-shim-lunatic-v1/Cargo.toml b/containerd-shim-lunatic-v1/Cargo.toml index 159c5daf..c5787e4b 100644 --- a/containerd-shim-lunatic-v1/Cargo.toml +++ b/containerd-shim-lunatic-v1/Cargo.toml @@ -7,7 +7,7 @@ edition = "2021" [dependencies] containerd-shim = "0.5.0" -containerd-shim-wasm = { git = "https://github.com/containerd/runwasi", rev = "7e978edeaf34b54efb895738357c805cf888b76d", features = ["cgroupsv2"] } +containerd-shim-wasm = { git = "https://github.com/containerd/runwasi", rev = "4d212b968d24d42a27952e8b04979382b543a613", features = ["cgroupsv2"] } libcontainer = { git = "https://github.com/containers/youki", rev = "09e67372a892f22a89eeef62ff429c3cbcac6d41", features = ["v1","v2"], default-features = false } nix = "0.26.2" serde = "1.0.183" diff --git a/containerd-shim-lunatic-v1/src/executor.rs b/containerd-shim-lunatic-v1/src/executor.rs index 65326389..1b1281aa 100644 --- a/containerd-shim-lunatic-v1/src/executor.rs +++ b/containerd-shim-lunatic-v1/src/executor.rs @@ -3,58 +3,38 @@ use std::path::PathBuf; use std::sync::Arc; use tokio::runtime::Runtime; -use containerd_shim_wasm::libcontainer_instance::LinuxContainerExecutor; -use containerd_shim_wasm::sandbox::Stdio; -use libcontainer::workload::{Executor, ExecutorError, ExecutorValidationError}; +use containerd_shim_wasm::{ + container::{Engine, RuntimeContext}, + sandbox::Stdio, +}; use lunatic_process::{ env::{Environments, LunaticEnvironments}, runtimes, }; -use oci_spec::runtime::Spec; -use utils::{get_args, is_linux_executable}; use crate::common::{run_wasm, RunWasm}; -#[derive(Clone)] -pub struct LunaticExecutor { - stdio: Stdio, -} +#[derive(Clone, Default)] +pub struct LunaticEngine; -impl LunaticExecutor { - pub fn new(stdio: Stdio) -> Self { - Self { stdio } +impl Engine for LunaticEngine { + fn name() -> &'static str { + "lunatic" } - fn wasm_exec(&self, spec: &Spec) -> anyhow::Result<()> { - self.stdio - .take() - .redirect() - .context("failed to redirect stdio")?; - let cmd = get_args(spec).first().context("no cmd provided")?.clone(); + fn run_wasi(&self, ctx: &impl RuntimeContext, stdio: Stdio) -> Result { + log::info!("setting up wasi"); + stdio.redirect()?; + let cmd = ctx.args().first().context("no cmd provided")?.clone(); let rt = Runtime::new().context("failed to create runtime")?; - rt.block_on(async { + if let Err(e) = rt.block_on(async { log::info!(" >>> building lunatic application"); crate::executor::exec(cmd).await - }) - } -} - -impl Executor for LunaticExecutor { - fn exec(&self, spec: &Spec) -> Result<(), ExecutorError> { - if is_linux_executable(spec).is_ok() { - log::info!("executing linux container"); - LinuxContainerExecutor::new(self.stdio.clone()).exec(spec) - } else { - if let Err(e) = self.wasm_exec(spec) { - log::error!(" >>> error: {:?}", e); - std::process::exit(137); - } - std::process::exit(0); + }) { + log::error!(" >>> error: {:?}", e); + return Ok(137); } - } - - fn validate(&self, _spec: &Spec) -> Result<(), ExecutorValidationError> { - Ok(()) + Ok(0) } } diff --git a/containerd-shim-lunatic-v1/src/main.rs b/containerd-shim-lunatic-v1/src/main.rs index 248fc06c..d5f8d2b1 100644 --- a/containerd-shim-lunatic-v1/src/main.rs +++ b/containerd-shim-lunatic-v1/src/main.rs @@ -1,86 +1,16 @@ -use std::{ - env, - path::PathBuf, - sync::{Arc, Condvar, Mutex}, -}; +use std::env; use containerd_shim::{parse, run}; -use containerd_shim_wasm::sandbox::instance_utils::determine_rootdir; -use containerd_shim_wasm::sandbox::stdio::Stdio; -use containerd_shim_wasm::{ - libcontainer_instance::LibcontainerInstance, - sandbox::{instance::ExitCode, Error, InstanceConfig, ShimCli}, -}; -use libcontainer::container::{builder::ContainerBuilder, Container}; -use libcontainer::syscall::syscall::SyscallType; +use containerd_shim_wasm::container::Instance; +use containerd_shim_wasm::sandbox::ShimCli; -use anyhow::Result; +use executor::LunaticEngine; -use crate::executor::LunaticExecutor; +pub type LunaticInstance = Instance; mod common; mod executor; -static DEFAULT_CONTAINER_ROOT_DIR: &str = "/run/containerd/lunatic"; - -pub struct Wasi { - id: String, - exit_code: ExitCode, - bundle: String, - rootdir: PathBuf, - stdio: Stdio, -} - -impl LibcontainerInstance for Wasi { - type Engine = (); - - fn new_libcontainer(id: String, cfg: Option<&InstanceConfig>) -> Self { - let cfg = cfg.unwrap(); - let bundle = cfg.get_bundle().unwrap_or_default(); - - Wasi { - id, - exit_code: Arc::new((Mutex::new(None), Condvar::new())), - rootdir: determine_rootdir( - bundle.as_str(), - cfg.get_namespace().as_str(), - DEFAULT_CONTAINER_ROOT_DIR, - ) - .unwrap(), - bundle, - stdio: Stdio::init_from_cfg(cfg).expect("failed to open stdio"), - } - } - - fn get_exit_code(&self) -> ExitCode { - self.exit_code.clone() - } - - fn get_id(&self) -> String { - self.id.clone() - } - - fn get_root_dir(&self) -> std::result::Result { - Ok(self.rootdir.clone()) - } - - fn build_container(&self) -> Result { - log::info!("Building container"); - - let err_msg = |err| format!("failed to create container: {}", err); - let container = ContainerBuilder::new(self.id.clone(), SyscallType::Linux) - .with_executor(LunaticExecutor::new(self.stdio.take())) - .with_root_path(self.rootdir.clone()) - .map_err(|err| Error::Others(err_msg(err)))? - .as_init(&self.bundle) - .with_systemd(false) - .build() - .map_err(|err| Error::Others(err_msg(err)))?; - log::info!(">>> Container built."); - Ok(container) - } -} - fn parse_version() { let os_args: Vec<_> = env::args_os().collect(); let flags = parse(&os_args[1..]).unwrap(); @@ -96,5 +26,5 @@ fn parse_version() { fn main() { parse_version(); - run::>("io.containerd.lunatic.v1", None); + run::>("io.containerd.lunatic.v1", None); } diff --git a/containerd-shim-slight-v1/Cargo.lock b/containerd-shim-slight-v1/Cargo.lock index 054bd675..b840a654 100644 --- a/containerd-shim-slight-v1/Cargo.lock +++ b/containerd-shim-slight-v1/Cargo.lock @@ -1457,7 +1457,7 @@ dependencies = [ "curl", "isahc 1.7.2", "libc", - "libcontainer", + "libcontainer 0.1.0", "log", "nix 0.26.4", "oci-spec", @@ -1478,7 +1478,7 @@ dependencies = [ [[package]] name = "containerd-shim-wasm" version = "0.2.1" -source = "git+https://github.com/containerd/runwasi?rev=7e978edeaf34b54efb895738357c805cf888b76d#7e978edeaf34b54efb895738357c805cf888b76d" +source = "git+https://github.com/containerd/runwasi?rev=4d212b968d24d42a27952e8b04979382b543a613#4d212b968d24d42a27952e8b04979382b543a613" dependencies = [ "anyhow", "caps", @@ -1488,7 +1488,7 @@ dependencies = [ "containerd-shim", "crossbeam", "libc", - "libcontainer", + "libcontainer 0.2.0", "log", "nix 0.26.4", "oci-spec", @@ -1497,6 +1497,7 @@ dependencies = [ "serde_json", "thiserror", "ttrpc", + "wat", "windows-sys 0.48.0", ] @@ -3018,6 +3019,21 @@ dependencies = [ "tracing", ] +[[package]] +name = "libcgroups" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ebc75981724e1f7e065582ddfb1ef41bbe82c2d3afa130777fc41d75f386a0c6" +dependencies = [ + "fixedbitset 0.4.2", + "nix 0.26.4", + "oci-spec", + "procfs", + "serde", + "thiserror", + "tracing", +] + [[package]] name = "libcontainer" version = "0.1.0" @@ -3029,7 +3045,34 @@ dependencies = [ "fastrand 2.0.0", "futures", "libc", - "libcgroups", + "libcgroups 0.1.0", + "nix 0.26.4", + "oci-spec", + "once_cell", + "prctl", + "procfs", + "regex", + "rust-criu", + "safe-path", + "serde", + "serde_json", + "thiserror", + "tracing", +] + +[[package]] +name = "libcontainer" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0a122c3ce58c5a705d3e71809816ab6726dfd37621d8e55bfd5f33dac213c713" +dependencies = [ + "bitflags 2.4.0", + "caps", + "chrono", + "fastrand 2.0.0", + "futures", + "libc", + "libcgroups 0.2.0", "nix 0.26.4", "oci-spec", "once_cell", diff --git a/containerd-shim-slight-v1/Cargo.toml b/containerd-shim-slight-v1/Cargo.toml index 11a049ff..0696782c 100644 --- a/containerd-shim-slight-v1/Cargo.toml +++ b/containerd-shim-slight-v1/Cargo.toml @@ -14,7 +14,7 @@ Containerd shim for running Slight workloads. chrono = "0.4" clap = { version = "4.1", features = ["derive", "env"] } containerd-shim = "0.5.0" -containerd-shim-wasm = { git = "https://github.com/containerd/runwasi", rev = "7e978edeaf34b54efb895738357c805cf888b76d", features = ["cgroupsv2"] } +containerd-shim-wasm = { git = "https://github.com/containerd/runwasi", rev = "4d212b968d24d42a27952e8b04979382b543a613", features = ["cgroupsv2"] } libcontainer = { git = "https://github.com/containers/youki", rev = "09e67372a892f22a89eeef62ff429c3cbcac6d41", features = ["v1","v2"], default-features = false } log = "0.4" tokio = { version = "1", features = [ "full" ] } diff --git a/containerd-shim-slight-v1/src/executor.rs b/containerd-shim-slight-v1/src/executor.rs index 30680e49..2ba3a61e 100644 --- a/containerd-shim-slight-v1/src/executor.rs +++ b/containerd-shim-slight-v1/src/executor.rs @@ -1,29 +1,23 @@ use anyhow::{Context, Result}; +use containerd_shim_wasm::container::RuntimeContext; use std::path::PathBuf; use tokio::runtime::Runtime; -use containerd_shim_wasm::libcontainer_instance::LinuxContainerExecutor; +use containerd_shim_wasm::container::Engine; use containerd_shim_wasm::sandbox::Stdio; -use libcontainer::workload::{Executor, ExecutorError, ExecutorValidationError}; -use oci_spec::runtime::Spec; use slight_lib::commands::run::{handle_run, RunArgs}; -use utils::is_linux_executable; -#[derive(Clone)] -pub struct SlightExecutor { - stdio: Stdio, -} +#[derive(Clone, Default)] +pub struct SlightEngine; -impl SlightExecutor { - pub fn new(stdio: Stdio) -> Self { - Self { stdio } +impl Engine for SlightEngine { + fn name() -> &'static str { + "slight" } - fn wasm_exec(&self) -> anyhow::Result<()> { - self.stdio - .take() - .redirect() - .context("failed to redirect stdio")?; + fn run_wasi(&self, _ctx: &impl RuntimeContext, stdio: Stdio) -> Result { + log::info!("setting up wasi"); + stdio.redirect()?; let mod_path = PathBuf::from("/slightfile.toml"); let wasm_path = PathBuf::from("/app.wasm"); let rt = Runtime::new().context("failed to create runtime")?; @@ -33,26 +27,11 @@ impl SlightExecutor { io_redirects: None, link_all_capabilities: true, }; - rt.block_on(handle_run(args)) - } -} -impl Executor for SlightExecutor { - fn exec(&self, spec: &Spec) -> Result<(), ExecutorError> { - if is_linux_executable(spec).is_ok() { - log::info!("executing linux container"); - LinuxContainerExecutor::new(self.stdio.clone()).exec(spec) - } else { - if let Err(err) = self.wasm_exec() { - log::error!(" >>> error: {:?}", err); - std::process::exit(137); - } - log::info!(" >>> slight shut down: exiting"); - std::process::exit(0); + if let Err(err) = rt.block_on(handle_run(args)) { + log::error!(" >>> error: {:?}", err); + return Ok(137); } - } - - fn validate(&self, _spec: &Spec) -> Result<(), ExecutorValidationError> { - Ok(()) + Ok(0) } } diff --git a/containerd-shim-slight-v1/src/main.rs b/containerd-shim-slight-v1/src/main.rs index 08efa0f5..842be796 100644 --- a/containerd-shim-slight-v1/src/main.rs +++ b/containerd-shim-slight-v1/src/main.rs @@ -1,78 +1,12 @@ use std::env; -use std::option::Option; -use std::path::PathBuf; use containerd_shim as shim; -use containerd_shim_wasm::libcontainer_instance::LibcontainerInstance; -use containerd_shim_wasm::sandbox::instance::ExitCode; -use containerd_shim_wasm::sandbox::instance_utils::determine_rootdir; -use containerd_shim_wasm::sandbox::stdio::Stdio; -use containerd_shim_wasm::sandbox::{error::Error, InstanceConfig, ShimCli}; -use executor::SlightExecutor; -use libcontainer::container::builder::ContainerBuilder; -use libcontainer::container::Container; -use libcontainer::syscall::syscall::SyscallType; +use containerd_shim_wasm::{container::Instance, sandbox::ShimCli}; +use executor::SlightEngine; mod executor; -static DEFAULT_CONTAINER_ROOT_DIR: &str = "/run/containerd/slight"; - -pub struct Wasi { - exit_code: ExitCode, - id: String, - stdio: Stdio, - bundle: String, - rootdir: PathBuf, -} - -impl LibcontainerInstance for Wasi { - type Engine = (); - fn new_libcontainer(id: String, cfg: Option<&InstanceConfig>) -> Self { - log::info!(">>> new instance"); - let cfg = cfg.unwrap(); - let bundle = cfg.get_bundle().unwrap_or_default(); - let rootdir = determine_rootdir( - bundle.as_str(), - cfg.get_namespace().as_str(), - DEFAULT_CONTAINER_ROOT_DIR, - ) - .unwrap(); - Wasi { - exit_code: Default::default(), - id, - stdio: Stdio::init_from_cfg(cfg).expect("failed to open stdio"), - bundle, - rootdir, - } - } - - fn get_exit_code(&self) -> ExitCode { - self.exit_code.clone() - } - - fn get_id(&self) -> String { - self.id.clone() - } - - fn get_root_dir(&self) -> std::result::Result { - Ok(self.rootdir.clone()) - } - - fn build_container(&self) -> std::result::Result { - let err_others = |err| Error::Others(format!("failed to create container: {}", err)); - let slight_executor = SlightExecutor::new(self.stdio.take()); - let container = ContainerBuilder::new(self.id.clone(), SyscallType::Linux) - .with_executor(slight_executor) - .with_root_path(self.rootdir.clone()) - .map_err(err_others)? - .as_init(&self.bundle) - .with_systemd(false) - .with_detach(true) - .build() - .map_err(err_others)?; - Ok(container) - } -} +pub type SlightInstance = Instance; fn parse_version() { let os_args: Vec<_> = env::args_os().collect(); @@ -89,5 +23,5 @@ fn parse_version() { fn main() { parse_version(); - shim::run::>("io.containerd.slight.v1", None); + shim::run::>("io.containerd.slight.v1", None); } diff --git a/containerd-shim-spin-v1/Cargo.lock b/containerd-shim-spin-v1/Cargo.lock index d2c02c2c..ea29e188 100644 --- a/containerd-shim-spin-v1/Cargo.lock +++ b/containerd-shim-spin-v1/Cargo.lock @@ -788,7 +788,7 @@ dependencies = [ "containerd-shim", "containerd-shim-wasm", "libc", - "libcontainer", + "libcontainer 0.1.0", "log", "nix 0.26.4", "oci-spec", @@ -813,7 +813,7 @@ dependencies = [ [[package]] name = "containerd-shim-wasm" version = "0.2.1" -source = "git+https://github.com/containerd/runwasi?rev=7e978edeaf34b54efb895738357c805cf888b76d#7e978edeaf34b54efb895738357c805cf888b76d" +source = "git+https://github.com/containerd/runwasi?rev=4d212b968d24d42a27952e8b04979382b543a613#4d212b968d24d42a27952e8b04979382b543a613" dependencies = [ "anyhow", "caps", @@ -823,7 +823,7 @@ dependencies = [ "containerd-shim", "crossbeam", "libc", - "libcontainer", + "libcontainer 0.2.0", "log", "nix 0.26.4", "oci-spec", @@ -832,6 +832,7 @@ dependencies = [ "serde_json", "thiserror", "ttrpc", + "wat", "windows-sys 0.48.0", ] @@ -2274,6 +2275,21 @@ dependencies = [ "tracing", ] +[[package]] +name = "libcgroups" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ebc75981724e1f7e065582ddfb1ef41bbe82c2d3afa130777fc41d75f386a0c6" +dependencies = [ + "fixedbitset 0.4.2", + "nix 0.26.4", + "oci-spec", + "procfs", + "serde", + "thiserror", + "tracing", +] + [[package]] name = "libcontainer" version = "0.1.0" @@ -2285,7 +2301,34 @@ dependencies = [ "fastrand 2.0.0", "futures", "libc", - "libcgroups", + "libcgroups 0.1.0", + "nix 0.26.4", + "oci-spec", + "once_cell", + "prctl", + "procfs", + "regex", + "rust-criu", + "safe-path", + "serde", + "serde_json", + "thiserror", + "tracing", +] + +[[package]] +name = "libcontainer" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0a122c3ce58c5a705d3e71809816ab6726dfd37621d8e55bfd5f33dac213c713" +dependencies = [ + "bitflags 2.4.0", + "caps", + "chrono", + "fastrand 2.0.0", + "futures", + "libc", + "libcgroups 0.2.0", "nix 0.26.4", "oci-spec", "once_cell", diff --git a/containerd-shim-spin-v1/Cargo.toml b/containerd-shim-spin-v1/Cargo.toml index c13d9880..7798bbda 100644 --- a/containerd-shim-spin-v1/Cargo.toml +++ b/containerd-shim-spin-v1/Cargo.toml @@ -14,7 +14,7 @@ Containerd shim for running Spin workloads. chrono = "0.4" clap = { version = "4.3", features = ["derive", "env"] } containerd-shim = "0.5.0" -containerd-shim-wasm = { git = "https://github.com/containerd/runwasi", rev = "7e978edeaf34b54efb895738357c805cf888b76d", features = ["cgroupsv2"] } +containerd-shim-wasm = { git = "https://github.com/containerd/runwasi", rev = "4d212b968d24d42a27952e8b04979382b543a613", features = ["cgroupsv2"] } libcontainer = { git = "https://github.com/containers/youki", rev = "09e67372a892f22a89eeef62ff429c3cbcac6d41", features = ["v1","v2"], default-features = false } log = "0.4" spin-trigger = { git = "https://github.com/fermyon/spin", tag = "v1.4.1" } diff --git a/containerd-shim-spin-v1/src/executor.rs b/containerd-shim-spin-v1/src/executor.rs index e2c6001f..5f4d5113 100644 --- a/containerd-shim-spin-v1/src/executor.rs +++ b/containerd-shim-spin-v1/src/executor.rs @@ -1,35 +1,25 @@ +use std::net::SocketAddr; +use std::net::ToSocketAddrs; +use std::path::PathBuf; + use anyhow::{anyhow, Context, Result}; use log::info; use spin_manifest::Application; use spin_redis_engine::RedisTrigger; use spin_trigger::{loader, RuntimeConfig, TriggerExecutor, TriggerExecutorBuilder}; use spin_trigger_http::HttpTrigger; -use std::path::PathBuf; - use tokio::runtime::Runtime; use url::Url; use wasmtime::OptLevel; -use containerd_shim_wasm::libcontainer_instance::LinuxContainerExecutor; -use containerd_shim_wasm::sandbox::Stdio; -use libcontainer::workload::{Executor, ExecutorError, ExecutorValidationError}; -use oci_spec::runtime::Spec; -use utils::is_linux_executable; - -use crate::{parse_addr, SPIN_ADDR}; +use containerd_shim_wasm::{container::Engine, sandbox::Stdio}; -#[derive(Clone)] -pub struct SpinExecutor { - stdio: Stdio, -} +const SPIN_ADDR: &str = "0.0.0.0:80"; -impl SpinExecutor { - pub fn new(stdio: Stdio) -> Self { - Self { stdio } - } -} +#[derive(Clone, Default)] +pub struct SpinEngine; -impl SpinExecutor { +impl SpinEngine { async fn build_spin_application( mod_path: PathBuf, working_dir: PathBuf, @@ -65,16 +55,10 @@ impl SpinExecutor { Ok(executor) } - fn wasm_exec(&self, _spec: &Spec) -> Result<()> { - log::info!("executing spin container"); - let rt = Runtime::new().context("failed to create runtime")?; - rt.block_on(self.wasm_exec_async()) - } - async fn wasm_exec_async(&self) -> Result<()> { info!(" >>> building spin application"); let app = - SpinExecutor::build_spin_application(PathBuf::from("/spin.toml"), PathBuf::from("/")) + SpinEngine::build_spin_application(PathBuf::from("/spin.toml"), PathBuf::from("/")) .await .context("failed to build spin application")?; @@ -84,7 +68,7 @@ impl SpinExecutor { let f = match trigger { spin_manifest::ApplicationTrigger::Http(_config) => { let http_trigger: HttpTrigger = - SpinExecutor::build_spin_trigger(PathBuf::from("/"), app) + SpinEngine::build_spin_trigger(PathBuf::from("/"), app) .await .context("failed to build spin trigger")?; info!(" >>> running spin trigger"); @@ -96,7 +80,7 @@ impl SpinExecutor { } spin_manifest::ApplicationTrigger::Redis(_config) => { let redis_trigger: RedisTrigger = - SpinExecutor::build_spin_trigger(PathBuf::from("/"), app) + SpinEngine::build_spin_trigger(PathBuf::from("/"), app) .await .context("failed to build spin trigger")?; @@ -111,22 +95,44 @@ impl SpinExecutor { } } -impl Executor for SpinExecutor { - fn exec(&self, spec: &Spec) -> Result<(), ExecutorError> { - if is_linux_executable(spec).is_ok() { - log::info!("executing linux container"); - LinuxContainerExecutor::new(self.stdio.clone()).exec(spec) - } else { - if let Err(err) = self.wasm_exec(spec) { - log::info!(" >>> server shut down due to error: {err}"); - std::process::exit(137); - } - log::info!(" >>> server shut down: exiting"); - std::process::exit(0); +impl Engine for SpinEngine { + fn name() -> &'static str { + "spin" + } + + fn run_wasi( + &self, + _ctx: &impl containerd_shim_wasm::container::RuntimeContext, + stdio: Stdio, + ) -> Result { + log::info!("setting up wasi"); + stdio.redirect()?; + let rt = Runtime::new().context("failed to create runtime")?; + + if let Err(err) = rt.block_on(self.wasm_exec_async()) { + log::error!(" >>> error: {:?}", err); + return Ok(137); } + Ok(0) } +} + +fn parse_addr(addr: &str) -> Result { + let addrs: SocketAddr = addr + .to_socket_addrs()? + .next() + .ok_or_else(|| anyhow!("could not parse address: {}", addr))?; + Ok(addrs) +} + +#[cfg(test)] +mod tests { + use super::*; - fn validate(&self, _spec: &Spec) -> Result<(), ExecutorValidationError> { - Ok(()) + #[test] + fn can_parse_spin_address() { + let parsed = parse_addr(SPIN_ADDR).unwrap(); + assert_eq!(parsed.clone().port(), 80); + assert_eq!(parsed.ip().to_string(), "0.0.0.0"); } } diff --git a/containerd-shim-spin-v1/src/main.rs b/containerd-shim-spin-v1/src/main.rs index b51c8c2e..81c71c7b 100644 --- a/containerd-shim-spin-v1/src/main.rs +++ b/containerd-shim-spin-v1/src/main.rs @@ -1,91 +1,13 @@ use std::env; -use std::net::SocketAddr; -use std::net::ToSocketAddrs; -use std::option::Option; -use std::path::PathBuf; -use std::sync::{Arc, Condvar, Mutex}; -use anyhow::{anyhow, Result}; use containerd_shim as shim; -use containerd_shim_wasm::libcontainer_instance::LibcontainerInstance; -use containerd_shim_wasm::sandbox::instance::ExitCode; -use containerd_shim_wasm::sandbox::instance_utils::determine_rootdir; -use containerd_shim_wasm::sandbox::stdio::Stdio; -use containerd_shim_wasm::sandbox::{error::Error, InstanceConfig, ShimCli}; -use executor::SpinExecutor; -use libcontainer::container::builder::ContainerBuilder; -use libcontainer::container::Container; -use libcontainer::syscall::syscall::SyscallType; +use containerd_shim_wasm::container::Instance; +use containerd_shim_wasm::sandbox::ShimCli; +use executor::SpinEngine; mod executor; -const SPIN_ADDR: &str = "0.0.0.0:80"; -static DEFAULT_CONTAINER_ROOT_DIR: &str = "/run/containerd/spin"; - -pub struct Wasi { - exit_code: ExitCode, - id: String, - stdio: Stdio, - bundle: String, - rootdir: PathBuf, -} - -impl LibcontainerInstance for Wasi { - type Engine = (); - - fn new_libcontainer(id: String, cfg: Option<&InstanceConfig>) -> Self { - let cfg = cfg.unwrap(); - let bundle = cfg.get_bundle().unwrap_or_default(); - let rootdir = determine_rootdir( - bundle.as_str(), - cfg.get_namespace().as_str(), - DEFAULT_CONTAINER_ROOT_DIR, - ) - .unwrap(); - Wasi { - exit_code: Arc::new((Mutex::new(None), Condvar::new())), - id, - stdio: Stdio::init_from_cfg(cfg).expect("failed to open stdio"), - bundle: cfg.get_bundle().unwrap_or_default(), - rootdir, - } - } - - fn get_exit_code(&self) -> ExitCode { - self.exit_code.clone() - } - - fn get_id(&self) -> String { - self.id.clone() - } - - fn get_root_dir(&self) -> std::result::Result { - Ok(self.rootdir.clone()) - } - - fn build_container(&self) -> std::result::Result { - let err_others = |err| Error::Others(format!("failed to create container: {}", err)); - let spin_executor = SpinExecutor::new(self.stdio.take()); - let container = ContainerBuilder::new(self.id.clone(), SyscallType::Linux) - .with_executor(spin_executor) - .with_root_path(self.rootdir.clone()) - .map_err(err_others)? - .as_init(&self.bundle) - .with_systemd(false) - .with_detach(true) - .build() - .map_err(err_others)?; - Ok(container) - } -} - -fn parse_addr(addr: &str) -> Result { - let addrs: SocketAddr = addr - .to_socket_addrs()? - .next() - .ok_or_else(|| anyhow!("could not parse address: {}", addr))?; - Ok(addrs) -} +pub type SpinInstance = Instance; fn parse_version() { let os_args: Vec<_> = env::args_os().collect(); @@ -101,17 +23,5 @@ fn parse_version() { fn main() { parse_version(); - shim::run::>("io.containerd.spin.v1", None); -} - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn can_parse_spin_address() { - let parsed = parse_addr(SPIN_ADDR).unwrap(); - assert_eq!(parsed.clone().port(), 80); - assert_eq!(parsed.ip().to_string(), "0.0.0.0"); - } + shim::run::>("io.containerd.spin.v1", None); } diff --git a/containerd-shim-wws-v1/Cargo.lock b/containerd-shim-wws-v1/Cargo.lock index 5ad32c5b..0cee5a6b 100644 --- a/containerd-shim-wws-v1/Cargo.lock +++ b/containerd-shim-wws-v1/Cargo.lock @@ -771,7 +771,7 @@ dependencies = [ [[package]] name = "containerd-shim-wasm" version = "0.2.1" -source = "git+https://github.com/containerd/runwasi?rev=7e978edeaf34b54efb895738357c805cf888b76d#7e978edeaf34b54efb895738357c805cf888b76d" +source = "git+https://github.com/containerd/runwasi?rev=4d212b968d24d42a27952e8b04979382b543a613#4d212b968d24d42a27952e8b04979382b543a613" dependencies = [ "anyhow", "caps", @@ -781,7 +781,7 @@ dependencies = [ "containerd-shim", "crossbeam", "libc", - "libcontainer", + "libcontainer 0.2.0", "log", "nix 0.26.4", "oci-spec", @@ -790,6 +790,7 @@ dependencies = [ "serde_json", "thiserror", "ttrpc", + "wat", "windows-sys 0.48.0", ] @@ -802,7 +803,7 @@ dependencies = [ "containerd-shim", "containerd-shim-wasm", "libc", - "libcontainer", + "libcontainer 0.1.0", "log", "nix 0.26.4", "oci-spec", @@ -2010,6 +2011,21 @@ dependencies = [ "tracing", ] +[[package]] +name = "libcgroups" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ebc75981724e1f7e065582ddfb1ef41bbe82c2d3afa130777fc41d75f386a0c6" +dependencies = [ + "fixedbitset 0.4.2", + "nix 0.26.4", + "oci-spec", + "procfs", + "serde", + "thiserror", + "tracing", +] + [[package]] name = "libcontainer" version = "0.1.0" @@ -2021,7 +2037,34 @@ dependencies = [ "fastrand", "futures", "libc", - "libcgroups", + "libcgroups 0.1.0", + "nix 0.26.4", + "oci-spec", + "once_cell", + "prctl", + "procfs", + "regex", + "rust-criu", + "safe-path", + "serde", + "serde_json", + "thiserror", + "tracing", +] + +[[package]] +name = "libcontainer" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0a122c3ce58c5a705d3e71809816ab6726dfd37621d8e55bfd5f33dac213c713" +dependencies = [ + "bitflags 2.4.0", + "caps", + "chrono", + "fastrand", + "futures", + "libc", + "libcgroups 0.2.0", "nix 0.26.4", "oci-spec", "once_cell", diff --git a/containerd-shim-wws-v1/Cargo.toml b/containerd-shim-wws-v1/Cargo.toml index bd3eda7f..7f795048 100644 --- a/containerd-shim-wws-v1/Cargo.toml +++ b/containerd-shim-wws-v1/Cargo.toml @@ -14,7 +14,7 @@ Containerd shim for running Wasm Workers Server workloads. [dependencies] containerd-shim = "0.5.0" -containerd-shim-wasm = { git = "https://github.com/containerd/runwasi", rev = "7e978edeaf34b54efb895738357c805cf888b76d", features = ["cgroupsv2"] } +containerd-shim-wasm = { git = "https://github.com/containerd/runwasi", rev = "4d212b968d24d42a27952e8b04979382b543a613", features = ["cgroupsv2"] } libcontainer = { git = "https://github.com/containers/youki", rev = "09e67372a892f22a89eeef62ff429c3cbcac6d41", features = ["v1","v2"], default-features = false } wasm-workers-server = { git = "https://github.com/vmware-labs/wasm-workers-server", tag = "v1.5.0" } log = "0.4" diff --git a/containerd-shim-wws-v1/src/executor.rs b/containerd-shim-wws-v1/src/executor.rs index 05e50415..0d13a597 100644 --- a/containerd-shim-wws-v1/src/executor.rs +++ b/containerd-shim-wws-v1/src/executor.rs @@ -3,10 +3,10 @@ use log::{error, info}; use std::path::Path; use tokio::runtime::Runtime; -use containerd_shim_wasm::{libcontainer_instance::LinuxContainerExecutor, sandbox::Stdio}; -use libcontainer::workload::{Executor, ExecutorError, ExecutorValidationError}; -use oci_spec::runtime::Spec; -use utils::is_linux_executable; +use containerd_shim_wasm::{ + container::{Engine, RuntimeContext}, + sandbox::Stdio, +}; use wasm_workers_server::{ wws_config::Config, wws_router::Routes, @@ -17,20 +17,33 @@ use wasm_workers_server::{ const WWS_ADDR: &str = "0.0.0.0"; const WWS_PORT: u16 = 3000; -#[derive(Clone)] -pub struct WwsExecutor { - pub stdio: Stdio, -} +#[derive(Clone, Default)] +pub struct WwsEngine; -impl WwsExecutor { - pub fn new(stdio: Stdio) -> Self { - Self { stdio } +impl WwsEngine { + async fn wasm_exec_async(&self, root: &Path, routes: Routes) -> Result<()> { + let server = serve(ServeOptions { + root_path: root.to_path_buf(), + base_routes: routes, + hostname: WWS_ADDR.to_string(), + port: WWS_PORT, + panel: Panel::Disabled, + cors_origins: None, + }) + .await?; + info!(" >>> notifying main thread we are about to start"); + Ok(server.await?) } +} - fn wasm_exec(&self, _spec: &Spec) -> anyhow::Result<()> { - let stderr = self.stdio.take().stderr; - stderr.redirect().context("redirecting stdio")?; +impl Engine for WwsEngine { + fn name() -> &'static str { + "wws" + } + fn run_wasi(&self, _ctx: &impl RuntimeContext, stdio: Stdio) -> Result { + log::info!("setting up wasi"); + stdio.redirect()?; let path = Path::new("/"); let config = Config::load(path).unwrap_or_else(|err| { @@ -48,39 +61,11 @@ impl WwsExecutor { let routes = Routes::new(path, "", Vec::new(), &config); let rt = Runtime::new().context("failed to create runtime")?; - rt.block_on(self.wasm_exec_async(path, routes)) - } - async fn wasm_exec_async(&self, root: &Path, routes: Routes) -> Result<()> { - let server = serve(ServeOptions { - root_path: root.to_path_buf(), - base_routes: routes, - hostname: WWS_ADDR.to_string(), - port: WWS_PORT, - panel: Panel::Disabled, - cors_origins: None, - }).await?; - info!(" >>> notifying main thread we are about to start"); - Ok(server.await?) - } -} - -impl Executor for WwsExecutor { - fn exec(&self, spec: &Spec) -> Result<(), ExecutorError> { - if is_linux_executable(spec).is_ok() { - log::info!("executing linux container"); - LinuxContainerExecutor::new(self.stdio.clone()).exec(spec) - } else { - if let Err(err) = self.wasm_exec(spec) { - log::info!(" >>> server shut down due to error: {err}"); - std::process::exit(137); - } - log::info!(" >>> server shut down: exiting"); - std::process::exit(0); + if let Err(e) = rt.block_on(self.wasm_exec_async(path, routes)) { + log::error!(" >>> error: {:?}", e); + return Ok(137); } - } - - fn validate(&self, _spec: &Spec) -> Result<(), ExecutorValidationError> { - Ok(()) + Ok(0) } } diff --git a/containerd-shim-wws-v1/src/main.rs b/containerd-shim-wws-v1/src/main.rs index 3db75c12..c8f1f561 100644 --- a/containerd-shim-wws-v1/src/main.rs +++ b/containerd-shim-wws-v1/src/main.rs @@ -1,79 +1,13 @@ -use containerd_shim as shim; -use containerd_shim_wasm::libcontainer_instance::LibcontainerInstance; -use containerd_shim_wasm::sandbox::instance::ExitCode; -use containerd_shim_wasm::sandbox::instance_utils::determine_rootdir; -use containerd_shim_wasm::sandbox::Stdio; -use containerd_shim_wasm::sandbox::{error::Error, InstanceConfig, ShimCli}; -use executor::WwsExecutor; -use libcontainer::container::builder::ContainerBuilder; -use libcontainer::container::Container; -use libcontainer::syscall::syscall::SyscallType; use std::env; -use std::option::Option; -use std::path::PathBuf; - -mod executor; -static DEFAULT_CONTAINER_ROOT_DIR: &str = "/run/containerd/wws"; - -pub struct Workers { - exit_code: ExitCode, - id: String, - stdio: Stdio, - bundle: String, - rootdir: PathBuf, -} - -/// Implement the "default" interface from runwasi -impl LibcontainerInstance for Workers { - type Engine = (); - fn new_libcontainer(id: String, cfg: Option<&InstanceConfig>) -> Self { - log::info!("[wws] new instance"); - let cfg = cfg.unwrap(); - let bundle = cfg.get_bundle().unwrap_or_default(); - let rootdir = determine_rootdir( - bundle.as_str(), - cfg.get_namespace().as_str(), - DEFAULT_CONTAINER_ROOT_DIR, - ) - .unwrap(); - Workers { - exit_code: Default::default(), - id, - stdio: Stdio::init_from_cfg(cfg).expect("failed to open stdio"), - bundle, - rootdir, - } - } - - fn get_exit_code(&self) -> ExitCode { - self.exit_code.clone() - } - - fn get_id(&self) -> String { - self.id.clone() - } - - fn get_root_dir(&self) -> std::result::Result { - Ok(self.rootdir.clone()) - } +use containerd_shim as shim; +use containerd_shim_wasm::container::Instance; +use containerd_shim_wasm::sandbox::ShimCli; +use executor::WwsEngine; - fn build_container(&self) -> std::result::Result { - let err_others = |err| Error::Others(format!("failed to create container: {}", err)); - let wws_executor = WwsExecutor::new(self.stdio.take()); +mod executor; - let container = ContainerBuilder::new(self.id.clone(), SyscallType::Linux) - .with_executor(wws_executor) - .with_root_path(self.rootdir.clone()) - .map_err(err_others)? - .as_init(&self.bundle) - .with_systemd(false) - .with_detach(true) - .build() - .map_err(err_others)?; - Ok(container) - } -} +pub type WwsInstance = Instance; fn parse_version() { let os_args: Vec<_> = env::args_os().collect(); @@ -90,5 +24,5 @@ fn parse_version() { fn main() { parse_version(); - shim::run::>("io.containerd.wws.v1", None); + shim::run::>("io.containerd.wws.v1", None); }