diff --git a/Makefile b/Makefile index 60b3273f..147e9e0a 100644 --- a/Makefile +++ b/Makefile @@ -9,6 +9,14 @@ INSTALL_DIR := /var/lib/kuasar BIN_DIR := /usr/local/bin SYSTEMD_SERVICE_DIR := /usr/lib/systemd/system SYSTEMD_CONF_DIR := /etc/sysconfig +ENABLE_YOUKI ?= false +RUNC_FEATURES = +VMM_TASK_FEATURES = + +ifeq ($(ENABLE_YOUKI), true) + RUNC_FEATURES = youki + VMM_TASK_FEATURES = youki +endif .PHONY: vmm wasm quark clean all install-vmm install-wasm install-quark install \ bin/vmm-sandboxer bin/vmm-task bin/vmlinux.bin bin/kuasar.img bin/kuasar.initrd \ @@ -21,7 +29,7 @@ bin/vmm-sandboxer: @mkdir -p bin && cp vmm/sandbox/target/release/${HYPERVISOR} bin/vmm-sandboxer bin/vmm-task: - @cd vmm/task && cargo build --release --target=${ARCH}-unknown-linux-musl + @cd vmm/task && cargo build --release --target=${ARCH}-unknown-linux-musl --features=${VMM_TASK_FEATURES} @mkdir -p bin && cp vmm/task/target/${ARCH}-unknown-linux-musl/release/vmm-task bin/vmm-task bin/vmlinux.bin: @@ -45,7 +53,7 @@ bin/quark-sandboxer: @mkdir -p bin && cp quark/target/release/quark-sandboxer bin/quark-sandboxer bin/runc-sandboxer: - @cd runc && cargo build --release + @cd runc && cargo build --release --features=${RUNC_FEATURES} @mkdir -p bin && cp runc/target/release/runc-sandboxer bin/runc-sandboxer wasm: bin/wasm-sandboxer diff --git a/vmm/task/Cargo.lock b/vmm/task/Cargo.lock index 573d0a22..93c44937 100644 --- a/vmm/task/Cargo.lock +++ b/vmm/task/Cargo.lock @@ -17,6 +17,12 @@ version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" +[[package]] +name = "adler2" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "512761e0bb2578dd7380c6baaa0f4ce03e84f95e960231d1dec8bf4d7d6e2627" + [[package]] name = "aho-corasick" version = "1.0.2" @@ -26,6 +32,21 @@ dependencies = [ "memchr", ] +[[package]] +name = "android-tzdata" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e999941b234f3131b00bc13c22d06e8c5ff726d1b6318ac7eb276997bbb4fef0" + +[[package]] +name = "android_system_properties" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311" +dependencies = [ + "libc", +] + [[package]] name = "anyhow" version = "1.0.71" @@ -54,7 +75,7 @@ checksum = "16e62a023e7c117e27523144c5d2459f4397fcc3cab0085af8e2224f643a0193" dependencies = [ "proc-macro2", "quote", - "syn 2.0.18", + "syn 2.0.85", ] [[package]] @@ -65,7 +86,7 @@ checksum = "b9ccdd8f2a161be9bd5c023df56f1b2a0bd1d83872ae53b71a84a12c9bf6e842" dependencies = [ "proc-macro2", "quote", - "syn 2.0.18", + "syn 2.0.85", ] [[package]] @@ -83,7 +104,7 @@ dependencies = [ "async-trait", "axum-core 0.2.9", "bitflags 1.3.2", - "bytes 1.8.0", + "bytes 1.4.0", "futures-util", "http", "http-body", @@ -112,7 +133,7 @@ dependencies = [ "async-trait", "axum-core 0.3.4", "bitflags 1.3.2", - "bytes 1.8.0", + "bytes 1.4.0", "futures-util", "http", "http-body", @@ -138,7 +159,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "37e5939e02c56fecd5c017c37df4238c0a839fa76b7f97acdd7efb804fd181cc" dependencies = [ "async-trait", - "bytes 1.8.0", + "bytes 1.4.0", "futures-util", "http", "http-body", @@ -154,7 +175,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "759fa577a247914fd3f7f76d62972792636412fbfd634cd452f6a385a74d2d2c" dependencies = [ "async-trait", - "bytes 1.8.0", + "bytes 1.4.0", "futures-util", "http", "http-body", @@ -174,7 +195,7 @@ dependencies = [ "cc", "cfg-if 1.0.0", "libc", - "miniz_oxide", + "miniz_oxide 0.7.2", "object", "rustc-demangle", ] @@ -233,15 +254,28 @@ dependencies = [ [[package]] name = "bytes" -version = "1.8.0" +version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ac0150caa2ae65ca5bd83f25c7de183dea78d4d366469f148435e2acfbad0da" +checksum = "89b2fd2a0dcf38d7971e2194b6b6eebab45ae01067456a7fd93d5547a61b70be" + +[[package]] +name = "caps" +version = "0.5.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "190baaad529bcfbde9e1a19022c42781bdb6ff9de25721abdb8fd98c0807730b" +dependencies = [ + "libc", + "thiserror", +] [[package]] name = "cc" -version = "1.0.79" +version = "1.1.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "50d30906286121d95be3d479533b458f87493b30a4b5f79a607db8f5d11aa91f" +checksum = "c2e7962b54006dcfcc61cb72735f4d89bb97061dd6a7ed882ec6b8ee53714c6f" +dependencies = [ + "shlex", +] [[package]] name = "cfg-if" @@ -273,6 +307,19 @@ dependencies = [ "regex", ] +[[package]] +name = "chrono" +version = "0.4.38" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a21f936df1771bf62b77f047b726c4625ff2e8aa607c01ec06e5a05bd8463401" +dependencies = [ + "android-tzdata", + "iana-time-zone", + "num-traits", + "serde", + "windows-targets 0.52.6", +] + [[package]] name = "cmake" version = "0.1.50" @@ -306,7 +353,7 @@ dependencies = [ "libc", "log", "nix 0.23.2", - "oci-spec", + "oci-spec 0.5.8", "pin-project-lite", "prost 0.10.4", "prost-types 0.10.1", @@ -336,7 +383,7 @@ dependencies = [ "libc", "log", "nix 0.28.0", - "oci-spec", + "oci-spec 0.5.8", "page_size", "pin-project-lite", "prctl", @@ -363,6 +410,21 @@ dependencies = [ "ttrpc-codegen 0.4.2", ] +[[package]] +name = "core-foundation-sys" +version = "0.8.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b" + +[[package]] +name = "crc32fast" +version = "1.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a97769d94ddab943e4510d138150169a2758b5ef3eb191a9ee688de3e23ef7b3" +dependencies = [ + "cfg-if 1.0.0", +] + [[package]] name = "crossbeam" version = "0.8.2" @@ -436,8 +498,18 @@ version = "0.14.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7b750cb3417fd1b327431a470f388520309479ab0bf5e323505daf0290cd3850" dependencies = [ - "darling_core", - "darling_macro", + "darling_core 0.14.4", + "darling_macro 0.14.4", +] + +[[package]] +name = "darling" +version = "0.20.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6f63b86c8a8826a49b8c21f08a2d07338eec8d900540f8630dc76284be802989" +dependencies = [ + "darling_core 0.20.10", + "darling_macro 0.20.10", ] [[package]] @@ -450,21 +522,46 @@ dependencies = [ "ident_case", "proc-macro2", "quote", - "strsim", + "strsim 0.10.0", "syn 1.0.109", ] +[[package]] +name = "darling_core" +version = "0.20.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "95133861a8032aaea082871032f5815eb9e98cef03fa916ab4500513994df9e5" +dependencies = [ + "fnv", + "ident_case", + "proc-macro2", + "quote", + "strsim 0.11.1", + "syn 2.0.85", +] + [[package]] name = "darling_macro" version = "0.14.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a4aab4dbc9f7611d8b55048a3a16d2d010c2c8334e46304b40ac1cc14bf3b48e" dependencies = [ - "darling_core", + "darling_core 0.14.4", "quote", "syn 1.0.109", ] +[[package]] +name = "darling_macro" +version = "0.20.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d336a2a514f6ccccaa3e09b02d41d35330c07ddf03a62165fcec10bb561c7806" +dependencies = [ + "darling_core 0.20.10", + "quote", + "syn 2.0.85", +] + [[package]] name = "derive-new" version = "0.5.9" @@ -482,7 +579,16 @@ version = "0.11.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d07adf7be193b71cc36b193d0f5fe60b918a3a9db4dad0449f57bcfd519704a3" dependencies = [ - "derive_builder_macro", + "derive_builder_macro 0.11.2", +] + +[[package]] +name = "derive_builder" +version = "0.20.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "507dfb09ea8b7fa618fcf76e953f4f5e192547945816d5358edffe39f6f94947" +dependencies = [ + "derive_builder_macro 0.20.2", ] [[package]] @@ -491,22 +597,44 @@ version = "0.11.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1f91d4cfa921f1c05904dc3c57b4a32c38aed3340cce209f3a6fd1478babafc4" dependencies = [ - "darling", + "darling 0.14.4", "proc-macro2", "quote", "syn 1.0.109", ] +[[package]] +name = "derive_builder_core" +version = "0.20.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2d5bcf7b024d6835cfb3d473887cd966994907effbe9227e8c8219824d06c4e8" +dependencies = [ + "darling 0.20.10", + "proc-macro2", + "quote", + "syn 2.0.85", +] + [[package]] name = "derive_builder_macro" version = "0.11.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8f0314b72bed045f3a68671b3c86328386762c93f82d98c65c3cb5e5f573dd68" dependencies = [ - "derive_builder_core", + "derive_builder_core 0.11.2", "syn 1.0.109", ] +[[package]] +name = "derive_builder_macro" +version = "0.20.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ab63b0e2bf4d5928aff72e83a7dace85d7bba5fe12dcc3c5a572d78caffd3f3c" +dependencies = [ + "derive_builder_core 0.20.2", + "syn 2.0.85", +] + [[package]] name = "either" version = "1.8.1" @@ -521,7 +649,7 @@ checksum = "4bcfec3a70f97c962c307b2d2c56e358cf1d00b558d74262b5f929ee8cc7e73a" dependencies = [ "errno-dragonfly", "libc", - "windows-sys 0.48.0", + "windows-sys", ] [[package]] @@ -543,6 +671,12 @@ dependencies = [ "instant", ] +[[package]] +name = "fastrand" +version = "2.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e8c02a5121d4ea3eb16a80748c74f5549a5665e4c21333c6098f283870fbdea6" + [[package]] name = "fixedbitset" version = "0.2.0" @@ -555,6 +689,22 @@ version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0ce7134b9999ecaf8bcd65542e436736ef32ddca1b3e06094cb6ec5755203b80" +[[package]] +name = "fixedbitset" +version = "0.5.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d674e81391d1e1ab681a28d99df07927c6d4aa5b027d7da16ba32d1d21ecd99" + +[[package]] +name = "flate2" +version = "1.0.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1b589b4dc103969ad3cf85c950899926ec64300a1a46d76c03a6072957036f0" +dependencies = [ + "crc32fast", + "miniz_oxide 0.8.0", +] + [[package]] name = "fnv" version = "1.0.7" @@ -617,7 +767,7 @@ checksum = "89ca545a94061b6365f2c7355b4b32bd20df3ff95f02da9329b34ccc3bd6ee72" dependencies = [ "proc-macro2", "quote", - "syn 2.0.18", + "syn 2.0.85", ] [[package]] @@ -694,7 +844,7 @@ version = "0.3.19" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d357c7ae988e7d2182f7d7871d0b963962420b0678b0997ce7de72001aeab782" dependencies = [ - "bytes 1.8.0", + "bytes 1.4.0", "fnv", "futures-core", "futures-sink", @@ -728,11 +878,32 @@ version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" +[[package]] +name = "heck" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" + [[package]] name = "hermit-abi" -version = "0.3.9" +version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024" +checksum = "ee512640fe35acbfb4bb779db6f0d80704c2cacfa2e39b601ef3e3f47d1ae4c7" +dependencies = [ + "libc", +] + +[[package]] +name = "hermit-abi" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fed44880c466736ef9a5c5b5facefb5ed0785676d0c02d612db14e54f0d84286" + +[[package]] +name = "hex" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" [[package]] name = "http" @@ -740,7 +911,7 @@ version = "0.2.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bd6effc99afb63425aff9b05836f029929e345a6148a14b7ecd5ab67af944482" dependencies = [ - "bytes 1.8.0", + "bytes 1.4.0", "fnv", "itoa", ] @@ -751,7 +922,7 @@ version = "0.4.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d5f38f16d184e36f2408a55281cd658ecbd3ca05cce6d6510a176eca393e26d1" dependencies = [ - "bytes 1.8.0", + "bytes 1.4.0", "http", "pin-project-lite", ] @@ -780,7 +951,7 @@ version = "0.14.26" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ab302d72a6f11a3b910431ff93aae7e773078c769f0a3ef15fb9ec692ed147d4" dependencies = [ - "bytes 1.8.0", + "bytes 1.4.0", "futures-channel", "futures-core", "futures-util", @@ -791,7 +962,7 @@ dependencies = [ "httpdate", "itoa", "pin-project-lite", - "socket2 0.4.9", + "socket2", "tokio", "tower-service", "tracing", @@ -810,6 +981,29 @@ dependencies = [ "tokio-io-timeout", ] +[[package]] +name = "iana-time-zone" +version = "0.1.61" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "235e081f3925a06703c2d0117ea8b91f042756fd6e7a6e5d901e8ca1a996b220" +dependencies = [ + "android_system_properties", + "core-foundation-sys", + "iana-time-zone-haiku", + "js-sys", + "wasm-bindgen", + "windows-core", +] + +[[package]] +name = "iana-time-zone-haiku" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f31827a206f56af32e590ba56d5d2d085f558508192593743f16b2306495269f" +dependencies = [ + "cc", +] + [[package]] name = "ident_case" version = "1.0.1" @@ -841,9 +1035,9 @@ version = "1.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "eae7b9aee968036d54dce06cebaefd919e4472e753296daccd6d344e3e2df0c2" dependencies = [ - "hermit-abi", + "hermit-abi 0.3.1", "libc", - "windows-sys 0.48.0", + "windows-sys", ] [[package]] @@ -881,9 +1075,9 @@ checksum = "453ad9f582a441959e5f0d088b02ce04cfe8d51a8eaf077f12ac6d3e94164ca6" [[package]] name = "js-sys" -version = "0.3.70" +version = "0.3.72" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1868808506b929d7b0cfa8f75951347aa71bb21144b7791bae35d9bccfcfe37a" +checksum = "6a88f1bda2bd75b0452a14784937d796722fdebfe50df998aeb3f0b7603019a9" dependencies = [ "wasm-bindgen", ] @@ -896,9 +1090,48 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" [[package]] name = "libc" -version = "0.2.153" +version = "0.2.161" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c198f91728a82281a64e1f4f9eeb25d82cb32a5de251c6bd1b5154d63a8e7bd" +checksum = "8e9489c2807c139ffd9c1794f4af0ebe86a828db53ecdc7fea2111d0fed085d1" + +[[package]] +name = "libcgroups" +version = "0.4.1" +source = "git+https://github.com/containers/youki.git#6717cbcb2d883a5e5ebdf1e4fef3eac59c2b7091" +dependencies = [ + "fixedbitset 0.5.7", + "nix 0.28.0", + "oci-spec 0.7.0", + "procfs", + "serde", + "thiserror", + "tracing", +] + +[[package]] +name = "libcontainer" +version = "0.4.1" +source = "git+https://github.com/containers/youki.git#6717cbcb2d883a5e5ebdf1e4fef3eac59c2b7091" +dependencies = [ + "caps", + "chrono", + "fastrand 2.1.1", + "libc", + "libcgroups", + "nc", + "nix 0.28.0", + "oci-spec 0.7.0", + "once_cell", + "prctl", + "procfs", + "regex", + "rust-criu", + "safe-path", + "serde", + "serde_json", + "thiserror", + "tracing", +] [[package]] name = "linux-raw-sys" @@ -906,6 +1139,12 @@ version = "0.3.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ef53942eb7bf7ff43a617b3e2c1c4a5ecf5944a7c1bc12d7ee39bbb15e5c1519" +[[package]] +name = "linux-raw-sys" +version = "0.4.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "78b3ae25bc7c8c38cec158d1f2757ee79e9b3740fbc7ccf0e59e4b08d793fa89" + [[package]] name = "lock_api" version = "0.4.10" @@ -928,7 +1167,7 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8263075bb86c5a1b1427b5ae862e8889656f126e9f77c484496e8b47cf5c5558" dependencies = [ - "regex-automata", + "regex-automata 0.1.10", ] [[package]] @@ -945,9 +1184,9 @@ checksum = "0e7465ac9959cc2b1404e8e2367b43684a6d13790fe23056cc8c6c5a6b7bcb94" [[package]] name = "memchr" -version = "2.5.0" +version = "2.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d" +checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" [[package]] name = "memoffset" @@ -991,16 +1230,24 @@ dependencies = [ "adler", ] +[[package]] +name = "miniz_oxide" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2d80299ef12ff69b16a84bb182e3b9df68b5a91574d3d4fa6e41b65deec4df1" +dependencies = [ + "adler2", +] + [[package]] name = "mio" -version = "1.0.2" +version = "0.8.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "80e04d1dcff3aae0704555fe5fee3bcfaf3d1fdf8a7e521d5b9d2b42acb52cec" +checksum = "a4a650543ca06a924e8b371db273b2756685faae30f8487da1b56505a8f78b0c" dependencies = [ - "hermit-abi", "libc", "wasi", - "windows-sys 0.52.0", + "windows-sys", ] [[package]] @@ -1009,6 +1256,15 @@ version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e5ce46fe64a9d73be07dcbe690a38ce1b293be448fd8ce1e6c1b8062c9f72c6a" +[[package]] +name = "nc" +version = "0.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34566634a278b9af0f62b872339d884ea689982514825ba306705f264038144e" +dependencies = [ + "cc", +] + [[package]] name = "netlink-packet-core" version = "0.7.0" @@ -1052,7 +1308,7 @@ version = "0.11.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "86b33524dc0968bfad349684447bfce6db937a9ac3332a1fe60c0c5a5ce63f21" dependencies = [ - "bytes 1.8.0", + "bytes 1.4.0", "futures", "log", "netlink-packet-core", @@ -1079,7 +1335,7 @@ version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6471bf08e7ac0135876a9581bf3217ef0333c191c128d34878079f42ee150411" dependencies = [ - "bytes 1.8.0", + "bytes 1.4.0", "futures", "libc", "log", @@ -1181,11 +1437,21 @@ dependencies = [ "autocfg", ] +[[package]] +name = "num_cpus" +version = "1.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fac9e2da13b5eb447a6ce3d392f23a29d8694bff781bf03a16cd9ac8697593b" +dependencies = [ + "hermit-abi 0.2.6", + "libc", +] + [[package]] name = "num_threads" -version = "0.1.6" +version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2819ce041d2ee131036f4fc9d6ae7ae125a3a40e97ba64d04fe799ad9dabbb44" +checksum = "5c7398b9c8b70908f6371f47ed36737907c87c52af34c268fed0bf0ceb92ead9" dependencies = [ "libc", ] @@ -1205,18 +1471,34 @@ version = "0.5.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "98135224dd4faeb24c05a2fac911ed53ea6b09ecb09d7cada1cb79963ab2ee34" dependencies = [ - "derive_builder", + "derive_builder 0.11.2", + "getset", + "serde", + "serde_json", + "thiserror", +] + +[[package]] +name = "oci-spec" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5cee185ce7cf1cce45e194e34cd87c0bad7ff0aa2e8917009a2da4f7b31fb363" +dependencies = [ + "derive_builder 0.20.2", "getset", + "regex", "serde", "serde_json", + "strum", + "strum_macros", "thiserror", ] [[package]] name = "once_cell" -version = "1.18.0" +version = "1.20.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d" +checksum = "1261fe7e33c73b354eab43b1273a57c8f967d0391e80353e51f764ac02cf6775" [[package]] name = "opentelemetry" @@ -1323,7 +1605,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0ae859aa07428ca9a929b936690f8b12dc5f11dd8c6992a18ca93919f28bc177" dependencies = [ "libc", - "windows-sys 0.48.0", + "windows-sys", ] [[package]] @@ -1432,14 +1714,14 @@ checksum = "39407670928234ebc5e6e580247dd567ad73a3578460c5990f9503df207e8f07" dependencies = [ "proc-macro2", "quote", - "syn 2.0.18", + "syn 2.0.85", ] [[package]] name = "pin-project-lite" -version = "0.2.15" +version = "0.2.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "915a1e146535de9163f3987b8944ed8cf49a18bb0056bcebcdcece385cece4ff" +checksum = "e0a7ae3ac2f1173085d398531c705756c94a4c56843785df85a60c1a0afac116" [[package]] name = "pin-utils" @@ -1499,20 +1781,46 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.86" +version = "1.0.89" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5e719e8df665df0d1c8fbfd238015744736151d4445ec0836b8e628aae103b77" +checksum = "f139b0662de085916d1fb67d2b4169d1addddda1919e696f3252b740b629986e" dependencies = [ "unicode-ident", ] +[[package]] +name = "procfs" +version = "0.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "731e0d9356b0c25f16f33b5be79b1c57b562f141ebfcdb0ad8ac2c13a24293b4" +dependencies = [ + "bitflags 2.6.0", + "chrono", + "flate2", + "hex", + "lazy_static", + "procfs-core", + "rustix 0.38.25", +] + +[[package]] +name = "procfs-core" +version = "0.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2d3554923a69f4ce04c4a754260c338f505ce22642d3830e049a399fc2059a29" +dependencies = [ + "bitflags 2.6.0", + "chrono", + "hex", +] + [[package]] name = "prost" version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "de5e2533f59d08fcf364fd374ebda0692a70bd6d7e66ef97f306f45c6c5d8020" dependencies = [ - "bytes 1.8.0", + "bytes 1.4.0", "prost-derive 0.8.0", ] @@ -1522,7 +1830,7 @@ version = "0.10.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "71adf41db68aa0daaefc69bb30bcd68ded9b9abaad5d1fbb6304c4fb390e083e" dependencies = [ - "bytes 1.8.0", + "bytes 1.4.0", "prost-derive 0.10.1", ] @@ -1532,7 +1840,7 @@ version = "0.11.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0b82eaa1d779e9a4bc1c3217db8ffbeabaae1dca241bf70183242128d48681cd" dependencies = [ - "bytes 1.8.0", + "bytes 1.4.0", "prost-derive 0.11.9", ] @@ -1542,7 +1850,7 @@ version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "355f634b43cdd80724ee7848f95770e7e70eefa6dcf14fea676216573b8fd603" dependencies = [ - "bytes 1.8.0", + "bytes 1.4.0", "heck 0.3.3", "itertools", "log", @@ -1560,7 +1868,7 @@ version = "0.10.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8ae5a4388762d5815a9fc0dea33c56b021cdc8dde0c55e0c9ca57197254b0cab" dependencies = [ - "bytes 1.8.0", + "bytes 1.4.0", "cfg-if 1.0.0", "cmake", "heck 0.4.1", @@ -1621,7 +1929,7 @@ version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "603bbd6394701d13f3f25aada59c7de9d35a6a5887cfc156181234a44002771b" dependencies = [ - "bytes 1.8.0", + "bytes 1.4.0", "prost 0.8.0", ] @@ -1631,7 +1939,7 @@ version = "0.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2d0a014229361011dc8e69c8a1ec6c2e8d0f2af7c91e3ea3f5b2170298461e68" dependencies = [ - "bytes 1.8.0", + "bytes 1.4.0", "prost 0.10.4", ] @@ -1703,9 +2011,9 @@ dependencies = [ [[package]] name = "quote" -version = "1.0.28" +version = "1.0.37" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b9ab9c7eadfd8df19006f1cf1a4aed13540ed5cbc047010ece5826e10825488" +checksum = "b5b9d34b8991d19d98081b46eacdd8eb58c6f2b201139f7c5f643cc155a633af" dependencies = [ "proc-macro2", ] @@ -1751,13 +2059,14 @@ dependencies = [ [[package]] name = "regex" -version = "1.8.4" +version = "1.10.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d0ab3ca65655bb1e41f2a8c8cd662eb4fb035e67c3f78da1d61dffe89d07300f" +checksum = "4219d74c6b67a3654a9fbebc4b419e22126d13d2f3c4a07ee0cb61ff79a79619" dependencies = [ "aho-corasick", "memchr", - "regex-syntax 0.7.2", + "regex-automata 0.4.8", + "regex-syntax 0.8.5", ] [[package]] @@ -1769,6 +2078,17 @@ dependencies = [ "regex-syntax 0.6.29", ] +[[package]] +name = "regex-automata" +version = "0.4.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "368758f23274712b504848e9d5a6f010445cc8b87a7cdb4d7cbee666c1288da3" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax 0.8.5", +] + [[package]] name = "regex-syntax" version = "0.6.29" @@ -1777,9 +2097,9 @@ checksum = "f162c6dd7b008981e4d40210aca20b4bd0f9b60ca9271061b07f78537722f2e1" [[package]] name = "regex-syntax" -version = "0.7.2" +version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "436b050e76ed2903236f032a59761c1eb99e1b0aead2c257922771dab1fc8c78" +checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c" [[package]] name = "rtnetlink" @@ -1809,7 +2129,7 @@ dependencies = [ "libc", "log", "nix 0.25.1", - "oci-spec", + "oci-spec 0.5.8", "os_pipe", "path-absolutize", "rand", @@ -1823,6 +2143,18 @@ dependencies = [ "uuid", ] +[[package]] +name = "rust-criu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4737b28406b3395359f485127073117a11cedc8942738b69ba6ab9a79432acbc" +dependencies = [ + "anyhow", + "libc", + "protobuf 3.2.0", + "protobuf-codegen 3.2.0", +] + [[package]] name = "rustc-demangle" version = "0.1.24" @@ -1839,15 +2171,28 @@ dependencies = [ "errno", "io-lifetimes", "libc", - "linux-raw-sys", - "windows-sys 0.48.0", + "linux-raw-sys 0.3.8", + "windows-sys", +] + +[[package]] +name = "rustix" +version = "0.38.25" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc99bc2d4f1fed22595588a013687477aedf3cdcfb26558c559edb67b4d9b22e" +dependencies = [ + "bitflags 2.6.0", + "errno", + "libc", + "linux-raw-sys 0.4.14", + "windows-sys", ] [[package]] name = "rustversion" -version = "1.0.17" +version = "1.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "955d28af4278de8121b7ebeb796b6a45735dc01436d898801014aced2773a3d6" +checksum = "0e819f2bc632f285be6d7cd36e25940d45b2391dd6d9b939e79de557f7014248" [[package]] name = "ryu" @@ -1855,6 +2200,15 @@ version = "1.0.13" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f91339c0467de62360649f8d3e185ca8de4224ff281f66000de5eb2a77a79041" +[[package]] +name = "safe-path" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "980abdd3220aa19b67ca3ea07b173ca36383f18ae48cde696d90c8af39447ffb" +dependencies = [ + "libc", +] + [[package]] name = "scopeguard" version = "1.1.0" @@ -1878,7 +2232,7 @@ checksum = "8c805777e3930c8883389c602315a24224bcc738b63905ef87cd1420353ea93e" dependencies = [ "proc-macro2", "quote", - "syn 2.0.18", + "syn 2.0.85", ] [[package]] @@ -1901,6 +2255,12 @@ dependencies = [ "lazy_static", ] +[[package]] +name = "shlex" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" + [[package]] name = "signal-hook" version = "0.3.15" @@ -1943,9 +2303,9 @@ dependencies = [ [[package]] name = "smallvec" -version = "1.13.2" +version = "1.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67" +checksum = "a507befe795404456341dfab10cef66ead4c041f62b8b11bbb92bffe5d0953e0" [[package]] name = "socket2" @@ -1958,20 +2318,35 @@ dependencies = [ ] [[package]] -name = "socket2" -version = "0.5.7" +name = "strsim" +version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce305eb0b4296696835b71df73eb912e0f1ffd2556a501fcede6e0c50349191c" -dependencies = [ - "libc", - "windows-sys 0.52.0", -] +checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" [[package]] name = "strsim" -version = "0.10.0" +version = "0.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" +checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" + +[[package]] +name = "strum" +version = "0.26.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8fec0f0aef304996cf250b31b5a10dee7980c85da9d759361292b8bca5a18f06" + +[[package]] +name = "strum_macros" +version = "0.26.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4c6bee85a5a24955dc440386795aa378cd9cf82acd5f764469152d2270e581be" +dependencies = [ + "heck 0.5.0", + "proc-macro2", + "quote", + "rustversion", + "syn 2.0.85", +] [[package]] name = "syn" @@ -1986,9 +2361,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.18" +version = "2.0.85" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32d41677bcbe24c20c52e7c70b0d8db04134c5d1066bf98662e2871ad200ea3e" +checksum = "5023162dfcd14ef8f32034d8bcd4cc5ddc61ef7a247c024a33e24e1f24d21b56" dependencies = [ "proc-macro2", "quote", @@ -2009,30 +2384,30 @@ checksum = "31c0432476357e58790aaa47a8efb0c5138f137343f3b5f23bd36a27e3b0a6d6" dependencies = [ "autocfg", "cfg-if 1.0.0", - "fastrand", + "fastrand 1.9.0", "redox_syscall", - "rustix", - "windows-sys 0.48.0", + "rustix 0.37.19", + "windows-sys", ] [[package]] name = "thiserror" -version = "1.0.40" +version = "1.0.65" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "978c9a314bd8dc99be594bc3c175faaa9794be04a5a5e153caba6915336cebac" +checksum = "5d11abd9594d9b38965ef50805c5e469ca9cc6f197f883f717e0269a3057b3d5" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.40" +version = "1.0.65" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f9456a42c5b0d803c8cd86e73dd7cc9edd429499f37a3550d286d5e86720569f" +checksum = "ae71770322cbd277e69d762a16c444af02aa0575ac0d174f0b9562d3b37f8602" dependencies = [ "proc-macro2", "quote", - "syn 2.0.18", + "syn 2.0.85", ] [[package]] @@ -2058,20 +2433,21 @@ dependencies = [ [[package]] name = "tokio" -version = "1.41.0" +version = "1.28.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "145f3413504347a2be84393cc8a7d2fb4d863b375909ea59f2158261aa258bbb" +checksum = "94d7b1cfd2aa4011f2de74c2c4c63665e27a71006b0a192dcd2710272e73dfa2" dependencies = [ - "backtrace", - "bytes 1.8.0", + "autocfg", + "bytes 1.4.0", "libc", "mio", + "num_cpus", "parking_lot", "pin-project-lite", "signal-hook-registry", - "socket2 0.5.7", + "socket2", "tokio-macros", - "windows-sys 0.52.0", + "windows-sys", ] [[package]] @@ -2086,13 +2462,13 @@ dependencies = [ [[package]] name = "tokio-macros" -version = "2.4.0" +version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "693d596312e88961bc67d7f1f97af8a70227d9f90c31bba5806eec004978d752" +checksum = "630bdcf245f78637c13ec01ffae6187cca34625e8c63150d424b59e55af2675e" dependencies = [ "proc-macro2", "quote", - "syn 2.0.18", + "syn 2.0.85", ] [[package]] @@ -2107,9 +2483,9 @@ dependencies = [ [[package]] name = "tokio-stream" -version = "0.1.16" +version = "0.1.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4f4e6ce100d0eb49a2734f8c0812bcd324cf357d21810932c5df6b96ef2b86f1" +checksum = "397c988d37662c7dda6d2208364a706264bf3d6138b11d436cbac0ad38832842" dependencies = [ "futures-core", "pin-project-lite", @@ -2122,7 +2498,7 @@ version = "0.7.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "806fe8c2c87eccc8b3267cbae29ed3ab2d0bd37fca70ab622e46aaa9375ddb7d" dependencies = [ - "bytes 1.8.0", + "bytes 1.4.0", "futures-core", "futures-sink", "pin-project-lite", @@ -2153,7 +2529,7 @@ dependencies = [ "async-trait", "axum 0.5.17", "base64 0.13.1", - "bytes 1.8.0", + "bytes 1.4.0", "futures-core", "futures-util", "h2", @@ -2184,7 +2560,7 @@ dependencies = [ "async-trait", "axum 0.6.20", "base64 0.21.7", - "bytes 1.8.0", + "bytes 1.4.0", "futures-core", "futures-util", "h2", @@ -2243,7 +2619,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f873044bf02dd1e8239e9c1293ea39dad76dc594ec16185d0a1bf31d8dc8d858" dependencies = [ "bitflags 1.3.2", - "bytes 1.8.0", + "bytes 1.4.0", "futures-core", "futures-util", "http", @@ -2287,7 +2663,7 @@ checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.18", + "syn 2.0.85", ] [[package]] @@ -2519,13 +2895,15 @@ dependencies = [ "ipnetwork", "lazy_static", "libc", + "libcontainer", "log", "netlink-packet-core", "netlink-packet-route", "netlink-sys 0.7.0", "nix 0.28.0", - "oci-spec", + "oci-spec 0.5.8", "opentelemetry", + "os_pipe", "pin-project-lite", "protobuf 3.2.0", "rtnetlink", @@ -2535,6 +2913,7 @@ dependencies = [ "signal-hook-tokio", "time", "tokio", + "tokio-pipe", "tokio-vsock", "tracing", "tracing-opentelemetry", @@ -2571,9 +2950,9 @@ checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" [[package]] name = "wasm-bindgen" -version = "0.2.93" +version = "0.2.95" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a82edfc16a6c469f5f44dc7b571814045d60404b55a0ee849f9bcfa2e63dd9b5" +checksum = "128d1e363af62632b8eb57219c8fd7877144af57558fb2ef0368d0087bddeb2e" dependencies = [ "cfg-if 1.0.0", "once_cell", @@ -2582,24 +2961,24 @@ dependencies = [ [[package]] name = "wasm-bindgen-backend" -version = "0.2.93" +version = "0.2.95" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9de396da306523044d3302746f1208fa71d7532227f15e347e2d93e4145dd77b" +checksum = "cb6dd4d3ca0ddffd1dd1c9c04f94b868c37ff5fac97c30b97cff2d74fce3a358" dependencies = [ "bumpalo", "log", "once_cell", "proc-macro2", "quote", - "syn 2.0.18", + "syn 2.0.85", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-macro" -version = "0.2.93" +version = "0.2.95" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "585c4c91a46b072c92e908d99cb1dcdf95c5218eeb6f3bf1efa991ee7a68cccf" +checksum = "e79384be7f8f5a9dd5d7167216f022090cf1f9ec128e6e6a482a2cb5c5422c56" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -2607,22 +2986,22 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.93" +version = "0.2.95" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "afc340c74d9005395cf9dd098506f7f44e38f2b4a21c6aaacf9a105ea5e1e836" +checksum = "26c6ab57572f7a24a4985830b120de1594465e5d500f24afe89e16b4e833ef68" dependencies = [ "proc-macro2", "quote", - "syn 2.0.18", + "syn 2.0.85", "wasm-bindgen-backend", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-shared" -version = "0.2.93" +version = "0.2.95" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c62a0a307cb4a311d3a07867860911ca130c3494e8c2719593806c08bc5d0484" +checksum = "65fc09f10666a9f147042251e0dda9c18f166ff7de300607007e96bdebc1068d" [[package]] name = "which" @@ -2658,21 +3037,21 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" [[package]] -name = "windows-sys" -version = "0.48.0" +name = "windows-core" +version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" +checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9" dependencies = [ - "windows-targets 0.48.0", + "windows-targets 0.52.6", ] [[package]] name = "windows-sys" -version = "0.52.0" +version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" +checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" dependencies = [ - "windows-targets 0.52.6", + "windows-targets 0.48.0", ] [[package]] diff --git a/vmm/task/Cargo.toml b/vmm/task/Cargo.toml index d1c1c555..3f09a378 100644 --- a/vmm/task/Cargo.toml +++ b/vmm/task/Cargo.toml @@ -44,6 +44,12 @@ ttrpc = { version = "0.7", features = ["async"] } containerd-sandbox = { git = "https://github.com/kuasar-io/rust-extensions.git" } containerd-shim = { git = "https://github.com/kuasar-io/rust-extensions.git", features = ["async"] } runc = { git = "https://github.com/kuasar-io/rust-extensions.git", features = ["async"] } +libcontainer = { git="https://github.com/containers/youki.git", version="0.4.1", optional = true, default-features = false, features = ["v1", "v2", "systemd"] } +os_pipe = "1.0.0" +tokio-pipe = "0.2.12" [patch.crates-io] ttrpc = { git = "https://github.com/kuasar-io/ttrpc-rust.git", branch = "v0.7.1-kuasar" } + +[features] +youki = ["libcontainer"] diff --git a/vmm/task/src/container.rs b/vmm/task/src/container.rs index 96fbecd6..fd019570 100644 --- a/vmm/task/src/container.rs +++ b/vmm/task/src/container.rs @@ -54,7 +54,11 @@ use tokio::{ sync::Mutex, }; use tracing::instrument; -use vmm_common::{mount::get_mount_type, storage::Storage, KUASAR_STATE_DIR}; +use vmm_common::{ + mount::get_mount_type, + storage::{Storage, ANNOTATION_KEY_STORAGE}, + KUASAR_STATE_DIR, +}; use crate::{ device::rescan_pci_bus, @@ -65,8 +69,6 @@ use crate::{ pub const INIT_PID_FILE: &str = "init.pid"; -const STORAGE_ANNOTATION: &str = "io.kuasar.storages"; - pub type ExecProcess = ProcessTemplate; pub type InitProcess = ProcessTemplate; @@ -119,7 +121,7 @@ impl ContainerFactory for KuasarFactory { let bundle = format!("{}/{}", KUASAR_STATE_DIR, req.id); let spec: Spec = read_spec(&bundle).await?; let annotations = spec.annotations().clone().unwrap_or_default(); - let storages = if let Some(storage_str) = annotations.get(STORAGE_ANNOTATION) { + let storages = if let Some(storage_str) = annotations.get(ANNOTATION_KEY_STORAGE) { serde_json::from_str::>(storage_str)? } else { read_storages(&bundle, req.id()).await? diff --git a/vmm/task/src/debug.rs b/vmm/task/src/debug.rs index 094db50c..19c2c31c 100644 --- a/vmm/task/src/debug.rs +++ b/vmm/task/src/debug.rs @@ -26,7 +26,11 @@ use containerd_shim::{ }; use futures::StreamExt; use log::{debug, error}; -use nix::{pty::openpty, unistd::setsid}; +use nix::{ + pty::openpty, + sys::signal::{kill, Signal}, + unistd::{setsid, Pid}, +}; use tokio::process::Command; use tokio_vsock::VsockStream; @@ -79,6 +83,7 @@ pub async fn debug_console(stream: VsockStream) -> Result<()> { } } if let Some(id) = child.id() { + kill(Pid::from_raw(id as i32), Signal::SIGKILL).unwrap_or_default(); let exit_status = wait_pid(id as i32, s).await; debug!("debug console shell exit with {}", exit_status) } diff --git a/vmm/task/src/io.rs b/vmm/task/src/io.rs index 19a2c3fe..4ec5dd97 100644 --- a/vmm/task/src/io.rs +++ b/vmm/task/src/io.rs @@ -27,12 +27,12 @@ use std::{ task::{Context, Poll}, }; +#[cfg(not(feature = "youki"))] +use containerd_shim::util::IntoOption; use containerd_shim::{ asynchronous::{console::ConsoleSocket, processes::ProcessTemplate, util::asyncify}, io::Stdio, - io_error, other, - util::IntoOption, - Console, Error, ExitSignal, Result, + io_error, other, Console, Error, ExitSignal, Result, }; use log::{debug, error, warn}; use nix::{ @@ -42,7 +42,9 @@ use nix::{ termios::tcgetattr, }, }; -use runc::io::{IOOption, Io, NullIo, PipedIo, FIFO}; +use runc::io::Io; +#[cfg(not(feature = "youki"))] +use runc::io::{IOOption, NullIo, PipedIo, FIFO}; use tokio::{ fs::{File, OpenOptions}, io::{AsyncRead, AsyncReadExt, AsyncWrite, AsyncWriteExt, ReadBuf}, @@ -63,6 +65,7 @@ pub struct ProcessIO { const VSOCK: &str = "vsock"; const STREAMING: &str = "streaming"; +#[cfg(not(feature = "youki"))] pub fn create_io( id: &str, io_uid: u32, @@ -145,7 +148,7 @@ pub(crate) async fn copy_io_or_console

( Ok(()) } -async fn copy_console

( +pub async fn copy_console

( p: &ProcessTemplate

, console_socket: &ConsoleSocket, stdio: &Stdio, diff --git a/vmm/task/src/main.rs b/vmm/task/src/main.rs index f032bf8b..1076cdd1 100644 --- a/vmm/task/src/main.rs +++ b/vmm/task/src/main.rs @@ -58,6 +58,7 @@ use crate::{ }; mod config; +#[cfg(not(feature = "youki"))] mod container; mod debug; mod device; @@ -71,6 +72,8 @@ mod streaming; mod task; mod util; mod vsock; +#[cfg(feature = "youki")] +mod youki; const NAMESPACE: &str = "k8s.io"; diff --git a/vmm/task/src/task.rs b/vmm/task/src/task.rs index 22dfef70..3e94aa10 100644 --- a/vmm/task/src/task.rs +++ b/vmm/task/src/task.rs @@ -31,18 +31,28 @@ use log::{debug, error}; use oci_spec::runtime::{LinuxNamespaceType, Spec}; use tokio::sync::{mpsc::Sender, Mutex}; -use crate::{ - container::{KuasarContainer, KuasarFactory}, - sandbox::SandboxResources, - NAMESPACE, -}; +#[cfg(not(feature = "youki"))] +use crate::container::{KuasarContainer, KuasarFactory}; +#[cfg(feature = "youki")] +use crate::youki::{YoukiContainer, YoukiFactory}; +use crate::{sandbox::SandboxResources, NAMESPACE}; + +#[cfg(not(feature = "youki"))] +type Factory = KuasarFactory; +#[cfg(not(feature = "youki"))] +type RealContainer = KuasarContainer; + +#[cfg(feature = "youki")] +type Factory = YoukiFactory; +#[cfg(feature = "youki")] +type RealContainer = YoukiContainer; pub(crate) async fn create_task_service( tx: Sender<(String, Box)>, -) -> anyhow::Result> { +) -> anyhow::Result> { let sandbox = Arc::new(Mutex::new(SandboxResources::new().await)); let task = TaskService { - factory: KuasarFactory::new(sandbox), + factory: Factory::new(sandbox), containers: Arc::new(Default::default()), namespace: NAMESPACE.to_string(), exit: Arc::new(Default::default()), @@ -54,7 +64,7 @@ pub(crate) async fn create_task_service( Ok(task) } -async fn process_exits(s: Subscription, task: &TaskService) { +async fn process_exits(s: Subscription, task: &TaskService) { let containers = task.containers.clone(); let mut s = s; tokio::spawn(async move { diff --git a/vmm/task/src/youki.rs b/vmm/task/src/youki.rs new file mode 100644 index 00000000..2de09018 --- /dev/null +++ b/vmm/task/src/youki.rs @@ -0,0 +1,648 @@ +/* + Copyright The containerd Authors. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +use std::{ + convert::TryFrom, + os::fd::{FromRawFd, IntoRawFd, OwnedFd, RawFd}, + path::{Path, PathBuf}, + sync::Arc, +}; + +use async_trait::async_trait; +use containerd_shim::{ + api::{CreateTaskRequest, ExecProcessRequest, Options, Status}, + asynchronous::{ + console::ConsoleSocket, + container::{ContainerFactory, ContainerTemplate, ProcessFactory}, + processes::{ProcessLifecycle, ProcessTemplate}, + }, + io::Stdio, + io_error, other, other_error, + protos::{ + api::ProcessInfo, + cgroups::metrics::Metrics, + protobuf::{CodedInputStream, Message}, + }, + util::read_spec, + Error, ExitSignal, Result, +}; +use libcontainer::{ + container::{builder::ContainerBuilder, Container}, + error::LibcontainerError, + signal::Signal, + syscall::syscall::SyscallType, +}; +use log::{debug, warn}; +use nix::{ + sys::signal::kill, + unistd::{Gid, Pid, Uid}, +}; +use oci_spec::runtime::{LinuxResources, Process, Spec}; +use runc::io::{IOOption, Io, NullIo}; +use tokio::{ + io::{AsyncRead, AsyncWrite}, + process::Command, + sync::Mutex, + task::spawn_blocking, +}; +use vmm_common::{ + storage::{Storage, ANNOTATION_KEY_STORAGE}, + KUASAR_STATE_DIR, +}; + +use crate::{ + device::rescan_pci_bus, + io::{convert_stdio, copy_io_or_console, ProcessIO}, + sandbox::SandboxResources, + util::{read_io, read_storages}, +}; + +pub type ExecProcess = ProcessTemplate; +pub type InitProcess = ProcessTemplate; + +pub type YoukiContainer = ContainerTemplate; + +pub const YOUKI_DIR: &str = "/run/kuasar/youki"; + +#[derive(Clone)] +pub(crate) struct YoukiFactory { + sandbox: Arc>, +} + +#[async_trait] +impl ContainerFactory for YoukiFactory { + async fn create( + &self, + _ns: &str, + req: &CreateTaskRequest, + ) -> containerd_shim::Result { + rescan_pci_bus().await?; + let bundle = format!("{}/{}", KUASAR_STATE_DIR, req.id); + let spec: Spec = read_spec(&bundle).await?; + let annotations = spec.annotations().clone().unwrap_or_default(); + let storages = if let Some(storage_str) = annotations.get(ANNOTATION_KEY_STORAGE) { + serde_json::from_str::>(storage_str)? + } else { + read_storages(&bundle, req.id()).await? + }; + self.sandbox + .lock() + .await + .add_storages(req.id(), storages) + .await?; + let mut opts = Options::new(); + if let Some(any) = req.options.as_ref() { + let mut input = CodedInputStream::from_bytes(any.value.as_ref()); + opts.merge_from(&mut input)?; + } + if opts.compute_size() > 0 { + debug!("create options: {:?}", &opts); + } + + let id = req.id(); + + let stdio = match read_io(&bundle, req.id(), None).await { + Ok(io) => Stdio::new(&io.stdin, &io.stdout, &io.stderr, io.terminal), + Err(_) => Stdio::new(req.stdin(), req.stdout(), req.stderr(), req.terminal()), + }; + + // for qemu, the io path is pci address for virtio-serial + // that needs to be converted to the serial file path + let stdio = convert_stdio(&stdio).await?; + + let init = self.do_create(id, &stdio, &opts, &bundle).await?; + let container = YoukiContainer { + id: id.to_string(), + bundle: bundle.to_string(), + init, + process_factory: YoukiExecFactory { + bundle: bundle.to_string(), + io_uid: opts.io_uid, + io_gid: opts.io_gid, + }, + processes: Default::default(), + }; + Ok(container) + } + + async fn cleanup(&self, _ns: &str, c: &YoukiContainer) -> containerd_shim::Result<()> { + self.sandbox.lock().await.defer_storages(&c.id).await?; + Ok(()) + } +} + +impl YoukiFactory { + pub fn new(sandbox: Arc>) -> Self { + Self { sandbox } + } + + async fn do_create( + &self, + id: &str, + stdio: &Stdio, + opts: &Options, + bundle: &str, + ) -> Result { + // youki seems not support no_pivot_root and no_new_keyring option yet. + + let (socket, pio, _container_io) = if stdio.terminal { + let s = ConsoleSocket::new().await?; + (Some(s), None, None) + } else { + let (pio, container_io) = create_io(id, opts.io_uid, opts.io_gid, stdio)?; + (None, Some(pio), Some(container_io)) + }; + let id_clone = id.to_string(); + let opts_clone = opts.clone(); + let bundle_clone = bundle.to_string(); + let socket_path = socket.as_ref().map(|p| p.path.clone()); + let resp = spawn_blocking(move || { + let builder = ContainerBuilder::new(id_clone, SyscallType::default()) + .with_console_socket(socket_path) + .with_root_path(PathBuf::from(YOUKI_DIR)) + .map_err(other_error!(e, "failed to set youki create root path"))?; + // TODO: will uncomment this after youki-dev/youki#2961 is merged. + // if let Some(f) = container_io { + // if let Some(p) = f.stdin { + // builder = builder.with_stdin(p); + // } + // if let Some(p) = f.stdout { + // builder = builder.with_stdout(p); + // } + // if let Some(p) = f.stderr { + // builder = builder.with_stderr(p); + // } + // } + + builder + .as_init(bundle_clone) + .with_systemd(opts_clone.systemd_cgroup) + .build() + .map_err(other_error!(e, "failed to build youki container ")) + }) + .await + .map_err(other_error!(e, "failed to wait container building "))?; + + match resp { + Ok(mut c) => { + let pid = if let Some(p) = c.pid() { + p.as_raw() + } else { + if let Err(e) = c.delete(true) { + warn!("failed to cleanup container {}", e); + } + return Err(other!("failed to get pid of the youki container {}", id)); + }; + let mut init = InitProcess::new( + id, + stdio.clone(), + YoukiInitLifecycle::new(Arc::new(Mutex::new(c)), opts.clone(), bundle), + ); + let exit_signal = init.lifecycle.exit_signal.clone(); + copy_io_or_console(&mut init, socket, pio, exit_signal).await?; + init.pid = pid; + Ok(init) + } + Err(e) => { + if let Some(s) = socket { + s.clean().await; + } + Err(other!("failed to create container {}", e)) + } + } + } +} + +pub struct YoukiExecFactory { + bundle: String, + io_uid: u32, + io_gid: u32, +} + +#[async_trait] +impl ProcessFactory for YoukiExecFactory { + async fn create(&self, req: &ExecProcessRequest) -> Result { + let p = get_spec_from_request(req)?; + let stdio = match read_io(&self.bundle, req.id(), Some(req.exec_id())).await { + // terminal is still determined from request + Ok(io) => Stdio::new(&io.stdin, &io.stdout, &io.stderr, req.terminal()), + Err(_) => Stdio::new(req.stdin(), req.stdout(), req.stderr(), req.terminal()), + }; + let stdio = convert_stdio(&stdio).await?; + Ok(ExecProcess { + state: Status::CREATED, + id: req.exec_id.to_string(), + stdio, + pid: 0, + exit_code: 0, + exited_at: None, + wait_chan_tx: vec![], + console: None, + lifecycle: Arc::from(YoukiExecLifecycle { + bundle: self.bundle.to_string(), + container_id: req.id.to_string(), + io_uid: self.io_uid, + io_gid: self.io_gid, + spec: p, + exit_signal: Default::default(), + }), + stdin: Arc::new(Mutex::new(None)), + }) + } +} + +pub struct YoukiInitLifecycle { + youki_container: Arc>, + exit_signal: Arc, +} + +#[async_trait] +impl ProcessLifecycle for YoukiInitLifecycle { + async fn start(&self, p: &mut InitProcess) -> containerd_shim::Result<()> { + p.lifecycle + .youki_container + .lock() + .await + .start() + .map_err(other_error!(e, "failed to start container "))?; + p.state = Status::RUNNING; + Ok(()) + } + + async fn kill( + &self, + p: &mut InitProcess, + signal: u32, + all: bool, + ) -> containerd_shim::Result<()> { + let signal = Signal::try_from(signal as i32) + .map_err(other_error!(e, "failed to parse kill signal "))?; + p.lifecycle + .youki_container + .lock() + .await + .kill(signal, all) + .or_else(|e| { + if let LibcontainerError::IncorrectStatus = e { + Ok(()) + } else { + Err(e) + } + }) + .map_err(other_error!(e, "failed to kill container "))?; + Ok(()) + } + + async fn delete(&self, p: &mut InitProcess) -> containerd_shim::Result<()> { + p.lifecycle + .youki_container + .lock() + .await + .delete(true) + .map_err(other_error!(e, "failed to delete container "))?; + self.exit_signal.signal(); + Ok(()) + } + + #[cfg(target_os = "linux")] + async fn update(&self, p: &mut InitProcess, resources: &LinuxResources) -> Result<()> { + if p.pid <= 0 { + return Err(other!( + "failed to update resources because init process is {}", + p.pid + )); + } + containerd_shim::cgroup::update_resources(p.pid as u32, resources) + } + + #[cfg(not(target_os = "linux"))] + async fn update(&self, _p: &mut InitProcess, _resources: &LinuxResources) -> Result<()> { + Err(Error::Unimplemented("update resource".to_string())) + } + + #[cfg(target_os = "linux")] + async fn stats(&self, p: &InitProcess) -> Result { + if p.pid <= 0 { + return Err(other!( + "failed to collect metrics because init process is {}", + p.pid + )); + } + containerd_shim::cgroup::collect_metrics(p.pid as u32) + } + + #[cfg(not(target_os = "linux"))] + async fn stats(&self, _p: &InitProcess) -> Result { + Err(Error::Unimplemented("process stats".to_string())) + } + + async fn ps(&self, p: &InitProcess) -> Result> { + Ok(vec![ProcessInfo { + pid: p.pid as u32, + ..Default::default() + }]) + } +} + +impl YoukiInitLifecycle { + pub fn new(youki_container: Arc>, opts: Options, bundle: &str) -> Self { + let work_dir = Path::new(bundle).join("work"); + let mut opts = opts; + if opts.criu_path().is_empty() { + opts.criu_path = work_dir.to_string_lossy().to_string(); + } + Self { + youki_container, + exit_signal: Default::default(), + } + } +} + +pub struct YoukiExecLifecycle { + bundle: String, + container_id: String, + io_uid: u32, + io_gid: u32, + spec: Process, + exit_signal: Arc, +} + +#[async_trait] +impl ProcessLifecycle for YoukiExecLifecycle { + async fn start(&self, p: &mut ExecProcess) -> containerd_shim::Result<()> { + rescan_pci_bus().await?; + let (socket, pio, _container_io) = if p.stdio.terminal { + let s = ConsoleSocket::new().await?; + (Some(s), None, None) + } else { + let (pio, container_io) = create_io(&p.id, self.io_uid, self.io_gid, &p.stdio)?; + (None, Some(pio), Some(container_io)) + }; + + let probe_path = format!("{}/{}-process.json", self.bundle, &p.id); + let spec_str = serde_json::to_string(&self.spec) + .map_err(other_error!(e, "failed to marshall exec spec to string"))?; + tokio::fs::write(&probe_path, &spec_str) + .await + .map_err(other_error!(e, "failed to write spec to process.json"))?; + + let container_id = self.container_id.clone(); + let socket_path = socket.as_ref().map(|p| p.path.clone()); + let probe_path_clone = probe_path.clone(); + let exec_result = spawn_blocking(move || { + let builder = ContainerBuilder::new(container_id, SyscallType::default()) + .with_root_path(PathBuf::from(YOUKI_DIR)) + .map_err(other_error!(e, "failed to set youki root path"))? + .with_console_socket(socket_path); + // TODO: will uncomment this after youki-dev/youki#2961 is merged. + // if let Some(f) = container_io { + // if let Some(fd) = f.stdin { + // builder = builder.with_stdin(fd); + // } + // if let Some(fd) = f.stdout { + // builder = builder.with_stdout(fd); + // } + // if let Some(fd) = f.stderr { + // builder = builder.with_stderr(fd); + // } + // } + + builder + .as_tenant() + .with_detach(true) + .with_process(Some(&probe_path_clone)) + .build() + .map_err(other_error!( + e, + "failed to exec process in youki container " + )) + }) + .await + .map_err(other_error!(e, "failed to wait exec thread "))?; + tokio::fs::remove_file(&probe_path) + .await + .unwrap_or_default(); + match exec_result { + Ok(pid) => { + copy_io_or_console(p, socket, pio, p.lifecycle.exit_signal.clone()).await?; + p.pid = pid.as_raw(); + p.state = Status::RUNNING; + } + Err(e) => { + if let Some(s) = socket { + s.clean().await; + } + return Err(other!("failed to start youki exec: {}", e)); + } + } + Ok(()) + } + + async fn kill( + &self, + p: &mut ExecProcess, + signal: u32, + _all: bool, + ) -> containerd_shim::Result<()> { + if p.pid <= 0 { + Err(Error::FailedPreconditionError( + "process not created".to_string(), + )) + } else if p.exited_at.is_some() { + Err(Error::NotFoundError("process already finished".to_string())) + } else { + // TODO this is kill from nix crate, it is os specific, maybe have annotated with target os + kill( + Pid::from_raw(p.pid), + nix::sys::signal::Signal::try_from(signal as i32).unwrap(), + ) + .map_err(Into::into) + } + } + + async fn delete(&self, _p: &mut ExecProcess) -> containerd_shim::Result<()> { + self.exit_signal.signal(); + Ok(()) + } + + async fn update(&self, _p: &mut ExecProcess, _resources: &LinuxResources) -> Result<()> { + Err(Error::Unimplemented("exec update".to_string())) + } + + async fn stats(&self, _p: &ExecProcess) -> Result { + Err(Error::Unimplemented("exec stats".to_string())) + } + + async fn ps(&self, _p: &ExecProcess) -> Result> { + Err(Error::Unimplemented("exec ps".to_string())) + } +} + +pub fn create_io( + _id: &str, + io_uid: u32, + io_gid: u32, + stdio: &Stdio, +) -> containerd_shim::Result<(ProcessIO, ContainerPipeIo)> { + if stdio.is_null() { + let nio = NullIo::new().map_err(io_error!(e, "new Null Io"))?; + let pio = ProcessIO { + io: Some(Arc::new(nio)), + copy: false, + }; + return Ok((pio, ContainerPipeIo::default())); + } + let stdout = stdio.stdout.as_str(); + let scheme_path = stdout.trim().split("://").collect::>(); + let _scheme = if scheme_path.len() <= 1 { + // no scheme specified + // default schema to fifo + "fifo" + } else { + scheme_path[0] + }; + + let mut pio = ProcessIO { + io: None, + copy: false, + }; + + let opt = IOOption { + open_stdin: !stdio.stdin.is_empty(), + open_stdout: !stdio.stdout.is_empty(), + open_stderr: !stdio.stderr.is_empty(), + }; + let (io, container_io) = + PipedIo::new(io_uid, io_gid, &opt).map_err(io_error!(e, "new PipedIo"))?; + pio.io = Some(Arc::new(io)); + pio.copy = true; + Ok((pio, container_io)) +} + +impl Io for PipedIo { + fn stdin(&self) -> Option> { + self.stdin.and_then(|pipe| { + tokio_pipe::PipeWrite::from_raw_fd_checked(pipe) + .map(|x| Box::new(x) as Box) + .ok() + }) + } + + fn stdout(&self) -> Option> { + self.stdout.and_then(|pipe| { + tokio_pipe::PipeRead::from_raw_fd_checked(pipe) + .map(|x| Box::new(x) as Box) + .ok() + }) + } + + fn stderr(&self) -> Option> { + self.stderr.and_then(|pipe| { + tokio_pipe::PipeRead::from_raw_fd_checked(pipe) + .map(|x| Box::new(x) as Box) + .ok() + }) + } + + // Note that this internally use [`std::fs::File`]'s `try_clone()`. + // Thus, the files passed to commands will be not closed after command exit. + fn set(&self, _cmd: &mut Command) -> std::io::Result<()> { + Ok(()) + } + + fn close_after_start(&self) {} +} + +/// Struct to represent a pipe that can be used to transfer stdio inputs and outputs. +/// +/// With this Io driver, methods of [crate::Runc] may capture the output/error messages. +/// When one side of the pipe is closed, the state will be represented with [`None`]. +#[derive(Debug)] +pub struct Pipe { + rd: RawFd, + wr: RawFd, +} + +#[derive(Debug, Default)] +pub struct PipedIo { + stdin: Option, + stdout: Option, + stderr: Option, +} + +#[derive(Debug, Default)] +pub struct ContainerPipeIo { + stdin: Option, + stdout: Option, + stderr: Option, +} + +impl Pipe { + fn new() -> std::io::Result { + let (rd, wr) = os_pipe::pipe()?; + Ok(Self { + rd: rd.into_raw_fd(), + wr: wr.into_raw_fd(), + }) + } +} + +impl PipedIo { + pub fn new(uid: u32, gid: u32, opts: &IOOption) -> std::io::Result<(Self, ContainerPipeIo)> { + let mut res = Self::default(); + let mut container_pipes = ContainerPipeIo::default(); + if opts.open_stdin { + let pipe = Self::create_pipe(uid, gid, true)?; + res.stdin = Some(pipe.wr); + container_pipes.stdin = Some(unsafe { OwnedFd::from_raw_fd(pipe.rd) }); + } + if opts.open_stdout { + let pipe = Self::create_pipe(uid, gid, false)?; + res.stdout = Some(pipe.rd); + container_pipes.stdout = Some(unsafe { OwnedFd::from_raw_fd(pipe.wr) }); + } + if opts.open_stderr { + let pipe = Self::create_pipe(uid, gid, false)?; + res.stderr = Some(pipe.rd); + container_pipes.stderr = Some(unsafe { OwnedFd::from_raw_fd(pipe.wr) }); + } + Ok((res, container_pipes)) + } + + fn create_pipe(uid: u32, gid: u32, stdin: bool) -> std::io::Result { + let pipe = Pipe::new()?; + let uid = Some(Uid::from_raw(uid)); + let gid = Some(Gid::from_raw(gid)); + if stdin { + nix::unistd::fchown(pipe.rd, uid, gid)?; + } else { + nix::unistd::fchown(pipe.wr, uid, gid)?; + } + Ok(pipe) + } +} + +fn get_spec_from_request( + req: &ExecProcessRequest, +) -> containerd_shim::Result { + if let Some(val) = req.spec.as_ref() { + let mut p = serde_json::from_slice::(&val.value)?; + p.set_terminal(Some(req.terminal)); + Ok(p) + } else { + Err(Error::InvalidArgument("no spec in request".to_string())) + } +}