From 01a94ad23ec4e7a66f7eb15d64e926e8a6d4c972 Mon Sep 17 00:00:00 2001 From: Alex Zenla Date: Tue, 13 Aug 2024 23:17:47 -0700 Subject: [PATCH] feature(krata): prepare for workload rework (#276) * chore(code): simple code cleanup * chore(code): additional code cleanup * feature(krata): rework api and make ip assignment persistent to database * rework and cleanup * fix daemon config references --- Cargo.lock | 566 +++++++++--------- crates/ctl/src/cli/host/cpu_topology.rs | 4 +- crates/ctl/src/cli/host/identify.rs | 10 +- crates/ctl/src/cli/host/mod.rs | 6 +- crates/ctl/src/cli/mod.rs | 10 +- crates/ctl/src/cli/zone/destroy.rs | 20 +- crates/ctl/src/cli/zone/exec.rs | 9 +- crates/ctl/src/cli/zone/launch.rs | 14 +- crates/ctl/src/cli/zone/list.rs | 47 +- crates/ctl/src/cli/zone/resolve.rs | 8 +- crates/ctl/src/cli/zone/top.rs | 8 +- crates/ctl/src/console.rs | 28 +- crates/ctl/src/format.rs | 31 +- crates/ctl/src/metrics.rs | 14 +- crates/daemon/Cargo.toml | 3 + crates/daemon/src/config.rs | 61 ++ crates/daemon/src/control.rs | 103 ++-- crates/daemon/src/db/ip.rs | 118 ++++ crates/daemon/src/db/mod.rs | 21 + crates/daemon/src/{db.rs => db/zone.rs} | 36 +- crates/daemon/src/event.rs | 31 +- crates/daemon/src/idm.rs | 148 +++-- crates/daemon/src/ip/assignment.rs | 179 ++++++ crates/daemon/src/ip/mod.rs | 1 + crates/daemon/src/lib.rs | 45 +- .../reconcile/zone/{start.rs => create.rs} | 60 +- crates/daemon/src/reconcile/zone/mod.rs | 119 ++-- crates/krata/proto/krata/v1/common.proto | 36 +- crates/krata/proto/krata/v1/control.proto | 83 +-- crates/krata/src/idm/client.rs | 2 +- crates/network/src/autonet.rs | 22 +- crates/oci/examples/squashify.rs | 2 +- crates/oci/src/packer/backend.rs | 8 +- crates/oci/src/progress.rs | 2 +- crates/runtime/src/channel.rs | 8 +- crates/runtime/src/launch.rs | 107 +--- crates/runtime/src/lib.rs | 117 +--- crates/xen/xenclient/src/lib.rs | 3 +- crates/xen/xenevtchn/src/lib.rs | 6 +- crates/xen/xenstore/src/bus.rs | 2 +- crates/zone/src/background.rs | 2 +- 41 files changed, 1227 insertions(+), 873 deletions(-) create mode 100644 crates/daemon/src/db/ip.rs create mode 100644 crates/daemon/src/db/mod.rs rename crates/daemon/src/{db.rs => db/zone.rs} (64%) create mode 100644 crates/daemon/src/ip/assignment.rs create mode 100644 crates/daemon/src/ip/mod.rs rename crates/daemon/src/reconcile/zone/{start.rs => create.rs} (81%) diff --git a/Cargo.lock b/Cargo.lock index 37e7dfd..0b318cf 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4,9 +4,9 @@ version = 3 [[package]] name = "addr2line" -version = "0.21.0" +version = "0.22.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a30b2e23b9e17a9f90641c7ab1549cd9b44f296d3ccbf309d2863cfe398a0cb" +checksum = "6e4503c46a5c0c7844e948c9a4d6acd9f50cccb4de1c48eb9e291ea17470c678" dependencies = [ "gimli", ] @@ -46,15 +46,16 @@ checksum = "5c6cb57a04249c6480766f7f7cef5467412af1490f8d1e243141daddada3264f" [[package]] name = "anstream" -version = "0.6.13" +version = "0.6.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d96bd03f33fe50a863e394ee9718a706f988b9079b20c3784fb726e7678b62fb" +checksum = "64e15c1ab1f89faffbf04a634d5e1962e9074f2741eef6d97f3c4e322426d526" dependencies = [ "anstyle", "anstyle-parse", "anstyle-query", "anstyle-wincon", "colorchoice", + "is_terminal_polyfill", "utf8parse", ] @@ -66,27 +67,27 @@ checksum = "1bec1de6f59aedf83baf9ff929c98f2ad654b97c9510f4e70cf6f661d49fd5b1" [[package]] name = "anstyle-parse" -version = "0.2.3" +version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c75ac65da39e5fe5ab759307499ddad880d724eed2f6ce5b5e8a26f4f387928c" +checksum = "eb47de1e80c2b463c735db5b217a0ddc39d612e7ac9e2e96a5aed1f57616c1cb" dependencies = [ "utf8parse", ] [[package]] name = "anstyle-query" -version = "1.0.2" +version = "1.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e28923312444cdd728e4738b3f9c9cac739500909bb3d3c94b43551b16517648" +checksum = "6d36fc52c7f6c869915e99412912f22093507da8d9e942ceaf66fe4b7c14422a" dependencies = [ "windows-sys 0.52.0", ] [[package]] name = "anstyle-wincon" -version = "3.0.2" +version = "3.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1cd54b81ec8d6180e24654d0b371ad22fc3dd083b6ff8ba325b72e00c87660a7" +checksum = "5bf74e1b6e971609db8ca7a9ce79fd5768ab6ae46441c572e46cf596f59e57f8" dependencies = [ "anstyle", "windows-sys 0.52.0", @@ -141,7 +142,7 @@ checksum = "16e62a023e7c117e27523144c5d2459f4397fcc3cab0085af8e2224f643a0193" dependencies = [ "proc-macro2", "quote", - "syn 2.0.57", + "syn 2.0.74", ] [[package]] @@ -152,7 +153,7 @@ checksum = "6e0c28dcc82d7c8ead5cb13beb15405b57b8546e93215673ff8ca0349a028107" dependencies = [ "proc-macro2", "quote", - "syn 2.0.57", + "syn 2.0.74", ] [[package]] @@ -163,9 +164,9 @@ checksum = "1505bd5d3d116872e7271a6d4e16d81d0c8570876c8de68093a09ac269d8aac0" [[package]] name = "autocfg" -version = "1.2.0" +version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1fdabc7756949593fe60f30ec81974b613357de856987752631dea1e3394c80" +checksum = "0c4b4d0bd25bd0b74681c0ad21497610ce1b7c91b1022cd21c80c6fbdd9476b0" [[package]] name = "axum" @@ -222,7 +223,7 @@ checksum = "8f2fc1bc7bb7fd449e02000cc1592cc63dcdcd61710f8b9efe32bab2d1784603" dependencies = [ "deku", "flate2", - "rustc-hash", + "rustc-hash 1.1.0", "thiserror", "tracing", "xz2", @@ -232,9 +233,9 @@ dependencies = [ [[package]] name = "backtrace" -version = "0.3.71" +version = "0.3.73" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26b05800d2e817c8b3b4b54abd461726265fa9789ae34330622f2db9ee696f9d" +checksum = "5cc23269a4f8976d0a4d2e7109211a419fe30e8d88d677cd60b6bc79c5732e0a" dependencies = [ "addr2line", "cc", @@ -245,12 +246,6 @@ dependencies = [ "rustc-demangle", ] -[[package]] -name = "base64" -version = "0.21.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9d297deb1925b89f2ccc13d7635fa0714f12c87adce1c75356b39ca9b7178567" - [[package]] name = "base64" version = "0.22.1" @@ -265,9 +260,9 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] name = "bitflags" -version = "2.5.0" +version = "2.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf4b9d6a944f767f8e5e0db018570623c85f3d925ac718db4e06d0187adb21c1" +checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de" [[package]] name = "bitvec" @@ -292,9 +287,9 @@ dependencies = [ [[package]] name = "bumpalo" -version = "3.15.4" +version = "3.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ff69b9dd49fd426c69a0db9fc04dd934cdb6645ff000864d98f7e2af8830eaa" +checksum = "79296716171880943b8470b5f8d03aa55eb2e645a4874bdbb28adb49162e012c" [[package]] name = "byteorder" @@ -336,18 +331,18 @@ checksum = "df8670b8c7b9dae1793364eafadf7239c40d669904660c5960d74cfd80b46a53" [[package]] name = "castaway" -version = "0.2.2" +version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a17ed5635fc8536268e5d4de1e22e81ac34419e5f052d4d51f4e01dcc263fcc" +checksum = "0abae9be0aaf9ea96a3b1b8b1b55c602ca751eba1b1500220cea4ecbafe7c0d5" dependencies = [ "rustversion", ] [[package]] name = "cc" -version = "1.0.90" +version = "1.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8cd6604a82acf3039f1144f54b8eb34e91ffba622051189e71b781822d5ee1f5" +checksum = "e9e8aabfac534be767c909e0690571677d49f41bd8465ae876fe043d52ba5292" dependencies = [ "jobserver", "libc", @@ -403,7 +398,7 @@ dependencies = [ "anstream", "anstyle", "clap_lex", - "strsim 0.11.0", + "strsim", ] [[package]] @@ -415,20 +410,20 @@ dependencies = [ "heck", "proc-macro2", "quote", - "syn 2.0.57", + "syn 2.0.74", ] [[package]] name = "clap_lex" -version = "0.7.0" +version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "98cc8fbded0c607b7ba9dd60cd98df59af97e84d24e49c8557331cfc26d301ce" +checksum = "1462739cb27611015575c0c11df5df7601141071f07518d56fcc1be504cbec97" [[package]] name = "colorchoice" -version = "1.0.0" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "acbf1af155f9b9ef647e42cdc158db4b64a1b61f743629225fde6f3e0be2a7c7" +checksum = "d3fd119d74b830634cea2a0f58bbd0d54540518a14397557951e79340abc28c0" [[package]] name = "comfy-table" @@ -470,24 +465,24 @@ dependencies = [ [[package]] name = "core-foundation-sys" -version = "0.8.6" +version = "0.8.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "06ea2b9bc92be3c2baa9334a323ebca2d6f074ff852cd1d7b11064035cd3868f" +checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b" [[package]] name = "cpufeatures" -version = "0.2.12" +version = "0.2.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "53fe5e26ff1b7aef8bca9c6080520cfb8d9333c7568e1829cef191a9723e5504" +checksum = "51e852e6dc9a5bed1fae92dd2375037bf2b768725bf3be87811edee3249d09ad" dependencies = [ "libc", ] [[package]] name = "crc32fast" -version = "1.4.0" +version = "1.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b3855a8a784b474f333699ef2bbca9db2c4a1f6d9088a90a2d25b1eb53111eaa" +checksum = "a97769d94ddab943e4510d138150169a2758b5ef3eb191a9ee688de3e23ef7b3" dependencies = [ "cfg-if", ] @@ -513,9 +508,9 @@ dependencies = [ [[package]] name = "crossbeam-utils" -version = "0.8.19" +version = "0.8.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "248e3bacc7dc6baa3b21e405ee045c3047101a49145e7e9eca583ab4c2ca5345" +checksum = "22ec99545bb0ed0ea7bb9b8e1e9122ea386ff8a48c0922e43f36d45ab09e0e80" [[package]] name = "crossterm" @@ -523,7 +518,7 @@ version = "0.27.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f476fe445d41c9e991fd07515a6f463074b782242ccf4a5b7b1d1012e70824df" dependencies = [ - "bitflags 2.5.0", + "bitflags 2.6.0", "crossterm_winapi", "futures-core", "libc", @@ -565,9 +560,9 @@ dependencies = [ [[package]] name = "darling" -version = "0.20.8" +version = "0.20.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "54e36fcd13ed84ffdfda6f5be89b31287cbb80c439841fe69e04841435464391" +checksum = "6f63b86c8a8826a49b8c21f08a2d07338eec8d900540f8630dc76284be802989" dependencies = [ "darling_core", "darling_macro", @@ -575,34 +570,34 @@ dependencies = [ [[package]] name = "darling_core" -version = "0.20.8" +version = "0.20.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c2cf1c23a687a1feeb728783b993c4e1ad83d99f351801977dd809b48d0a70f" +checksum = "95133861a8032aaea082871032f5815eb9e98cef03fa916ab4500513994df9e5" dependencies = [ "fnv", "ident_case", "proc-macro2", "quote", - "strsim 0.10.0", - "syn 2.0.57", + "strsim", + "syn 2.0.74", ] [[package]] name = "darling_macro" -version = "0.20.8" +version = "0.20.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a668eda54683121533a393014d8692171709ff57a7d61f187b6e782719f8933f" +checksum = "d336a2a514f6ccccaa3e09b02d41d35330c07ddf03a62165fcec10bb561c7806" dependencies = [ "darling_core", "quote", - "syn 2.0.57", + "syn 2.0.74", ] [[package]] name = "defmt" -version = "0.3.6" +version = "0.3.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3939552907426de152b3c2c6f51ed53f98f448babd26f28694c95f5906194595" +checksum = "a99dd22262668b887121d4672af5a64b238f026099f1a2a1b322066c9ecfe9e0" dependencies = [ "bitflags 1.3.2", "defmt-macros", @@ -610,15 +605,15 @@ dependencies = [ [[package]] name = "defmt-macros" -version = "0.3.7" +version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "18bdc7a7b92ac413e19e95240e75d3a73a8d8e78aa24a594c22cbb4d44b4bbda" +checksum = "e3a9f309eff1f79b3ebdf252954d90ae440599c26c2c553fe87a2d17195f2dcb" dependencies = [ "defmt-parser", "proc-macro-error", "proc-macro2", "quote", - "syn 2.0.57", + "syn 2.0.74", ] [[package]] @@ -652,7 +647,7 @@ dependencies = [ "proc-macro-crate", "proc-macro2", "quote", - "syn 2.0.57", + "syn 2.0.74", ] [[package]] @@ -673,7 +668,7 @@ dependencies = [ "darling", "proc-macro2", "quote", - "syn 2.0.57", + "syn 2.0.74", ] [[package]] @@ -683,7 +678,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "206868b8242f27cecce124c19fd88157fbd0dd334df2587f36417bafbc85097b" dependencies = [ "derive_builder_core", - "syn 2.0.57", + "syn 2.0.74", ] [[package]] @@ -698,9 +693,9 @@ dependencies = [ [[package]] name = "either" -version = "1.10.0" +version = "1.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "11157ac094ffbdde99aa67b23417ebdd801842852b500e395a45a9c0aac03e4a" +checksum = "60b1af1c220855b6ceac025d3f6ecdd2b7c4894bfe9cd9bda4fbb4bc7c0d4cf0" [[package]] name = "elf" @@ -716,9 +711,9 @@ checksum = "a357d28ed41a50f9c765dbfe56cbc04a64e53e5fc58ba79fbc34c10ef3df831f" [[package]] name = "env_filter" -version = "0.1.0" +version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a009aa4810eb158359dda09d0c87378e4bbb89b5a801f016885a4707ba24f7ea" +checksum = "4f2c92ceda6ceec50f43169f9ee8424fe2db276791afde7b2cd8bc084cb376ab" dependencies = [ "log", "regex", @@ -745,9 +740,9 @@ checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" [[package]] name = "errno" -version = "0.3.8" +version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a258e46cdc063eb8519c00b9fc845fc47bcfca4130e2f08e88665ceda8474245" +checksum = "534c5cf6194dfab3db3242765c03bbe257cf92f22b38f6bc0c58d59108a820ba" dependencies = [ "libc", "windows-sys 0.52.0", @@ -775,20 +770,20 @@ dependencies = [ [[package]] name = "fastrand" -version = "2.0.2" +version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "658bd65b1cf4c852a3cc96f18a8ce7b5640f6b703f905c7d74532294c2a63984" +checksum = "9fc0510504f03c51ada170672ac806f1f105a88aa97a5281117e1ddc3368e51a" [[package]] name = "filetime" -version = "0.2.23" +version = "0.2.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ee447700ac8aa0b2f2bd7bc4462ad686ba06baa6727ac149a2d6277f0d240fd" +checksum = "bf401df4a4e3872c4fe8151134cf483738e74b67fc934d6532c882b3d24a4550" dependencies = [ "cfg-if", "libc", - "redox_syscall 0.4.1", - "windows-sys 0.52.0", + "libredox", + "windows-sys 0.59.0", ] [[package]] @@ -884,7 +879,7 @@ checksum = "87750cf4b7a4c0625b1529e4c543c2182106e4dedc60a2a6455e00d212c489ac" dependencies = [ "proc-macro2", "quote", - "syn 2.0.57", + "syn 2.0.74", ] [[package]] @@ -929,9 +924,9 @@ dependencies = [ [[package]] name = "getrandom" -version = "0.2.12" +version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "190092ea657667030ac6a35e305e62fc4dd69fd98ac98631e5d3a2b1575a12b5" +checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7" dependencies = [ "cfg-if", "libc", @@ -952,9 +947,9 @@ dependencies = [ [[package]] name = "gimli" -version = "0.28.1" +version = "0.29.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4271d37baee1b8c7e4b708028c57d816cf9d2434acb33a549475f78c181f6253" +checksum = "40ecd4077b5ae9fd2e9e169b102c6c330d0605168eb0e8bf79952b256dbefffd" [[package]] name = "h2" @@ -992,9 +987,9 @@ checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" [[package]] name = "hashbrown" -version = "0.14.3" +version = "0.14.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "290f1a1d9242c78d09ce40a5e87e7554ee637af1351968159f4952f028f75604" +checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" dependencies = [ "ahash", "allocator-api2", @@ -1041,9 +1036,9 @@ dependencies = [ [[package]] name = "http-body" -version = "1.0.0" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1cac85db508abc24a2e48553ba12a996e87244a0395ce011e62b37158745d643" +checksum = "1efedce1fb8e6913f23e0c92de8e62cd5b772a67e7b3946df930a62566c93184" dependencies = [ "bytes", "http", @@ -1051,12 +1046,12 @@ dependencies = [ [[package]] name = "http-body-util" -version = "0.1.1" +version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0475f8b2ac86659c21b64320d5d653f9efe42acd2a4e560073ec61a155a34f1d" +checksum = "793429d76616a256bcb62c2a2ec2bed781c8307e797e2598c50010f2bee2544f" dependencies = [ "bytes", - "futures-core", + "futures-util", "http", "http-body", "pin-project-lite", @@ -1064,9 +1059,9 @@ dependencies = [ [[package]] name = "httparse" -version = "1.8.0" +version = "1.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d897f394bad6a705d5f4104762e116a75639e470d80901eed05a860a95cb1904" +checksum = "0fcc0b4a115bf80b728eb8ea024ad5bd707b615bfed49e0665b6e0f86fd082d9" [[package]] name = "httpdate" @@ -1191,7 +1186,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "93ead53efc7ea8ed3cfb0c79fc8023fbb782a5432b52830b6518941cebe6505c" dependencies = [ "equivalent", - "hashbrown 0.14.3", + "hashbrown 0.14.5", ] [[package]] @@ -1209,9 +1204,9 @@ dependencies = [ [[package]] name = "instant" -version = "0.1.12" +version = "0.1.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a5bbe824c507c5da5956355e86a746d82e0e1464f65d862cc5e71da70e94b2c" +checksum = "e0242819d153cba4b4b05a5a8f2a7e9bbf97b6055b2a002b395c96b5ff3c0222" dependencies = [ "cfg-if", ] @@ -1232,13 +1227,10 @@ dependencies = [ ] [[package]] -name = "itertools" -version = "0.12.1" +name = "is_terminal_polyfill" +version = "1.70.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba291022dbbd398a455acf126c1e341954079855bc60dfdda641363bd6922569" -dependencies = [ - "either", -] +checksum = "7943c866cc5cd64cbc25b2e01621d07fa8eb2a1a23160ee81ce38704e97b8ecf" [[package]] name = "itertools" @@ -1257,18 +1249,18 @@ checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b" [[package]] name = "jobserver" -version = "0.1.28" +version = "0.1.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ab46a6e9526ddef3ae7f787c06f0f2600639ba80ea3eade3d8e670a2230f51d6" +checksum = "48d1dbcbbeb6a7fec7e059840aa538bd62aaccf972c7346c4d9d2059312853d0" dependencies = [ "libc", ] [[package]] name = "js-sys" -version = "0.3.69" +version = "0.3.70" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "29c15563dc2726973df627357ce0c9ddddbea194836909d655df6a75d2cf296d" +checksum = "1868808506b929d7b0cfa8f75951347aa71bb21144b7791bae35d9bccfcfe37a" dependencies = [ "wasm-bindgen", ] @@ -1334,7 +1326,7 @@ version = "0.0.15" dependencies = [ "anyhow", "async-stream", - "base64 0.22.1", + "base64", "clap", "comfy-table", "crossterm", @@ -1370,7 +1362,9 @@ dependencies = [ "clap", "env_logger", "futures", + "ipnetwork", "krata", + "krata-advmac", "krata-oci", "krata-runtime", "krata-tokio-tar", @@ -1379,6 +1373,7 @@ dependencies = [ "redb", "scopeguard", "serde", + "serde_json", "signal-hook", "tokio", "tokio-stream", @@ -1453,7 +1448,6 @@ dependencies = [ "backhand", "env_logger", "indexmap 2.4.0", - "ipnetwork", "krata", "krata-advmac", "krata-loopdev", @@ -1600,9 +1594,9 @@ dependencies = [ [[package]] name = "lazy_static" -version = "1.4.0" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" +checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" [[package]] name = "libc" @@ -1611,16 +1605,27 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "97b3888a4aecf77e811145cadf6eef5901f4782c53886191b2f693f24761847c" [[package]] -name = "linux-raw-sys" -version = "0.4.13" +name = "libredox" +version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "01cda141df6706de531b6c46c3a33ecca755538219bd484262fa09410c13539c" +checksum = "c0ff37bd590ca25063e35af745c343cb7a0271906fb7b37e4813e8f79f00268d" +dependencies = [ + "bitflags 2.6.0", + "libc", + "redox_syscall 0.5.3", +] + +[[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.11" +version = "0.4.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c168f8615b12bc01f9c17e2eb0cc07dcae1940121185446edc3744920e8ef45" +checksum = "07af8b9cdd281b7915f413fa73f29ebd5d55d0d3f0155584dade1ff18cea1b17" dependencies = [ "autocfg", "scopeguard", @@ -1634,11 +1639,11 @@ checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24" [[package]] name = "lru" -version = "0.12.3" +version = "0.12.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d3262e75e648fce39813cb56ac41f3c3e3f65217ebf3844d818d1f9398cfb0dc" +checksum = "37ee39891760e7d94734f6f63fedc29a2e4a152f836120753a72503f09fcf904" dependencies = [ - "hashbrown 0.14.3", + "hashbrown 0.14.5", ] [[package]] @@ -1678,9 +1683,9 @@ checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a" [[package]] name = "miniz_oxide" -version = "0.7.2" +version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9d811f3e15f28568be3407c8e7fdb6514c1cda3cb30683f15b6a1a1dc4ea14a7" +checksum = "b8a240ddb74feaf34a79a7add65a741f3167852fba007066dcac1ca548d89c08" dependencies = [ "adler", ] @@ -1699,9 +1704,9 @@ dependencies = [ [[package]] name = "mio" -version = "1.0.1" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4569e456d394deccd22ce1c1913e6ea0e54519f577285001215d33557431afe4" +checksum = "80e04d1dcff3aae0704555fe5fee3bcfaf3d1fdf8a7e521d5b9d2b42acb52cec" dependencies = [ "hermit-abi", "libc", @@ -1711,9 +1716,9 @@ dependencies = [ [[package]] name = "multimap" -version = "0.8.3" +version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e5ce46fe64a9d73be07dcbe690a38ce1b293be448fd8ce1e6c1b8062c9f72c6a" +checksum = "defc4c55412d89136f966bbb339008b474350e5e6e78d2714439c386b3137a03" [[package]] name = "netlink-packet-core" @@ -1769,9 +1774,9 @@ dependencies = [ [[package]] name = "netlink-sys" -version = "0.8.5" +version = "0.8.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6471bf08e7ac0135876a9581bf3217ef0333c191c128d34878079f42ee150411" +checksum = "416060d346fbaf1f23f9512963e3e878f1a78e707cb699ba9215761754244307" dependencies = [ "bytes", "futures", @@ -1798,7 +1803,7 @@ version = "0.27.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2eb04e9c688eff1c89d72b407f168cf79bb9e867a9d3323ed6c01519eb9cc053" dependencies = [ - "bitflags 2.5.0", + "bitflags 2.6.0", "cfg-if", "libc", ] @@ -1809,7 +1814,7 @@ version = "0.29.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "71e2746dc3a24dd78b3cfcb7be93368c6de9963d30f43a6a73998a9cf4b17b46" dependencies = [ - "bitflags 2.5.0", + "bitflags 2.6.0", "cfg-if", "cfg_aliases", "libc", @@ -1835,9 +1840,9 @@ dependencies = [ [[package]] name = "num-traits" -version = "0.2.18" +version = "0.2.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da0df0e5185db44f69b44f26786fe401b6c293d1907744beaa7fa62b2e5a517a" +checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" dependencies = [ "autocfg", ] @@ -1850,9 +1855,9 @@ checksum = "830b246a0e5f20af87141b25c173cd1b609bd7779a4617d6ec582abaf90870f3" [[package]] name = "object" -version = "0.32.2" +version = "0.36.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a6a622008b6e321afc04970976f62ee297fdbaa6f95318ca343e3eebb9648441" +checksum = "27b64972346851a39438c60b341ebc01bba47464ae329e55cf343eb93964efd9" dependencies = [ "memchr", ] @@ -1891,9 +1896,9 @@ dependencies = [ [[package]] name = "parking_lot" -version = "0.12.1" +version = "0.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3742b2c103b9f06bc9fff0a37ff4912935851bee6d36f3c02bcc755bcfec228f" +checksum = "f1bf18183cf54e8d6059647fc3063646a1801cf30896933ec2311622cc4b9a27" dependencies = [ "lock_api", "parking_lot_core", @@ -1901,22 +1906,22 @@ dependencies = [ [[package]] name = "parking_lot_core" -version = "0.9.9" +version = "0.9.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c42a9226546d68acdd9c0a280d17ce19bfe27a46bf68784e4066115788d008e" +checksum = "1e401f977ab385c9e4e3ab30627d6f26d00e2c73eef317493c4ec6d468726cf8" dependencies = [ "cfg-if", "libc", - "redox_syscall 0.4.1", + "redox_syscall 0.5.3", "smallvec", - "windows-targets 0.48.5", + "windows-targets 0.52.6", ] [[package]] name = "paste" -version = "1.0.14" +version = "1.0.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "de3145af08024dea9fa9914f381a17b8fc6034dfb00f3a84013f7ff43f29ed4c" +checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a" [[package]] name = "path-absolutize" @@ -1950,9 +1955,9 @@ checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" [[package]] name = "petgraph" -version = "0.6.4" +version = "0.6.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e1d3afd2628e69da2be385eb6f2fd57c8ac7977ceeff6dc166ff1657b0e386a9" +checksum = "b4c5cc86750666a3ed20bdaf5ca2a0344f9c67674cae0515bec2da16fbaa47db" dependencies = [ "fixedbitset", "indexmap 2.4.0", @@ -1975,7 +1980,7 @@ checksum = "2f38a4412a78282e09a2cf38d195ea5420d15ba0602cb375210efbc877243965" dependencies = [ "proc-macro2", "quote", - "syn 2.0.57", + "syn 2.0.74", ] [[package]] @@ -2008,24 +2013,27 @@ dependencies = [ [[package]] name = "portable-atomic" -version = "1.6.0" +version = "1.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7170ef9988bc169ba16dd36a7fa041e5c4cbeb6a35b76d4c03daded371eae7c0" +checksum = "da544ee218f0d287a911e9c99a39a8c9bc8fcad3cb8db5959940044ecfc67265" [[package]] name = "ppv-lite86" -version = "0.2.17" +version = "0.2.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" +checksum = "77957b295656769bb8ad2b6a6b09d897d94f05c41b069aede1fcdaa675eaea04" +dependencies = [ + "zerocopy", +] [[package]] name = "prettyplease" -version = "0.2.17" +version = "0.2.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8d3928fb5db768cb86f891ff014f0144589297e3c6a1aba6ed7cecfdace270c7" +checksum = "5f12335488a2f3b0a83b14edad48dca9879ce89b2edd10e80237e4e852dd645e" dependencies = [ "proc-macro2", - "syn 2.0.57", + "syn 2.0.74", ] [[package]] @@ -2063,9 +2071,9 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.79" +version = "1.0.86" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e835ff2298f5721608eb1a980ecaee1aef2c132bf95ecc026a11b7bf3c01c02e" +checksum = "5e719e8df665df0d1c8fbfd238015744736151d4445ec0836b8e628aae103b77" dependencies = [ "unicode-ident", ] @@ -2088,7 +2096,7 @@ checksum = "5bb182580f71dd070f88d01ce3de9f4da5021db7115d2e1c3605a754153b77c1" dependencies = [ "bytes", "heck", - "itertools 0.13.0", + "itertools", "log", "multimap", "once_cell", @@ -2097,7 +2105,7 @@ dependencies = [ "prost", "prost-types", "regex", - "syn 2.0.57", + "syn 2.0.74", "tempfile", ] @@ -2108,10 +2116,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "18bec9b0adc4eba778b33684b7ba3e7137789434769ee3ce3930463ef904cfca" dependencies = [ "anyhow", - "itertools 0.13.0", + "itertools", "proc-macro2", "quote", - "syn 2.0.57", + "syn 2.0.74", ] [[package]] @@ -2120,7 +2128,7 @@ version = "0.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "55a6a9143ae25c25fa7b6a48d6cc08b10785372060009c25140a4e7c340e95af" dependencies = [ - "base64 0.22.1", + "base64", "once_cell", "prost", "prost-reflect-derive", @@ -2147,7 +2155,7 @@ checksum = "f4fce6b22f15cc8d8d400a2b98ad29202b33bd56c7d9ddd815bc803a807ecb65" dependencies = [ "proc-macro2", "quote", - "syn 2.0.57", + "syn 2.0.74", ] [[package]] @@ -2161,16 +2169,17 @@ dependencies = [ [[package]] name = "quinn" -version = "0.11.2" +version = "0.11.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e4ceeeeabace7857413798eb1ffa1e9c905a9946a57d81fb69b4b71c4d8eb3ad" +checksum = "b22d8e7369034b9a7132bc2008cac12f2013c8132b45e0554e6e20e2617f2156" dependencies = [ "bytes", "pin-project-lite", "quinn-proto", "quinn-udp", - "rustc-hash", + "rustc-hash 2.0.0", "rustls", + "socket2", "thiserror", "tokio", "tracing", @@ -2178,14 +2187,14 @@ dependencies = [ [[package]] name = "quinn-proto" -version = "0.11.3" +version = "0.11.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ddf517c03a109db8100448a4be38d498df8a210a99fe0e1b9eaf39e78c640efe" +checksum = "ba92fb39ec7ad06ca2582c0ca834dfeadcaf06ddfc8e635c80aa7e1c05315fdd" dependencies = [ "bytes", "rand", "ring", - "rustc-hash", + "rustc-hash 2.0.0", "rustls", "slab", "thiserror", @@ -2195,9 +2204,9 @@ dependencies = [ [[package]] name = "quinn-udp" -version = "0.5.2" +version = "0.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9096629c45860fc7fb143e125eb826b5e721e10be3263160c7d60ca832cf8c46" +checksum = "8bffec3605b73c6f1754535084a85229fa8a30f86014e6c81aeec4abb68b0285" dependencies = [ "libc", "once_cell", @@ -2208,9 +2217,9 @@ dependencies = [ [[package]] name = "quote" -version = "1.0.35" +version = "1.0.36" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "291ec9ab5efd934aaf503a6466c5d5251535d108ee747472c3977cc5acc868ef" +checksum = "0fa76aaf39101c457836aec0ce2316dbdc3ab723cdda1c6bd4e6ad4208acaca7" dependencies = [ "proc-macro2", ] @@ -2257,11 +2266,11 @@ version = "0.27.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d16546c5b5962abf8ce6e2881e722b4e0ae3b6f1a08a26ae3573c55853ca68d3" dependencies = [ - "bitflags 2.5.0", + "bitflags 2.6.0", "cassowary", "compact_str", "crossterm", - "itertools 0.13.0", + "itertools", "lru", "paste", "stability", @@ -2312,11 +2321,11 @@ dependencies = [ [[package]] name = "redox_syscall" -version = "0.4.1" +version = "0.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4722d768eff46b75989dd134e5c353f0d6296e5aaa3132e776cbdb56be7731aa" +checksum = "2a908a6e00f1fdd0dfd9c0eb08ce85126f6d8bbda50017e74bc4a4b7d4a926a4" dependencies = [ - "bitflags 1.3.2", + "bitflags 2.6.0", ] [[package]] @@ -2333,9 +2342,9 @@ dependencies = [ [[package]] name = "regex-automata" -version = "0.4.6" +version = "0.4.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "86b83b8b9847f9bf95ef68afb0b8e6cdb80f498442f5179a29fad448fcc1eaea" +checksum = "38caf58cc5ef2fed281f89292ef23f6365465ed9a41b7a7754eb4e26496c92df" dependencies = [ "aho-corasick", "memchr", @@ -2344,9 +2353,9 @@ dependencies = [ [[package]] name = "regex-syntax" -version = "0.8.3" +version = "0.8.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "adad44e29e4c806119491a7f06f03de4d1af22c3a680dd47f1e6e179439d1f56" +checksum = "7a66a03ae7c801facd77a29370b4faec201768915ac14a721ba36f20bc9c209b" [[package]] name = "reqwest" @@ -2354,7 +2363,7 @@ version = "0.12.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c7d6d2a27d57148378eb5e111173f4276ad26340ecc5c49a4a2152167a2d6a37" dependencies = [ - "base64 0.22.1", + "base64", "bytes", "futures-core", "futures-util", @@ -2425,9 +2434,9 @@ dependencies = [ [[package]] name = "rustc-demangle" -version = "0.1.23" +version = "0.1.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76" +checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f" [[package]] name = "rustc-hash" @@ -2436,12 +2445,18 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" [[package]] -name = "rustix" -version = "0.38.32" +name = "rustc-hash" +version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "65e04861e65f21776e67888bfbea442b3642beaa0138fdb1dd7a84a52dffdb89" +checksum = "583034fd73374156e66797ed8e5b0d5690409c9226b22d87cb7f19821c05d152" + +[[package]] +name = "rustix" +version = "0.38.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "70dc5ec042f7a43c4a73241207cecc9873a06d45debb38b329f8541d85c2730f" dependencies = [ - "bitflags 2.5.0", + "bitflags 2.6.0", "errno", "libc", "linux-raw-sys", @@ -2450,9 +2465,9 @@ dependencies = [ [[package]] name = "rustls" -version = "0.23.7" +version = "0.23.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ebbbdb961df0ad3f2652da8f3fdc4b36122f568f968f45ad3316f26c025c677b" +checksum = "c58f8c84392efc0a126acce10fa59ff7b3d2ac06ab451a33f2741989b806b044" dependencies = [ "log", "once_cell", @@ -2465,25 +2480,25 @@ dependencies = [ [[package]] name = "rustls-pemfile" -version = "2.1.1" +version = "2.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f48172685e6ff52a556baa527774f61fcaa884f59daf3375c62a3f1cd2549dab" +checksum = "196fe16b00e106300d3e45ecfcb764fa292a535d7326a29a5875c579c7417425" dependencies = [ - "base64 0.21.7", + "base64", "rustls-pki-types", ] [[package]] name = "rustls-pki-types" -version = "1.4.1" +version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ecd36cc4259e3e4514335c4a138c6b43171a8d61d8f5c9348f9fc7529416f247" +checksum = "fc0a2ce646f8655401bb81e7927b812614bd5d91dbc968696be50603510fcaf0" [[package]] name = "rustls-webpki" -version = "0.102.2" +version = "0.102.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "faaa0a62740bedb9b2ef5afa303da42764c012f743917351dc9a237ea1663610" +checksum = "8e6b52d4fda176fd835fdc55a835d4a89b8499cad995885a21149d5ad62f852e" dependencies = [ "ring", "rustls-pki-types", @@ -2498,9 +2513,9 @@ checksum = "955d28af4278de8121b7ebeb796b6a45735dc01436d898801014aced2773a3d6" [[package]] name = "ryu" -version = "1.0.17" +version = "1.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e86697c916019a8588c99b5fac3cead74ec0b4b819707a682fd4d23fa0ce1ba1" +checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f" [[package]] name = "same-file" @@ -2544,7 +2559,7 @@ checksum = "6aea2634c86b0e8ef2cfdc0c340baede54ec27b1e46febd7f80dffb2aa44a00e" dependencies = [ "proc-macro2", "quote", - "syn 2.0.57", + "syn 2.0.74", ] [[package]] @@ -2629,9 +2644,9 @@ dependencies = [ [[package]] name = "signal-hook-mio" -version = "0.2.3" +version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "29ad2e15f37ec9a6cc544097b78a1ec90001e9f71b81338ca39f430adaca99af" +checksum = "34db1a06d485c9142248b7a054f034b349b212551f3dfd19c94d45a754a217cd" dependencies = [ "libc", "mio 0.8.11", @@ -2640,9 +2655,9 @@ dependencies = [ [[package]] name = "signal-hook-registry" -version = "1.4.1" +version = "1.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d8229b473baa5980ac72ef434c4415e70c4b5e71b423043adb4ba059f89c99a1" +checksum = "a9e9e0b4211b72e7b8b6e85c807d36c212bdb33ea8587f7569562a84df5465b1" dependencies = [ "libc", ] @@ -2676,7 +2691,7 @@ checksum = "0eb01866308440fc64d6c44d9e86c5cc17adfe33c4d6eed55da9145044d0ffc1" dependencies = [ "proc-macro2", "quote", - "syn 2.0.57", + "syn 2.0.74", ] [[package]] @@ -2697,9 +2712,9 @@ dependencies = [ [[package]] name = "socket2" -version = "0.5.6" +version = "0.5.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05ffd9c0a93b7543e062e759284fcf5f5e3b098501104bfbdde4d404db792871" +checksum = "ce305eb0b4296696835b71df73eb912e0f1ffd2556a501fcede6e0c50349191c" dependencies = [ "libc", "windows-sys 0.52.0", @@ -2713,12 +2728,12 @@ checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67" [[package]] name = "stability" -version = "0.2.0" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2ff9eaf853dec4c8802325d8b6d3dffa86cc707fd7a1a4cdbf416e13b061787a" +checksum = "d904e7009df136af5297832a3ace3370cd14ff1546a232f4f185036c2736fcac" dependencies = [ "quote", - "syn 2.0.57", + "syn 2.0.74", ] [[package]] @@ -2735,21 +2750,15 @@ checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" [[package]] name = "strsim" -version = "0.10.0" +version = "0.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" - -[[package]] -name = "strsim" -version = "0.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ee073c9e4cd00e28217186dbe12796d692868f432bf2e97ee73bed0c56dfa01" +checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" [[package]] name = "strum" -version = "0.26.2" +version = "0.26.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5d8cec3501a5194c432b2b7976db6b7d10ec95c253208b45f83f7136aa985e29" +checksum = "8fec0f0aef304996cf250b31b5a10dee7980c85da9d759361292b8bca5a18f06" dependencies = [ "strum_macros", ] @@ -2764,14 +2773,14 @@ dependencies = [ "proc-macro2", "quote", "rustversion", - "syn 2.0.57", + "syn 2.0.74", ] [[package]] name = "subtle" -version = "2.5.0" +version = "2.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "81cdd64d312baedb58e21336b31bc043b77e01cc99033ce76ef539f78e965ebc" +checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" [[package]] name = "syn" @@ -2786,9 +2795,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.57" +version = "2.0.74" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "11a6ae1e52eb25aab8f3fb9fca13be982a373b8f1157ca14b897a825ba4a2d35" +checksum = "1fceb41e3d546d0bd83421d3409b1460cc7444cd389341a4c880fe7a042cb3d7" dependencies = [ "proc-macro2", "quote", @@ -2813,7 +2822,7 @@ version = "3.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a6acb8bb63826062d5a44b68298cf2e25b84bc151bc0c31c35a83b61f818682a" dependencies = [ - "bitflags 2.5.0", + "bitflags 2.6.0", "libc", "smart-default", "thiserror", @@ -2843,14 +2852,15 @@ checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369" [[package]] name = "tempfile" -version = "3.10.1" +version = "3.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85b77fafb263dd9d05cbeac119526425676db3784113aa9295c88498cbf8bff1" +checksum = "04cbcdd0c794ebb0d4cf35e88edd2f7d2c4c3e9a5a6dab322839b321c6a87a64" dependencies = [ "cfg-if", "fastrand", + "once_cell", "rustix", - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] @@ -2876,14 +2886,14 @@ checksum = "a4558b58466b9ad7ca0f102865eccc95938dca1a74a856f2b57b6629050da261" dependencies = [ "proc-macro2", "quote", - "syn 2.0.57", + "syn 2.0.74", ] [[package]] name = "tinyvec" -version = "1.6.0" +version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87cc5ceb3875bb20c2890005a4e226a4651264a5c75edb2421b52861a0a0cb50" +checksum = "445e881f4f6d382d5f27c034e25eb92edd7c784ceab92a0937db7f2e9471b938" dependencies = [ "tinyvec_macros", ] @@ -2903,7 +2913,7 @@ dependencies = [ "backtrace", "bytes", "libc", - "mio 1.0.1", + "mio 1.0.2", "parking_lot", "pin-project-lite", "signal-hook-registry", @@ -2920,7 +2930,7 @@ checksum = "693d596312e88961bc67d7f1f97af8a70227d9f90c31bba5806eec004978d752" dependencies = [ "proc-macro2", "quote", - "syn 2.0.57", + "syn 2.0.74", ] [[package]] @@ -2959,16 +2969,15 @@ dependencies = [ [[package]] name = "tokio-util" -version = "0.7.10" +version = "0.7.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5419f34732d9eb6ee4c3578b7989078579b7f039cbbb9ca2c4da015749371e15" +checksum = "9cf6b47b3771c49ac75ad09a6162f53ad4b8088b76ac60e8ec1455b31a189fe1" dependencies = [ "bytes", "futures-core", "futures-sink", "pin-project-lite", "tokio", - "tracing", ] [[package]] @@ -3025,7 +3034,7 @@ dependencies = [ "async-stream", "async-trait", "axum", - "base64 0.22.1", + "base64", "bytes", "h2", "http", @@ -3058,7 +3067,7 @@ dependencies = [ "proc-macro2", "prost-build", "quote", - "syn 2.0.57", + "syn 2.0.74", ] [[package]] @@ -3083,15 +3092,15 @@ dependencies = [ [[package]] name = "tower-layer" -version = "0.3.2" +version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c20c8dbed6283a09604c3e69b4b7eeb54e298b8a600d4d5ecb5ad39de609f1d0" +checksum = "121c2a6cda46980bb0fcd1647ffaf6cd3fc79a013de288782836f6df9c48780e" [[package]] name = "tower-service" -version = "0.3.2" +version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6bc1c9ce2b5135ac7f93c72918fc37feb872bdc6a5533a8b85eb4b86bfdae52" +checksum = "8df9b6e13f2d32c91b9bd719c00d1958837bc7dec474d94952798cc8e69eeec3" [[package]] name = "tracing" @@ -3113,7 +3122,7 @@ checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.57", + "syn 2.0.74", ] [[package]] @@ -3177,11 +3186,12 @@ checksum = "d4c87d22b6e3f4a18d4d40ef354e97c90fcb14dd91d7dc0aa9d8a1172ebf7202" [[package]] name = "unicode-truncate" -version = "1.0.0" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a5fbabedabe362c618c714dbefda9927b5afc8e2a8102f47f081089a9019226" +checksum = "b3644627a5af5fa321c95b9b235a72fd24cd29c648c2c379431e6628655627bf" dependencies = [ - "itertools 0.12.1", + "itertools", + "unicode-segmentation", "unicode-width", ] @@ -3216,9 +3226,9 @@ dependencies = [ [[package]] name = "utf8parse" -version = "0.2.1" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a" +checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" [[package]] name = "uuid" @@ -3231,9 +3241,9 @@ dependencies = [ [[package]] name = "version_check" -version = "0.9.4" +version = "0.9.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" +checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" [[package]] name = "walkdir" @@ -3262,34 +3272,35 @@ checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" [[package]] name = "wasm-bindgen" -version = "0.2.92" +version = "0.2.93" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4be2531df63900aeb2bca0daaaddec08491ee64ceecbee5076636a3b026795a8" +checksum = "a82edfc16a6c469f5f44dc7b571814045d60404b55a0ee849f9bcfa2e63dd9b5" dependencies = [ "cfg-if", + "once_cell", "wasm-bindgen-macro", ] [[package]] name = "wasm-bindgen-backend" -version = "0.2.92" +version = "0.2.93" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "614d787b966d3989fa7bb98a654e369c762374fd3213d212cfc0251257e747da" +checksum = "9de396da306523044d3302746f1208fa71d7532227f15e347e2d93e4145dd77b" dependencies = [ "bumpalo", "log", "once_cell", "proc-macro2", "quote", - "syn 2.0.57", + "syn 2.0.74", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-futures" -version = "0.4.42" +version = "0.4.43" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "76bc14366121efc8dbb487ab05bcc9d346b3b5ec0eaa76e46594cabbe51762c0" +checksum = "61e9300f63a621e96ed275155c108eb6f843b6a26d053f122ab69724559dc8ed" dependencies = [ "cfg-if", "js-sys", @@ -3299,9 +3310,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro" -version = "0.2.92" +version = "0.2.93" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1f8823de937b71b9460c0c34e25f3da88250760bec0ebac694b49997550d726" +checksum = "585c4c91a46b072c92e908d99cb1dcdf95c5218eeb6f3bf1efa991ee7a68cccf" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -3309,28 +3320,28 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.92" +version = "0.2.93" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e94f17b526d0a461a191c78ea52bbce64071ed5c04c9ffe424dcb38f74171bb7" +checksum = "afc340c74d9005395cf9dd098506f7f44e38f2b4a21c6aaacf9a105ea5e1e836" dependencies = [ "proc-macro2", "quote", - "syn 2.0.57", + "syn 2.0.74", "wasm-bindgen-backend", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-shared" -version = "0.2.92" +version = "0.2.93" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af190c94f2773fdb3729c55b007a722abb5384da03bc0986df4c289bf5567e96" +checksum = "c62a0a307cb4a311d3a07867860911ca130c3494e8c2719593806c08bc5d0484" [[package]] name = "web-sys" -version = "0.3.69" +version = "0.3.70" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77afa9a11836342370f4817622a2f0f418b134426d91a82dfb48f532d2ec13ef" +checksum = "26fdeaafd9bd129f65e7c031593c24d62186301e0c72c8978fa1678be7d532c0" dependencies = [ "js-sys", "wasm-bindgen", @@ -3338,9 +3349,9 @@ dependencies = [ [[package]] name = "webpki-roots" -version = "0.26.1" +version = "0.26.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b3de34ae270483955a94f4b21bdaaeb83d508bb84a01435f393818edb0012009" +checksum = "bd7c23921eeb1713a4e851530e9b9756e4fb0e89978582942612524cf09f01cd" dependencies = [ "rustls-pki-types", ] @@ -3363,11 +3374,11 @@ checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" [[package]] name = "winapi-util" -version = "0.1.6" +version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f29e6f9198ba0d26b4c9f07dbe6f9ed633e1f3d5b8b414090084349e46a52596" +checksum = "cf221c93e13a30d793f7645a0e7762c55d169dbb0a49671918a2319d289b10bb" dependencies = [ - "winapi", + "windows-sys 0.59.0", ] [[package]] @@ -3602,53 +3613,54 @@ dependencies = [ [[package]] name = "zerocopy" -version = "0.7.32" +version = "0.7.35" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74d4d3961e53fa4c9a25a8637fc2bfaf2595b3d3ae34875568a5cf64787716be" +checksum = "1b9b4fd18abc82b8136838da5d50bae7bdea537c574d8dc1a34ed098d6c166f0" dependencies = [ + "byteorder", "zerocopy-derive", ] [[package]] name = "zerocopy-derive" -version = "0.7.32" +version = "0.7.35" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ce1b18ccd8e73a9321186f97e46f9f04b778851177567b1975109d26a08d2a6" +checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e" dependencies = [ "proc-macro2", "quote", - "syn 2.0.57", + "syn 2.0.74", ] [[package]] name = "zeroize" -version = "1.7.0" +version = "1.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "525b4ec142c6b68a2d10f01f7bbf6755599ca3f81ea53b8431b7dd348f5fdb2d" +checksum = "ced3678a2879b30306d323f4542626697a464a97c0a07c9aebf7ebca65cd4dde" [[package]] name = "zstd" -version = "0.13.1" +version = "0.13.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2d789b1514203a1120ad2429eae43a7bd32b90976a7bb8a05f7ec02fa88cc23a" +checksum = "fcf2b778a664581e31e389454a7072dab1647606d44f7feea22cd5abb9c9f3f9" dependencies = [ "zstd-safe", ] [[package]] name = "zstd-safe" -version = "7.1.0" +version = "7.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1cd99b45c6bc03a018c8b8a86025678c87e55526064e38f9df301989dce7ec0a" +checksum = "54a3ab4db68cea366acc5c897c7b4d4d1b8994a9cd6e6f841f8964566a419059" dependencies = [ "zstd-sys", ] [[package]] name = "zstd-sys" -version = "2.0.10+zstd.1.5.6" +version = "2.0.13+zstd.1.5.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c253a4914af5bafc8fa8c86ee400827e83cf6ec01195ec1f1ed8441bf00d65aa" +checksum = "38ff0f21cfee8f97d94cef41359e0c89aa6113028ab0291aa8ca0038995a95aa" dependencies = [ "cc", "pkg-config", diff --git a/crates/ctl/src/cli/host/cpu_topology.rs b/crates/ctl/src/cli/host/cpu_topology.rs index 253ad2f..cf7911b 100644 --- a/crates/ctl/src/cli/host/cpu_topology.rs +++ b/crates/ctl/src/cli/host/cpu_topology.rs @@ -3,7 +3,7 @@ use clap::{Parser, ValueEnum}; use comfy_table::presets::UTF8_FULL_CONDENSED; use comfy_table::{Cell, Table}; use krata::v1::control::{ - control_service_client::ControlServiceClient, HostCpuTopologyClass, HostCpuTopologyRequest, + control_service_client::ControlServiceClient, GetHostCpuTopologyRequest, HostCpuTopologyClass, }; use tonic::{transport::Channel, Request}; @@ -31,7 +31,7 @@ pub struct HostCpuTopologyCommand { impl HostCpuTopologyCommand { pub async fn run(self, mut client: ControlServiceClient) -> Result<()> { let response = client - .get_host_cpu_topology(Request::new(HostCpuTopologyRequest {})) + .get_host_cpu_topology(Request::new(GetHostCpuTopologyRequest {})) .await? .into_inner(); diff --git a/crates/ctl/src/cli/host/identify.rs b/crates/ctl/src/cli/host/identify.rs index caf60f5..858bbee 100644 --- a/crates/ctl/src/cli/host/identify.rs +++ b/crates/ctl/src/cli/host/identify.rs @@ -1,17 +1,17 @@ use anyhow::Result; use clap::Parser; -use krata::v1::control::{control_service_client::ControlServiceClient, IdentifyHostRequest}; +use krata::v1::control::{control_service_client::ControlServiceClient, HostStatusRequest}; use tonic::{transport::Channel, Request}; #[derive(Parser)] -#[command(about = "Identify information about the host")] -pub struct HostIdentifyCommand {} +#[command(about = "Get information about the host")] +pub struct HostStatusCommand {} -impl HostIdentifyCommand { +impl HostStatusCommand { pub async fn run(self, mut client: ControlServiceClient) -> Result<()> { let response = client - .identify_host(Request::new(IdentifyHostRequest {})) + .host_status(Request::new(HostStatusRequest {})) .await? .into_inner(); println!("Host UUID: {}", response.host_uuid); diff --git a/crates/ctl/src/cli/host/mod.rs b/crates/ctl/src/cli/host/mod.rs index ca6d853..9c08dbe 100644 --- a/crates/ctl/src/cli/host/mod.rs +++ b/crates/ctl/src/cli/host/mod.rs @@ -6,7 +6,7 @@ use krata::events::EventStream; use krata::v1::control::control_service_client::ControlServiceClient; use crate::cli::host::cpu_topology::HostCpuTopologyCommand; -use crate::cli::host::identify::HostIdentifyCommand; +use crate::cli::host::identify::HostStatusCommand; use crate::cli::host::idm_snoop::HostIdmSnoopCommand; pub mod cpu_topology; @@ -33,7 +33,7 @@ impl HostCommand { #[derive(Subcommand)] pub enum HostCommands { CpuTopology(HostCpuTopologyCommand), - Identify(HostIdentifyCommand), + Status(HostStatusCommand), IdmSnoop(HostIdmSnoopCommand), } @@ -46,7 +46,7 @@ impl HostCommands { match self { HostCommands::CpuTopology(cpu_topology) => cpu_topology.run(client).await, - HostCommands::Identify(identify) => identify.run(client).await, + HostCommands::Status(status) => status.run(client).await, HostCommands::IdmSnoop(snoop) => snoop.run(client, events).await, } diff --git a/crates/ctl/src/cli/mod.rs b/crates/ctl/src/cli/mod.rs index 76e0533..8f68ef8 100644 --- a/crates/ctl/src/cli/mod.rs +++ b/crates/ctl/src/cli/mod.rs @@ -12,7 +12,7 @@ use clap::Parser; use krata::{ client::ControlClientProvider, events::EventStream, - v1::control::{control_service_client::ControlServiceClient, ResolveZoneRequest}, + v1::control::{control_service_client::ControlServiceClient, ResolveZoneIdRequest}, }; use tonic::{transport::Channel, Request}; @@ -51,7 +51,7 @@ impl ControlCommand { ControlCommands::Device(device) => device.run(client, events).await, - ControlCommands::Host(snoop) => snoop.run(client, events).await, + ControlCommands::Host(host) => host.run(client, events).await, } } } @@ -61,14 +61,14 @@ pub async fn resolve_zone( name: &str, ) -> Result { let reply = client - .resolve_zone(Request::new(ResolveZoneRequest { + .resolve_zone_id(Request::new(ResolveZoneIdRequest { name: name.to_string(), })) .await? .into_inner(); - if let Some(zone) = reply.zone { - Ok(zone.id) + if !reply.zone_id.is_empty() { + Ok(reply.zone_id) } else { Err(anyhow!("unable to resolve zone '{}'", name)) } diff --git a/crates/ctl/src/cli/zone/destroy.rs b/crates/ctl/src/cli/zone/destroy.rs index de5d59f..543618a 100644 --- a/crates/ctl/src/cli/zone/destroy.rs +++ b/crates/ctl/src/cli/zone/destroy.rs @@ -2,20 +2,16 @@ use anyhow::Result; use clap::Parser; use krata::{ events::EventStream, - v1::{ - common::ZoneStatus, - control::{ - control_service_client::ControlServiceClient, watch_events_reply::Event, - DestroyZoneRequest, - }, + v1::control::{ + control_service_client::ControlServiceClient, watch_events_reply::Event, DestroyZoneRequest, }, }; +use crate::cli::resolve_zone; +use krata::v1::common::ZoneState; use log::error; use tonic::{transport::Channel, Request}; -use crate::cli::resolve_zone; - #[derive(Parser)] #[command(about = "Destroy a zone")] pub struct ZoneDestroyCommand { @@ -61,12 +57,12 @@ async fn wait_zone_destroyed(id: &str, events: EventStream) -> Result<()> { continue; } - let Some(state) = zone.state else { + let Some(status) = zone.status else { continue; }; - if let Some(ref error) = state.error_info { - if state.status() == ZoneStatus::Failed { + if let Some(ref error) = status.error_status { + if status.state() == ZoneState::Failed { error!("destroy failed: {}", error.message); std::process::exit(1); } else { @@ -74,7 +70,7 @@ async fn wait_zone_destroyed(id: &str, events: EventStream) -> Result<()> { } } - if state.status() == ZoneStatus::Destroyed { + if status.state() == ZoneState::Destroyed { std::process::exit(0); } } diff --git a/crates/ctl/src/cli/zone/exec.rs b/crates/ctl/src/cli/zone/exec.rs index 0cd4b63..e0ba4bf 100644 --- a/crates/ctl/src/cli/zone/exec.rs +++ b/crates/ctl/src/cli/zone/exec.rs @@ -5,7 +5,7 @@ use anyhow::Result; use clap::Parser; use krata::v1::{ common::{ZoneTaskSpec, ZoneTaskSpecEnvVar}, - control::{control_service_client::ControlServiceClient, ExecZoneRequest}, + control::{control_service_client::ControlServiceClient, ExecInsideZoneRequest}, }; use tonic::{transport::Channel, Request}; @@ -34,7 +34,7 @@ pub struct ZoneExecCommand { impl ZoneExecCommand { pub async fn run(self, mut client: ControlServiceClient) -> Result<()> { let zone_id: String = resolve_zone(&mut client, &self.zone).await?; - let initial = ExecZoneRequest { + let initial = ExecInsideZoneRequest { zone_id, task: Some(ZoneTaskSpec { environment: env_map(&self.env.unwrap_or_default()) @@ -52,7 +52,10 @@ impl ZoneExecCommand { let stream = StdioConsoleStream::stdin_stream_exec(initial).await; - let response = client.exec_zone(Request::new(stream)).await?.into_inner(); + let response = client + .exec_inside_zone(Request::new(stream)) + .await? + .into_inner(); let code = StdioConsoleStream::exec_output(response).await?; std::process::exit(code); diff --git a/crates/ctl/src/cli/zone/launch.rs b/crates/ctl/src/cli/zone/launch.rs index 53ca8b2..611cd3a 100644 --- a/crates/ctl/src/cli/zone/launch.rs +++ b/crates/ctl/src/cli/zone/launch.rs @@ -7,7 +7,7 @@ use krata::{ v1::{ common::{ zone_image_spec::Image, OciImageFormat, ZoneImageSpec, ZoneOciImageSpec, ZoneSpec, - ZoneSpecDevice, ZoneStatus, ZoneTaskSpec, ZoneTaskSpecEnvVar, + ZoneSpecDevice, ZoneState, ZoneTaskSpec, ZoneTaskSpecEnvVar, }, control::{ control_service_client::ControlServiceClient, watch_events_reply::Event, @@ -120,7 +120,7 @@ impl ZoneLaunchCommand { image: Some(image), kernel, initrd, - vcpus: self.cpus, + cpus: self.cpus, mem: self.mem, task: Some(ZoneTaskSpec { environment: env_map(&self.env.unwrap_or_default()) @@ -209,12 +209,12 @@ async fn wait_zone_started(id: &str, events: EventStream) -> Result<()> { continue; } - let Some(state) = zone.state else { + let Some(status) = zone.status else { continue; }; - if let Some(ref error) = state.error_info { - if state.status() == ZoneStatus::Failed { + if let Some(ref error) = status.error_status { + if status.state() == ZoneState::Failed { error!("launch failed: {}", error.message); std::process::exit(1); } else { @@ -222,12 +222,12 @@ async fn wait_zone_started(id: &str, events: EventStream) -> Result<()> { } } - if state.status() == ZoneStatus::Destroyed { + if status.state() == ZoneState::Destroyed { error!("zone destroyed"); std::process::exit(1); } - if state.status() == ZoneStatus::Started { + if status.state() == ZoneState::Created { break; } } diff --git a/crates/ctl/src/cli/zone/list.rs b/crates/ctl/src/cli/zone/list.rs index eef38c5..4129603 100644 --- a/crates/ctl/src/cli/zone/list.rs +++ b/crates/ctl/src/cli/zone/list.rs @@ -4,18 +4,19 @@ use comfy_table::{presets::UTF8_FULL_CONDENSED, Cell, Color, Table}; use krata::{ events::EventStream, v1::{ - common::{Zone, ZoneStatus}, + common::Zone, control::{ - control_service_client::ControlServiceClient, ListZonesRequest, ResolveZoneRequest, + control_service_client::ControlServiceClient, ListZonesRequest, ResolveZoneIdRequest, }, }, }; +use crate::format::{kv2line, proto2dynamic, proto2kv, zone_simple_line, zone_state_text}; +use krata::v1::common::ZoneState; +use krata::v1::control::GetZoneRequest; use serde_json::Value; use tonic::{transport::Channel, Request}; -use crate::format::{kv2line, proto2dynamic, proto2kv, zone_simple_line, zone_status_text}; - #[derive(ValueEnum, Clone, Debug, PartialEq, Eq)] enum ZoneListFormat { Table, @@ -44,11 +45,21 @@ impl ZoneListCommand { ) -> Result<()> { let mut zones = if let Some(ref zone) = self.zone { let reply = client - .resolve_zone(Request::new(ResolveZoneRequest { name: zone.clone() })) + .resolve_zone_id(Request::new(ResolveZoneIdRequest { name: zone.clone() })) .await? .into_inner(); - if let Some(zone) = reply.zone { - vec![zone] + if !reply.zone_id.is_empty() { + let reply = client + .get_zone(Request::new(GetZoneRequest { + zone_id: reply.zone_id, + })) + .await? + .into_inner(); + if let Some(zone) = reply.zone { + vec![zone] + } else { + return Err(anyhow!("unable to resolve zone '{}'", zone)); + } } else { return Err(anyhow!("unable to resolve zone '{}'", zone)); } @@ -115,30 +126,30 @@ impl ZoneListCommand { let mut table = Table::new(); table.load_preset(UTF8_FULL_CONDENSED); table.set_content_arrangement(comfy_table::ContentArrangement::Dynamic); - table.set_header(vec!["name", "uuid", "status", "ipv4", "ipv6"]); + table.set_header(vec!["name", "uuid", "state", "ipv4", "ipv6"]); for zone in zones { let ipv4 = zone - .state + .status .as_ref() - .and_then(|x| x.network.as_ref()) + .and_then(|x| x.network_status.as_ref()) .map(|x| x.zone_ipv4.as_str()) .unwrap_or("n/a"); let ipv6 = zone - .state + .status .as_ref() - .and_then(|x| x.network.as_ref()) + .and_then(|x| x.network_status.as_ref()) .map(|x| x.zone_ipv6.as_str()) .unwrap_or("n/a"); let Some(spec) = zone.spec else { continue; }; - let status = zone.state.as_ref().cloned().unwrap_or_default().status(); - let status_text = zone_status_text(status); + let state = zone.status.as_ref().cloned().unwrap_or_default().state(); + let status_text = zone_state_text(state); - let status_color = match status { - ZoneStatus::Destroyed | ZoneStatus::Failed => Color::Red, - ZoneStatus::Destroying | ZoneStatus::Exited | ZoneStatus::Starting => Color::Yellow, - ZoneStatus::Started => Color::Green, + let status_color = match state { + ZoneState::Destroyed | ZoneState::Failed => Color::Red, + ZoneState::Destroying | ZoneState::Exited | ZoneState::Creating => Color::Yellow, + ZoneState::Created => Color::Green, _ => Color::Reset, }; diff --git a/crates/ctl/src/cli/zone/resolve.rs b/crates/ctl/src/cli/zone/resolve.rs index 34251d6..1e0381d 100644 --- a/crates/ctl/src/cli/zone/resolve.rs +++ b/crates/ctl/src/cli/zone/resolve.rs @@ -1,6 +1,6 @@ use anyhow::Result; use clap::Parser; -use krata::v1::control::{control_service_client::ControlServiceClient, ResolveZoneRequest}; +use krata::v1::control::{control_service_client::ControlServiceClient, ResolveZoneIdRequest}; use tonic::{transport::Channel, Request}; @@ -14,13 +14,13 @@ pub struct ZoneResolveCommand { impl ZoneResolveCommand { pub async fn run(self, mut client: ControlServiceClient) -> Result<()> { let reply = client - .resolve_zone(Request::new(ResolveZoneRequest { + .resolve_zone_id(Request::new(ResolveZoneIdRequest { name: self.zone.clone(), })) .await? .into_inner(); - if let Some(zone) = reply.zone { - println!("{}", zone.id); + if !reply.zone_id.is_empty() { + println!("{}", reply.zone_id); } else { std::process::exit(1); } diff --git a/crates/ctl/src/cli/zone/top.rs b/crates/ctl/src/cli/zone/top.rs index 843192c..04c2441 100644 --- a/crates/ctl/src/cli/zone/top.rs +++ b/crates/ctl/src/cli/zone/top.rs @@ -24,7 +24,7 @@ use ratatui::{ }; use crate::{ - format::zone_status_text, + format::zone_state_text, metrics::{ lookup_metric_value, MultiMetricCollector, MultiMetricCollectorHandle, MultiMetricState, }, @@ -106,7 +106,7 @@ impl ZoneTopApp { break; } } - }; + } } Ok(()) } @@ -157,7 +157,7 @@ impl Widget for &mut ZoneTopApp { continue; }; - let Some(ref state) = ms.zone.state else { + let Some(ref status) = ms.zone.status else { continue; }; @@ -177,7 +177,7 @@ impl Widget for &mut ZoneTopApp { let row = Row::new(vec![ spec.name.clone(), ms.zone.id.clone(), - zone_status_text(state.status()), + zone_state_text(status.state()), memory_total.unwrap_or_default(), memory_used.unwrap_or_default(), memory_free.unwrap_or_default(), diff --git a/crates/ctl/src/console.rs b/crates/ctl/src/console.rs index 96282e0..b05b0f6 100644 --- a/crates/ctl/src/console.rs +++ b/crates/ctl/src/console.rs @@ -4,14 +4,12 @@ use crossterm::{ terminal::{disable_raw_mode, enable_raw_mode, is_raw_mode_enabled}, tty::IsTty, }; +use krata::v1::common::ZoneState; use krata::{ events::EventStream, - v1::{ - common::ZoneStatus, - control::{ - watch_events_reply::Event, ExecZoneReply, ExecZoneRequest, ZoneConsoleReply, - ZoneConsoleRequest, - }, + v1::control::{ + watch_events_reply::Event, ExecInsideZoneReply, ExecInsideZoneRequest, ZoneConsoleReply, + ZoneConsoleRequest, }, }; use log::debug; @@ -49,8 +47,8 @@ impl StdioConsoleStream { } pub async fn stdin_stream_exec( - initial: ExecZoneRequest, - ) -> impl Stream { + initial: ExecInsideZoneRequest, + ) -> impl Stream { let mut stdin = stdin(); stream! { yield initial; @@ -68,7 +66,7 @@ impl StdioConsoleStream { if size == 1 && buffer[0] == 0x1d { break; } - yield ExecZoneRequest { zone_id: String::default(), task: None, data }; + yield ExecInsideZoneRequest { zone_id: String::default(), task: None, data }; } } } @@ -90,7 +88,7 @@ impl StdioConsoleStream { Ok(()) } - pub async fn exec_output(mut stream: Streaming) -> Result { + pub async fn exec_output(mut stream: Streaming) -> Result { let mut stdout = stdout(); let mut stderr = stderr(); while let Some(reply) = stream.next().await { @@ -128,7 +126,7 @@ impl StdioConsoleStream { continue; }; - let Some(state) = zone.state else { + let Some(status) = zone.status else { continue; }; @@ -136,12 +134,12 @@ impl StdioConsoleStream { continue; } - if let Some(exit_info) = state.exit_info { - return Some(exit_info.code); + if let Some(exit_status) = status.exit_status { + return Some(exit_status.code); } - let status = state.status(); - if status == ZoneStatus::Destroying || status == ZoneStatus::Destroyed { + let state = status.state(); + if state == ZoneState::Destroying || state == ZoneState::Destroyed { return Some(10); } } diff --git a/crates/ctl/src/format.rs b/crates/ctl/src/format.rs index d95e514..842a634 100644 --- a/crates/ctl/src/format.rs +++ b/crates/ctl/src/format.rs @@ -3,11 +3,12 @@ use std::{collections::HashMap, time::Duration}; use anyhow::Result; use fancy_duration::FancyDuration; use human_bytes::human_bytes; -use krata::v1::common::{Zone, ZoneMetricFormat, ZoneMetricNode, ZoneStatus}; use prost_reflect::{DynamicMessage, ReflectMessage}; use prost_types::Value; use termtree::Tree; +use krata::v1::common::{Zone, ZoneMetricFormat, ZoneMetricNode, ZoneState}; + pub fn proto2dynamic(proto: impl ReflectMessage) -> Result { Ok(DynamicMessage::decode( proto.descriptor(), @@ -75,30 +76,30 @@ pub fn kv2line(map: HashMap) -> String { .join(" ") } -pub fn zone_status_text(status: ZoneStatus) -> String { +pub fn zone_state_text(status: ZoneState) -> String { match status { - ZoneStatus::Starting => "starting", - ZoneStatus::Started => "started", - ZoneStatus::Destroying => "destroying", - ZoneStatus::Destroyed => "destroyed", - ZoneStatus::Exited => "exited", - ZoneStatus::Failed => "failed", + ZoneState::Creating => "creating", + ZoneState::Created => "created", + ZoneState::Destroying => "destroying", + ZoneState::Destroyed => "destroyed", + ZoneState::Exited => "exited", + ZoneState::Failed => "failed", _ => "unknown", } .to_string() } pub fn zone_simple_line(zone: &Zone) -> String { - let state = zone_status_text( - zone.state + let state = zone_state_text( + zone.status .as_ref() - .map(|x| x.status()) - .unwrap_or(ZoneStatus::Unknown), + .map(|x| x.state()) + .unwrap_or(ZoneState::Unknown), ); let name = zone.spec.as_ref().map(|x| x.name.as_str()).unwrap_or(""); - let network = zone.state.as_ref().and_then(|x| x.network.as_ref()); - let ipv4 = network.map(|x| x.zone_ipv4.as_str()).unwrap_or(""); - let ipv6 = network.map(|x| x.zone_ipv6.as_str()).unwrap_or(""); + let network_status = zone.status.as_ref().and_then(|x| x.network_status.as_ref()); + let ipv4 = network_status.map(|x| x.zone_ipv4.as_str()).unwrap_or(""); + let ipv6 = network_status.map(|x| x.zone_ipv6.as_str()).unwrap_or(""); format!("{}\t{}\t{}\t{}\t{}", zone.id, state, name, ipv4, ipv6) } diff --git a/crates/ctl/src/metrics.rs b/crates/ctl/src/metrics.rs index faad956..0a7a76e 100644 --- a/crates/ctl/src/metrics.rs +++ b/crates/ctl/src/metrics.rs @@ -1,8 +1,10 @@ +use crate::format::metrics_value_pretty; use anyhow::Result; +use krata::v1::common::ZoneState; use krata::{ events::EventStream, v1::{ - common::{Zone, ZoneMetricNode, ZoneStatus}, + common::{Zone, ZoneMetricNode}, control::{ control_service_client::ControlServiceClient, watch_events_reply::Event, ListZonesRequest, ReadZoneMetricsRequest, @@ -19,8 +21,6 @@ use tokio::{ }; use tonic::transport::Channel; -use crate::format::metrics_value_pretty; - pub struct MetricState { pub zone: Zone, pub root: Option, @@ -86,11 +86,11 @@ impl MultiMetricCollector { let Some(zone) = changed.zone else { continue; }; - let Some(ref state) = zone.state else { + let Some(ref status) = zone.status else { continue; }; zones.retain(|x| x.id != zone.id); - if state.status() != ZoneStatus::Destroying { + if status.state() != ZoneState::Destroying { zones.push(zone); } false @@ -112,11 +112,11 @@ impl MultiMetricCollector { let mut metrics = Vec::new(); for zone in &zones { - let Some(ref state) = zone.state else { + let Some(ref status) = zone.status else { continue; }; - if state.status() != ZoneStatus::Started { + if status.state() != ZoneState::Created { continue; } diff --git a/crates/daemon/Cargo.toml b/crates/daemon/Cargo.toml index cd72dcd..ce6cbca 100644 --- a/crates/daemon/Cargo.toml +++ b/crates/daemon/Cargo.toml @@ -9,6 +9,7 @@ edition = "2021" resolver = "2" [dependencies] +krata-advmac = { workspace = true } anyhow = { workspace = true } async-stream = { workspace = true } async-trait = { workspace = true } @@ -17,6 +18,7 @@ circular-buffer = { workspace = true } clap = { workspace = true } env_logger = { workspace = true } futures = { workspace = true } +ipnetwork = { workspace = true } krata = { path = "../krata", version = "^0.0.15" } krata-oci = { path = "../oci", version = "^0.0.15" } krata-runtime = { path = "../runtime", version = "^0.0.15" } @@ -25,6 +27,7 @@ prost = { workspace = true } redb = { workspace = true } scopeguard = { workspace = true } serde = { workspace = true } +serde_json = { workspace = true } signal-hook = { workspace = true } tokio = { workspace = true } tokio-stream = { workspace = true } diff --git a/crates/daemon/src/config.rs b/crates/daemon/src/config.rs index 731f198..ad48573 100644 --- a/crates/daemon/src/config.rs +++ b/crates/daemon/src/config.rs @@ -10,6 +10,8 @@ pub struct DaemonConfig { pub oci: OciConfig, #[serde(default)] pub pci: DaemonPciConfig, + #[serde(default = "default_network")] + pub network: DaemonNetworkConfig, } #[derive(Serialize, Deserialize, Clone, Debug, Default)] @@ -49,6 +51,65 @@ pub enum DaemonPciDeviceRdmReservePolicy { Relaxed, } +#[derive(Serialize, Deserialize, Clone, Debug, Default)] +pub struct DaemonNetworkConfig { + #[serde(default = "default_network_nameservers")] + pub nameservers: Vec, + #[serde(default = "default_network_ipv4")] + pub ipv4: DaemonIpv4NetworkConfig, + #[serde(default = "default_network_ipv6")] + pub ipv6: DaemonIpv6NetworkConfig, +} + +#[derive(Serialize, Deserialize, Clone, Debug, Default)] +pub struct DaemonIpv4NetworkConfig { + #[serde(default = "default_network_ipv4_subnet")] + pub subnet: String, +} + +#[derive(Serialize, Deserialize, Clone, Debug, Default)] +pub struct DaemonIpv6NetworkConfig { + #[serde(default = "default_network_ipv6_subnet")] + pub subnet: String, +} + +fn default_network() -> DaemonNetworkConfig { + DaemonNetworkConfig { + nameservers: default_network_nameservers(), + ipv4: default_network_ipv4(), + ipv6: default_network_ipv6(), + } +} + +fn default_network_nameservers() -> Vec { + vec![ + "1.1.1.1".to_string(), + "1.0.0.1".to_string(), + "2606:4700:4700::1111".to_string(), + "2606:4700:4700::1001".to_string(), + ] +} + +fn default_network_ipv4() -> DaemonIpv4NetworkConfig { + DaemonIpv4NetworkConfig { + subnet: default_network_ipv4_subnet(), + } +} + +fn default_network_ipv4_subnet() -> String { + "10.75.80.0/24".to_string() +} + +fn default_network_ipv6() -> DaemonIpv6NetworkConfig { + DaemonIpv6NetworkConfig { + subnet: default_network_ipv6_subnet(), + } +} + +fn default_network_ipv6_subnet() -> String { + "fdd4:1476:6c7e::/48".to_string() +} + impl DaemonConfig { pub async fn load(path: &Path) -> Result { if path.exists() { diff --git a/crates/daemon/src/control.rs b/crates/daemon/src/control.rs index 419abab..3fed4e6 100644 --- a/crates/daemon/src/control.rs +++ b/crates/daemon/src/control.rs @@ -1,5 +1,15 @@ +use crate::db::zone::ZoneStore; +use crate::{ + command::DaemonCommand, console::DaemonConsoleHandle, devices::DaemonDeviceManager, + event::DaemonEventContext, idm::DaemonIdmHandle, metrics::idm_metric_to_api, + oci::convert_oci_progress, zlt::ZoneLookupTable, +}; use async_stream::try_stream; use futures::Stream; +use krata::v1::control::{ + GetZoneReply, GetZoneRequest, SetHostPowerManagementPolicyReply, + SetHostPowerManagementPolicyRequest, +}; use krata::{ idm::internal::{ exec_stream_request_update::Update, request::Request as IdmRequestType, @@ -10,11 +20,11 @@ use krata::{ common::{OciImageFormat, Zone, ZoneState, ZoneStatus}, control::{ control_service_server::ControlService, CreateZoneReply, CreateZoneRequest, - DestroyZoneReply, DestroyZoneRequest, DeviceInfo, ExecZoneReply, ExecZoneRequest, - HostCpuTopologyInfo, HostCpuTopologyReply, HostCpuTopologyRequest, - HostPowerManagementPolicy, IdentifyHostReply, IdentifyHostRequest, ListDevicesReply, + DestroyZoneReply, DestroyZoneRequest, DeviceInfo, ExecInsideZoneReply, + ExecInsideZoneRequest, GetHostCpuTopologyReply, GetHostCpuTopologyRequest, + HostCpuTopologyInfo, HostStatusReply, HostStatusRequest, ListDevicesReply, ListDevicesRequest, ListZonesReply, ListZonesRequest, PullImageReply, PullImageRequest, - ReadZoneMetricsReply, ReadZoneMetricsRequest, ResolveZoneReply, ResolveZoneRequest, + ReadZoneMetricsReply, ReadZoneMetricsRequest, ResolveZoneIdReply, ResolveZoneIdRequest, SnoopIdmReply, SnoopIdmRequest, WatchEventsReply, WatchEventsRequest, ZoneConsoleReply, ZoneConsoleRequest, }, @@ -36,12 +46,6 @@ use tokio_stream::StreamExt; use tonic::{Request, Response, Status, Streaming}; use uuid::Uuid; -use crate::{ - command::DaemonCommand, console::DaemonConsoleHandle, db::ZoneStore, - devices::DaemonDeviceManager, event::DaemonEventContext, idm::DaemonIdmHandle, - metrics::idm_metric_to_api, oci::convert_oci_progress, zlt::ZoneLookupTable, -}; - pub struct ApiError { message: String, } @@ -112,8 +116,8 @@ enum PullImageSelect { #[tonic::async_trait] impl ControlService for DaemonControlService { - type ExecZoneStream = - Pin> + Send + 'static>>; + type ExecInsideZoneStream = + Pin> + Send + 'static>>; type AttachZoneConsoleStream = Pin> + Send + 'static>>; @@ -127,12 +131,12 @@ impl ControlService for DaemonControlService { type SnoopIdmStream = Pin> + Send + 'static>>; - async fn identify_host( + async fn host_status( &self, - request: Request, - ) -> Result, Status> { + request: Request, + ) -> Result, Status> { let _ = request.into_inner(); - Ok(Response::new(IdentifyHostReply { + Ok(Response::new(HostStatusReply { host_domid: self.glt.host_domid(), host_uuid: self.glt.host_uuid().to_string(), krata_version: DaemonCommand::version(), @@ -156,11 +160,11 @@ impl ControlService for DaemonControlService { uuid, Zone { id: uuid.to_string(), - state: Some(ZoneState { - status: ZoneStatus::Starting.into(), - network: None, - exit_info: None, - error_info: None, + status: Some(ZoneStatus { + state: ZoneState::Creating.into(), + network_status: None, + exit_status: None, + error_status: None, host: self.glt.host_uuid().to_string(), domid: u32::MAX, }), @@ -180,10 +184,10 @@ impl ControlService for DaemonControlService { })) } - async fn exec_zone( + async fn exec_inside_zone( &self, - request: Request>, - ) -> Result, Status> { + request: Request>, + ) -> Result, Status> { let mut input = request.into_inner(); let Some(request) = input.next().await else { return Err(ApiError { @@ -232,7 +236,7 @@ impl ControlService for DaemonControlService { loop { select! { x = input.next() => if let Some(update) = x { - let update: Result = update.map_err(|error| ApiError { + let update: Result = update.map_err(|error| ApiError { message: error.to_string() }.into()); @@ -252,7 +256,7 @@ impl ControlService for DaemonControlService { let Some(IdmResponseType::ExecStream(update)) = response.response else { break; }; - let reply = ExecZoneReply { + let reply = ExecInsideZoneReply { exited: update.exited, error: update.error, exit_code: update.exit_code, @@ -265,11 +269,11 @@ impl ControlService for DaemonControlService { break; } } - }; + } } }; - Ok(Response::new(Box::pin(output) as Self::ExecZoneStream)) + Ok(Response::new(Box::pin(output) as Self::ExecInsideZoneStream)) } async fn destroy_zone( @@ -287,16 +291,16 @@ impl ControlService for DaemonControlService { .into()); }; - zone.state = Some(zone.state.as_mut().cloned().unwrap_or_default()); + zone.status = Some(zone.status.as_mut().cloned().unwrap_or_default()); - if zone.state.as_ref().unwrap().status() == ZoneStatus::Destroyed { + if zone.status.as_ref().unwrap().state() == ZoneState::Destroyed { return Err(ApiError { message: "zone already destroyed".to_string(), } .into()); } - zone.state.as_mut().unwrap().status = ZoneStatus::Destroying.into(); + zone.status.as_mut().unwrap().state = ZoneState::Destroying.into(); self.zones .update(uuid, zone) .await @@ -320,10 +324,10 @@ impl ControlService for DaemonControlService { Ok(Response::new(ListZonesReply { zones })) } - async fn resolve_zone( + async fn resolve_zone_id( &self, - request: Request, - ) -> Result, Status> { + request: Request, + ) -> Result, Status> { let request = request.into_inner(); let zones = self.zones.list().await.map_err(ApiError::from)?; let zones = zones @@ -334,8 +338,8 @@ impl ControlService for DaemonControlService { || x.id == request.name }) .collect::>(); - Ok(Response::new(ResolveZoneReply { - zone: zones.first().cloned(), + Ok(Response::new(ResolveZoneIdReply { + zone_id: zones.first().cloned().map(|x| x.id).unwrap_or_default(), })) } @@ -558,8 +562,8 @@ impl ControlService for DaemonControlService { async fn get_host_cpu_topology( &self, - request: Request, - ) -> Result, Status> { + request: Request, + ) -> Result, Status> { let _ = request.into_inner(); let power = self .runtime @@ -579,13 +583,13 @@ impl ControlService for DaemonControlService { }) } - Ok(Response::new(HostCpuTopologyReply { cpus })) + Ok(Response::new(GetHostCpuTopologyReply { cpus })) } async fn set_host_power_management_policy( &self, - request: Request, - ) -> Result, Status> { + request: Request, + ) -> Result, Status> { let policy = request.into_inner(); let power = self .runtime @@ -603,9 +607,20 @@ impl ControlService for DaemonControlService { .await .map_err(ApiError::from)?; - Ok(Response::new(HostPowerManagementPolicy { - scheduler: scheduler.to_string(), - smt_awareness: policy.smt_awareness, + Ok(Response::new(SetHostPowerManagementPolicyReply {})) + } + + async fn get_zone( + &self, + request: Request, + ) -> Result, Status> { + let request = request.into_inner(); + let zones = self.zones.list().await.map_err(ApiError::from)?; + let zone = zones.get(&Uuid::from_str(&request.zone_id).map_err(|error| ApiError { + message: error.to_string(), + })?); + Ok(Response::new(GetZoneReply { + zone: zone.cloned(), })) } } diff --git a/crates/daemon/src/db/ip.rs b/crates/daemon/src/db/ip.rs new file mode 100644 index 0000000..d169d0d --- /dev/null +++ b/crates/daemon/src/db/ip.rs @@ -0,0 +1,118 @@ +use crate::db::KrataDatabase; +use advmac::MacAddr6; +use anyhow::Result; +use log::error; +use redb::{ReadableTable, TableDefinition}; +use serde::{Deserialize, Serialize}; +use std::collections::HashMap; +use std::net::{Ipv4Addr, Ipv6Addr}; +use uuid::Uuid; + +const IP_RESERVATION_TABLE: TableDefinition = TableDefinition::new("ip-reservation"); + +#[derive(Clone)] +pub struct IpReservationStore { + db: KrataDatabase, +} + +impl IpReservationStore { + pub fn open(db: KrataDatabase) -> Result { + let write = db.database.begin_write()?; + let _ = write.open_table(IP_RESERVATION_TABLE); + write.commit()?; + Ok(IpReservationStore { db }) + } + + pub async fn read(&self, id: Uuid) -> Result> { + let read = self.db.database.begin_read()?; + let table = read.open_table(IP_RESERVATION_TABLE)?; + let Some(entry) = table.get(id.to_u128_le())? else { + return Ok(None); + }; + let bytes = entry.value(); + Ok(Some(serde_json::from_slice(bytes)?)) + } + + pub async fn list(&self) -> Result> { + enum ListEntry { + Valid(Uuid, IpReservation), + Invalid(Uuid), + } + let mut reservations: HashMap = HashMap::new(); + + let corruptions = { + let read = self.db.database.begin_read()?; + let table = read.open_table(IP_RESERVATION_TABLE)?; + table + .iter()? + .flat_map(|result| { + result.map(|(key, value)| { + let uuid = Uuid::from_u128_le(key.value()); + match serde_json::from_slice::(value.value()) { + Ok(reservation) => ListEntry::Valid(uuid, reservation), + Err(error) => { + error!( + "found invalid ip reservation in database for uuid {}: {}", + uuid, error + ); + ListEntry::Invalid(uuid) + } + } + }) + }) + .filter_map(|entry| match entry { + ListEntry::Valid(uuid, reservation) => { + reservations.insert(uuid, reservation); + None + } + + ListEntry::Invalid(uuid) => Some(uuid), + }) + .collect::>() + }; + + if !corruptions.is_empty() { + let write = self.db.database.begin_write()?; + let mut table = write.open_table(IP_RESERVATION_TABLE)?; + for corruption in corruptions { + table.remove(corruption.to_u128_le())?; + } + } + + Ok(reservations) + } + + pub async fn update(&self, id: Uuid, entry: IpReservation) -> Result<()> { + let write = self.db.database.begin_write()?; + { + let mut table = write.open_table(IP_RESERVATION_TABLE)?; + let bytes = serde_json::to_vec(&entry)?; + table.insert(id.to_u128_le(), bytes.as_slice())?; + } + write.commit()?; + Ok(()) + } + + pub async fn remove(&self, id: Uuid) -> Result<()> { + let write = self.db.database.begin_write()?; + { + let mut table = write.open_table(IP_RESERVATION_TABLE)?; + table.remove(id.to_u128_le())?; + } + write.commit()?; + Ok(()) + } +} + +#[derive(Serialize, Deserialize, Clone, Debug)] +pub struct IpReservation { + pub uuid: String, + pub ipv4: Ipv4Addr, + pub ipv6: Ipv6Addr, + pub mac: MacAddr6, + pub ipv4_prefix: u8, + pub ipv6_prefix: u8, + pub gateway_ipv4: Ipv4Addr, + pub gateway_ipv6: Ipv6Addr, + pub gateway_mac: MacAddr6, +} diff --git a/crates/daemon/src/db/mod.rs b/crates/daemon/src/db/mod.rs new file mode 100644 index 0000000..5d2f70b --- /dev/null +++ b/crates/daemon/src/db/mod.rs @@ -0,0 +1,21 @@ +use anyhow::Result; +use redb::Database; +use std::path::Path; +use std::sync::Arc; + +pub mod ip; +pub mod zone; + +#[derive(Clone)] +pub struct KrataDatabase { + pub database: Arc, +} + +impl KrataDatabase { + pub fn open(path: &Path) -> Result { + let database = Database::create(path)?; + Ok(KrataDatabase { + database: Arc::new(database), + }) + } +} diff --git a/crates/daemon/src/db.rs b/crates/daemon/src/db/zone.rs similarity index 64% rename from crates/daemon/src/db.rs rename to crates/daemon/src/db/zone.rs index df2c78d..e56347e 100644 --- a/crates/daemon/src/db.rs +++ b/crates/daemon/src/db/zone.rs @@ -1,33 +1,31 @@ -use std::{collections::HashMap, path::Path, sync::Arc}; +use std::collections::HashMap; +use crate::db::KrataDatabase; use anyhow::Result; use krata::v1::common::Zone; use log::error; use prost::Message; -use redb::{Database, ReadableTable, TableDefinition}; +use redb::{ReadableTable, TableDefinition}; use uuid::Uuid; -const ZONES: TableDefinition = TableDefinition::new("zones"); +const ZONE_TABLE: TableDefinition = TableDefinition::new("zone"); #[derive(Clone)] pub struct ZoneStore { - database: Arc, + db: KrataDatabase, } impl ZoneStore { - pub fn open(path: &Path) -> Result { - let database = Database::create(path)?; - let write = database.begin_write()?; - let _ = write.open_table(ZONES); + pub fn open(db: KrataDatabase) -> Result { + let write = db.database.begin_write()?; + let _ = write.open_table(ZONE_TABLE); write.commit()?; - Ok(ZoneStore { - database: Arc::new(database), - }) + Ok(ZoneStore { db }) } pub async fn read(&self, id: Uuid) -> Result> { - let read = self.database.begin_read()?; - let table = read.open_table(ZONES)?; + let read = self.db.database.begin_read()?; + let table = read.open_table(ZONE_TABLE)?; let Some(entry) = table.get(id.to_u128_le())? else { return Ok(None); }; @@ -37,8 +35,8 @@ impl ZoneStore { pub async fn list(&self) -> Result> { let mut zones: HashMap = HashMap::new(); - let read = self.database.begin_read()?; - let table = read.open_table(ZONES)?; + let read = self.db.database.begin_read()?; + let table = read.open_table(ZONE_TABLE)?; for result in table.iter()? { let (key, value) = result?; let uuid = Uuid::from_u128_le(key.value()); @@ -58,9 +56,9 @@ impl ZoneStore { } pub async fn update(&self, id: Uuid, entry: Zone) -> Result<()> { - let write = self.database.begin_write()?; + let write = self.db.database.begin_write()?; { - let mut table = write.open_table(ZONES)?; + let mut table = write.open_table(ZONE_TABLE)?; let bytes = entry.encode_to_vec(); table.insert(id.to_u128_le(), bytes.as_slice())?; } @@ -69,9 +67,9 @@ impl ZoneStore { } pub async fn remove(&self, id: Uuid) -> Result<()> { - let write = self.database.begin_write()?; + let write = self.db.database.begin_write()?; { - let mut table = write.open_table(ZONES)?; + let mut table = write.open_table(ZONE_TABLE)?; table.remove(id.to_u128_le())?; } write.commit()?; diff --git a/crates/daemon/src/event.rs b/crates/daemon/src/event.rs index f92c215..8fb965d 100644 --- a/crates/daemon/src/event.rs +++ b/crates/daemon/src/event.rs @@ -4,9 +4,10 @@ use std::{ time::Duration, }; -use crate::{db::ZoneStore, idm::DaemonIdmHandle}; +use crate::db::zone::ZoneStore; +use crate::idm::DaemonIdmHandle; use anyhow::Result; -use krata::v1::common::ZoneExitInfo; +use krata::v1::common::ZoneExitStatus; use krata::{ idm::{internal::event::Event as EventType, internal::Event}, v1::common::{ZoneState, ZoneStatus}, @@ -83,15 +84,15 @@ impl DaemonEventGenerator { return Ok(()); }; - let Some(ref state) = zone.state else { + let Some(ref status) = zone.status else { return Ok(()); }; - let status = state.status(); + let state = status.state(); let id = Uuid::from_str(&zone.id)?; - let domid = state.domid; - match status { - ZoneStatus::Started => { + let domid = status.domid; + match state { + ZoneState::Created => { if let Entry::Vacant(e) = self.idms.entry(domid) { let client = self.idm.client_by_domid(domid).await?; let mut receiver = client.subscribe().await?; @@ -111,7 +112,7 @@ impl DaemonEventGenerator { } } - ZoneStatus::Destroyed => { + ZoneState::Destroyed => { if let Some((_, handle)) = self.idms.remove(&domid) { handle.abort(); } @@ -131,13 +132,13 @@ impl DaemonEventGenerator { async fn handle_exit_code(&mut self, id: Uuid, code: i32) -> Result<()> { if let Some(mut zone) = self.zones.read(id).await? { - zone.state = Some(ZoneState { - status: ZoneStatus::Exited.into(), - network: zone.state.clone().unwrap_or_default().network, - exit_info: Some(ZoneExitInfo { code }), - error_info: None, - host: zone.state.clone().map(|x| x.host).unwrap_or_default(), - domid: zone.state.clone().map(|x| x.domid).unwrap_or(u32::MAX), + zone.status = Some(ZoneStatus { + state: ZoneState::Exited.into(), + network_status: zone.status.clone().unwrap_or_default().network_status, + exit_status: Some(ZoneExitStatus { code }), + error_status: None, + host: zone.status.clone().map(|x| x.host).unwrap_or_default(), + domid: zone.status.clone().map(|x| x.domid).unwrap_or(u32::MAX), }); self.zones.update(id, zone).await?; diff --git a/crates/daemon/src/idm.rs b/crates/daemon/src/idm.rs index 94d70f6..83ae771 100644 --- a/crates/daemon/src/idm.rs +++ b/crates/daemon/src/idm.rs @@ -85,13 +85,13 @@ pub struct DaemonIdm { impl DaemonIdm { pub async fn new(glt: ZoneLookupTable) -> Result { - debug!("allocating channel for IDM"); + debug!("allocating channel service for idm"); let (service, tx_raw_sender, rx_receiver) = ChannelService::new("krata-channel".to_string(), None).await?; let (tx_sender, tx_receiver) = channel(100); let (snoop_sender, _) = broadcast::channel(100); - debug!("starting channel service"); + debug!("starting idm channel service"); let task = service.launch().await?; let clients = Arc::new(Mutex::new(HashMap::new())); @@ -133,52 +133,99 @@ impl DaemonIdm { }) } + async fn process_rx_packet( + &mut self, + domid: u32, + data: Option>, + buffers: &mut HashMap, + ) -> Result<()> { + // check if data is present, if it is not, that signals a closed channel. + if let Some(data) = data { + let buffer = buffers.entry(domid).or_insert_with_key(|_| BytesMut::new()); + buffer.extend_from_slice(&data); + loop { + // check if the buffer is less than the header size, if so, wait for more data + if buffer.len() < 6 { + break; + } + + // check for the magic bytes 0xff, 0xff at the start of the message, if that doesn't + // exist, clear the buffer. this ensures that partial messages won't be processed. + if buffer[0] != 0xff || buffer[1] != 0xff { + buffer.clear(); + return Ok(()); + } + + // read the size from the buffer as a little endian u32 + let size = (buffer[2] as u32 + | (buffer[3] as u32) << 8 + | (buffer[4] as u32) << 16 + | (buffer[5] as u32) << 24) as usize; + let needed = size + 6; + if buffer.len() < needed { + return Ok(()); + } + let mut packet = buffer.split_to(needed); + // advance the buffer by the header, leaving only the raw data. + packet.advance(6); + match IdmTransportPacket::decode(packet) { + Ok(packet) => { + let _ = + client_or_create(domid, &self.tx_sender, &self.clients, &self.feeds) + .await?; + let guard = self.feeds.lock().await; + if let Some(feed) = guard.get(&domid) { + let _ = feed.try_send(packet.clone()); + } + let _ = self.snoop_sender.send(DaemonIdmSnoopPacket { + from: domid, + to: 0, + packet, + }); + } + + Err(packet) => { + warn!("received invalid packet from domain {}: {}", domid, packet); + } + } + } + } else { + let mut clients = self.clients.lock().await; + let mut feeds = self.feeds.lock().await; + clients.remove(&domid); + feeds.remove(&domid); + } + Ok(()) + } + + async fn tx_packet(&mut self, domid: u32, packet: IdmTransportPacket) -> Result<()> { + let data = packet.encode_to_vec(); + let mut buffer = vec![0u8; 6]; + let length = data.len() as u32; + // magic bytes + buffer[0] = 0xff; + buffer[1] = 0xff; + // little endian u32 for message size + buffer[2] = length as u8; + buffer[3] = (length << 8) as u8; + buffer[4] = (length << 16) as u8; + buffer[5] = (length << 24) as u8; + buffer.extend_from_slice(&data); + self.tx_raw_sender.send((domid, buffer)).await?; + let _ = self.snoop_sender.send(DaemonIdmSnoopPacket { + from: 0, + to: domid, + packet, + }); + Ok(()) + } + async fn process(&mut self, buffers: &mut HashMap) -> Result<()> { loop { select! { x = self.rx_receiver.recv() => match x { Some((domid, data)) => { - if let Some(data) = data { - let buffer = buffers.entry(domid).or_insert_with_key(|_| BytesMut::new()); - buffer.extend_from_slice(&data); - loop { - if buffer.len() < 6 { - break; - } - - if buffer[0] != 0xff || buffer[1] != 0xff { - buffer.clear(); - break; - } - - let size = (buffer[2] as u32 | (buffer[3] as u32) << 8 | (buffer[4] as u32) << 16 | (buffer[5] as u32) << 24) as usize; - let needed = size + 6; - if buffer.len() < needed { - break; - } - let mut packet = buffer.split_to(needed); - packet.advance(6); - match IdmTransportPacket::decode(packet) { - Ok(packet) => { - let _ = client_or_create(domid, &self.tx_sender, &self.clients, &self.feeds).await?; - let guard = self.feeds.lock().await; - if let Some(feed) = guard.get(&domid) { - let _ = feed.try_send(packet.clone()); - } - let _ = self.snoop_sender.send(DaemonIdmSnoopPacket { from: domid, to: 0, packet }); - } - - Err(packet) => { - warn!("received invalid packet from domain {}: {}", domid, packet); - } - } - } - } else { - let mut clients = self.clients.lock().await; - let mut feeds = self.feeds.lock().await; - clients.remove(&domid); - feeds.remove(&domid); - } + self.process_rx_packet(domid, data, buffers).await?; }, None => { @@ -187,25 +234,14 @@ impl DaemonIdm { }, x = self.tx_receiver.recv() => match x { Some((domid, packet)) => { - let data = packet.encode_to_vec(); - let mut buffer = vec![0u8; 6]; - let length = data.len() as u32; - buffer[0] = 0xff; - buffer[1] = 0xff; - buffer[2] = length as u8; - buffer[3] = (length << 8) as u8; - buffer[4] = (length << 16) as u8; - buffer[5] = (length << 24) as u8; - buffer.extend_from_slice(&data); - self.tx_raw_sender.send((domid, buffer)).await?; - let _ = self.snoop_sender.send(DaemonIdmSnoopPacket { from: 0, to: domid, packet }); + self.tx_packet(domid, packet).await?; }, None => { break; } } - }; + } } Ok(()) } diff --git a/crates/daemon/src/ip/assignment.rs b/crates/daemon/src/ip/assignment.rs new file mode 100644 index 0000000..ded5524 --- /dev/null +++ b/crates/daemon/src/ip/assignment.rs @@ -0,0 +1,179 @@ +use advmac::MacAddr6; +use anyhow::{anyhow, Result}; +use ipnetwork::{Ipv4Network, Ipv6Network}; +use std::{ + collections::HashMap, + net::{Ipv4Addr, Ipv6Addr}, + sync::Arc, +}; +use tokio::sync::RwLock; +use uuid::Uuid; + +use crate::db::ip::{IpReservation, IpReservationStore}; + +#[derive(Default, Clone)] +pub struct IpAssignmentState { + pub ipv4: HashMap, + pub ipv6: HashMap, +} + +#[derive(Clone)] +pub struct IpAssignment { + ipv4_network: Ipv4Network, + ipv6_network: Ipv6Network, + gateway_ipv4: Ipv4Addr, + gateway_ipv6: Ipv6Addr, + gateway_mac: MacAddr6, + store: IpReservationStore, + state: Arc>, +} + +impl IpAssignment { + pub async fn new( + host_uuid: Uuid, + ipv4_network: Ipv4Network, + ipv6_network: Ipv6Network, + store: IpReservationStore, + ) -> Result { + let mut state = IpAssignment::fetch_current_state(&store).await?; + let reservation = if let Some(reservation) = store.read(host_uuid).await? { + reservation + } else { + IpAssignment::allocate( + &mut state, + &store, + host_uuid, + ipv4_network, + ipv6_network, + None, + None, + None, + ) + .await? + }; + let assignment = IpAssignment { + ipv4_network, + ipv6_network, + gateway_ipv4: reservation.ipv4, + gateway_ipv6: reservation.ipv6, + gateway_mac: reservation.gateway_mac, + store, + state: Arc::new(RwLock::new(state)), + }; + Ok(assignment) + } + + async fn fetch_current_state(store: &IpReservationStore) -> Result { + let reservations = store.list().await?; + let mut state = IpAssignmentState::default(); + for reservation in reservations.values() { + state.ipv4.insert(reservation.ipv4, reservation.clone()); + state.ipv6.insert(reservation.ipv6, reservation.clone()); + } + Ok(state) + } + + #[allow(clippy::too_many_arguments)] + async fn allocate( + state: &mut IpAssignmentState, + store: &IpReservationStore, + uuid: Uuid, + ipv4_network: Ipv4Network, + ipv6_network: Ipv6Network, + gateway_ipv4: Option, + gateway_ipv6: Option, + gateway_mac: Option, + ) -> Result { + let found_ipv4: Option = ipv4_network + .iter() + .filter(|ip| { + ip.is_private() && !(ip.is_loopback() || ip.is_multicast() || ip.is_broadcast()) + }) + .filter(|ip| { + let last = ip.octets()[3]; + // filter for IPs ending in .1 to .250 because .250+ can have special meaning + last > 0 && last < 250 + }) + .find(|ip| !state.ipv4.contains_key(ip)); + + let found_ipv6: Option = ipv6_network + .iter() + .filter(|ip| !ip.is_loopback() && !ip.is_multicast()) + .find(|ip| !state.ipv6.contains_key(ip)); + + let Some(ipv4) = found_ipv4 else { + return Err(anyhow!( + "unable to allocate ipv4 address, assigned network is exhausted" + )); + }; + + let Some(ipv6) = found_ipv6 else { + return Err(anyhow!( + "unable to allocate ipv6 address, assigned network is exhausted" + )); + }; + + let mut mac = MacAddr6::random(); + mac.set_local(false); + mac.set_multicast(false); + + let reservation = IpReservation { + uuid: uuid.to_string(), + ipv4, + ipv6, + mac, + ipv4_prefix: ipv4_network.prefix(), + ipv6_prefix: ipv6_network.prefix(), + gateway_ipv4: gateway_ipv4.unwrap_or(ipv4), + gateway_ipv6: gateway_ipv6.unwrap_or(ipv6), + gateway_mac: gateway_mac.unwrap_or(mac), + }; + state.ipv4.insert(ipv4, reservation.clone()); + state.ipv6.insert(ipv6, reservation.clone()); + store.update(uuid, reservation.clone()).await?; + Ok(reservation) + } + + pub async fn assign(&self, uuid: Uuid) -> Result { + let mut state = self.state.write().await; + let reservation = IpAssignment::allocate( + &mut state, + &self.store, + uuid, + self.ipv4_network, + self.ipv6_network, + Some(self.gateway_ipv4), + Some(self.gateway_ipv6), + Some(self.gateway_mac), + ) + .await?; + Ok(reservation) + } + + pub async fn recall(&self, uuid: Uuid) -> Result<()> { + let mut state = self.state.write().await; + self.store.remove(uuid).await?; + state + .ipv4 + .retain(|_, reservation| reservation.uuid != uuid.to_string()); + state + .ipv6 + .retain(|_, reservation| reservation.uuid != uuid.to_string()); + Ok(()) + } + + pub async fn retrieve(&self, uuid: Uuid) -> Result> { + self.store.read(uuid).await + } + + pub async fn reload(&self) -> Result<()> { + let mut state = self.state.write().await; + let intermediate = IpAssignment::fetch_current_state(&self.store).await?; + *state = intermediate; + Ok(()) + } + + pub async fn read(&self) -> Result { + Ok(self.state.read().await.clone()) + } +} diff --git a/crates/daemon/src/ip/mod.rs b/crates/daemon/src/ip/mod.rs new file mode 100644 index 0000000..53a13b4 --- /dev/null +++ b/crates/daemon/src/ip/mod.rs @@ -0,0 +1 @@ +pub mod assignment; diff --git a/crates/daemon/src/lib.rs b/crates/daemon/src/lib.rs index 9da5b6a..816682d 100644 --- a/crates/daemon/src/lib.rs +++ b/crates/daemon/src/lib.rs @@ -1,18 +1,22 @@ -use std::{net::SocketAddr, path::PathBuf, str::FromStr, sync::Arc}; - +use crate::db::ip::IpReservationStore; +use crate::db::zone::ZoneStore; +use crate::db::KrataDatabase; +use crate::ip::assignment::IpAssignment; use anyhow::{anyhow, Result}; use config::DaemonConfig; use console::{DaemonConsole, DaemonConsoleHandle}; use control::DaemonControlService; -use db::ZoneStore; use devices::DaemonDeviceManager; use event::{DaemonEventContext, DaemonEventGenerator}; use idm::{DaemonIdm, DaemonIdmHandle}; +use ipnetwork::{Ipv4Network, Ipv6Network}; use krata::{dial::ControlDialAddress, v1::control::control_service_server::ControlServiceServer}; use krataoci::{packer::service::OciPackerService, registry::OciPlatform}; use kratart::Runtime; use log::{debug, info}; use reconcile::zone::ZoneReconciler; +use std::path::Path; +use std::{net::SocketAddr, path::PathBuf, str::FromStr, sync::Arc}; use tokio::{ fs, net::UnixListener, @@ -32,6 +36,7 @@ pub mod db; pub mod devices; pub mod event; pub mod idm; +pub mod ip; pub mod metrics; pub mod oci; pub mod reconcile; @@ -101,31 +106,33 @@ impl Daemon { debug!("initializing caches and hydrating zone state"); let seed = config.oci.seed.clone().map(PathBuf::from); let packer = OciPackerService::new(seed, &image_cache_dir, OciPlatform::current()).await?; - let glt = ZoneLookupTable::new(0, host_uuid); - let zones_db_path = format!("{}/zones.db", store); - let zones = ZoneStore::open(&PathBuf::from(zones_db_path))?; + debug!("initializing core runtime"); + let runtime = Runtime::new().await?; + let zlt = ZoneLookupTable::new(0, host_uuid); + let db_path = format!("{}/krata.db", store); + let database = KrataDatabase::open(Path::new(&db_path))?; + let zones = ZoneStore::open(database.clone())?; let (zone_reconciler_notify, zone_reconciler_receiver) = channel::(ZONE_RECONCILER_QUEUE_LEN); - - debug!("initializing core runtime"); - let runtime = Runtime::new(host_uuid).await?; - debug!("starting IDM service"); - let idm = DaemonIdm::new(glt.clone()).await?; + let idm = DaemonIdm::new(zlt.clone()).await?; let idm = idm.launch().await?; - debug!("initializing console interfaces"); - let console = DaemonConsole::new(glt.clone()).await?; + let console = DaemonConsole::new(zlt.clone()).await?; let console = console.launch().await?; - - debug!("initializing zone reconciler"); let (events, generator) = DaemonEventGenerator::new(zones.clone(), zone_reconciler_notify.clone(), idm.clone()) .await?; let runtime_for_reconciler = runtime.dupe().await?; + let ipv4_network = Ipv4Network::from_str(&config.network.ipv4.subnet)?; + let ipv6_network = Ipv6Network::from_str(&config.network.ipv6.subnet)?; + let ip_reservation_store = IpReservationStore::open(database)?; + let ip_assignment = + IpAssignment::new(host_uuid, ipv4_network, ipv6_network, ip_reservation_store).await?; + debug!("initializing zone reconciler"); let zone_reconciler = ZoneReconciler::new( devices.clone(), - glt.clone(), + zlt.clone(), zones.clone(), events.clone(), runtime_for_reconciler, @@ -134,6 +141,8 @@ impl Daemon { kernel_path, initrd_path, addons_path, + ip_assignment, + config.clone(), )?; let zone_reconciler_task = zone_reconciler.launch(zone_reconciler_receiver).await?; @@ -152,7 +161,7 @@ impl Daemon { Ok(Self { store, _config: config, - glt, + glt: zlt, devices, zones, events, @@ -167,7 +176,7 @@ impl Daemon { } pub async fn listen(&mut self, addr: ControlDialAddress) -> Result<()> { - debug!("starting API service"); + debug!("starting control service"); let control_service = DaemonControlService::new( self.glt.clone(), self.devices.clone(), diff --git a/crates/daemon/src/reconcile/zone/start.rs b/crates/daemon/src/reconcile/zone/create.rs similarity index 81% rename from crates/daemon/src/reconcile/zone/start.rs rename to crates/daemon/src/reconcile/zone/create.rs index e1bdcf2..774149c 100644 --- a/crates/daemon/src/reconcile/zone/start.rs +++ b/crates/daemon/src/reconcile/zone/create.rs @@ -1,41 +1,41 @@ -use std::collections::HashMap; -use std::path::{Path, PathBuf}; -use std::str::FromStr; -use std::sync::atomic::{AtomicBool, Ordering}; - use anyhow::{anyhow, Result}; use futures::StreamExt; use krata::launchcfg::LaunchPackedFormat; use krata::v1::common::ZoneOciImageSpec; use krata::v1::common::{OciImageFormat, Zone, ZoneState, ZoneStatus}; use krataoci::packer::{service::OciPackerService, OciPackedFormat}; -use kratart::launch::{PciBdf, PciDevice, PciRdmReservePolicy}; +use kratart::launch::{PciBdf, PciDevice, PciRdmReservePolicy, ZoneLaunchNetwork}; use kratart::{launch::ZoneLaunchRequest, Runtime}; use log::info; +use std::collections::HashMap; +use std::path::{Path, PathBuf}; +use std::str::FromStr; +use std::sync::atomic::{AtomicBool, Ordering}; -use crate::config::DaemonPciDeviceRdmReservePolicy; +use crate::config::{DaemonConfig, DaemonPciDeviceRdmReservePolicy}; use crate::devices::DaemonDeviceManager; -use crate::{ - reconcile::zone::{zoneinfo_to_networkstate, ZoneReconcilerResult}, - zlt::ZoneLookupTable, -}; +use crate::ip::assignment::IpAssignment; +use crate::reconcile::zone::ip_reservation_to_network_status; +use crate::{reconcile::zone::ZoneReconcilerResult, zlt::ZoneLookupTable}; use krata::v1::common::zone_image_spec::Image; use tokio::fs::{self, File}; use tokio::io::AsyncReadExt; use tokio_tar::Archive; use uuid::Uuid; -pub struct ZoneStarter<'a> { +pub struct ZoneCreator<'a> { pub devices: &'a DaemonDeviceManager, pub kernel_path: &'a Path, pub initrd_path: &'a Path, pub addons_path: &'a Path, pub packer: &'a OciPackerService, - pub glt: &'a ZoneLookupTable, + pub ip_assignment: &'a IpAssignment, + pub zlt: &'a ZoneLookupTable, pub runtime: &'a Runtime, + pub config: &'a DaemonConfig, } -impl ZoneStarter<'_> { +impl ZoneCreator<'_> { pub async fn oci_spec_tar_read_file( &self, file: &Path, @@ -75,7 +75,7 @@ impl ZoneStarter<'_> { )) } - pub async fn start(&self, uuid: Uuid, zone: &mut Zone) -> Result { + pub async fn create(&self, uuid: Uuid, zone: &mut Zone) -> Result { let Some(ref spec) = zone.spec else { return Err(anyhow!("zone spec not specified")); }; @@ -174,6 +174,8 @@ impl ZoneStarter<'_> { } } + let reservation = self.ip_assignment.assign(uuid).await?; + let info = self .runtime .launch(ZoneLaunchRequest { @@ -187,7 +189,7 @@ impl ZoneStarter<'_> { image, kernel, initrd, - vcpus: spec.vcpus, + vcpus: spec.cpus, mem: spec.mem, pcis, env: task @@ -198,16 +200,26 @@ impl ZoneStarter<'_> { run: empty_vec_optional(task.command.clone()), debug: false, addons_image: Some(self.addons_path.to_path_buf()), + network: ZoneLaunchNetwork { + ipv4: reservation.ipv4.to_string(), + ipv4_prefix: reservation.ipv4_prefix, + ipv6: reservation.ipv6.to_string(), + ipv6_prefix: reservation.ipv6_prefix, + gateway_ipv4: reservation.gateway_ipv4.to_string(), + gateway_ipv6: reservation.gateway_ipv6.to_string(), + zone_mac: reservation.mac, + nameservers: self.config.network.nameservers.clone(), + }, }) .await?; - self.glt.associate(uuid, info.domid).await; - info!("started zone {}", uuid); - zone.state = Some(ZoneState { - status: ZoneStatus::Started.into(), - network: Some(zoneinfo_to_networkstate(&info)), - exit_info: None, - error_info: None, - host: self.glt.host_uuid().to_string(), + self.zlt.associate(uuid, info.domid).await; + info!("created zone {}", uuid); + zone.status = Some(ZoneStatus { + state: ZoneState::Created.into(), + network_status: Some(ip_reservation_to_network_status(&reservation)), + exit_status: None, + error_status: None, + host: self.zlt.host_uuid().to_string(), domid: info.domid, }); success.store(true, Ordering::Release); diff --git a/crates/daemon/src/reconcile/zone/mod.rs b/crates/daemon/src/reconcile/zone/mod.rs index 1be6f46..e5b4e9f 100644 --- a/crates/daemon/src/reconcile/zone/mod.rs +++ b/crates/daemon/src/reconcile/zone/mod.rs @@ -5,13 +5,23 @@ use std::{ time::Duration, }; +use self::create::ZoneCreator; +use crate::config::DaemonConfig; +use crate::db::ip::IpReservation; +use crate::ip::assignment::IpAssignment; +use crate::{ + db::zone::ZoneStore, + devices::DaemonDeviceManager, + event::{DaemonEvent, DaemonEventContext}, + zlt::ZoneLookupTable, +}; use anyhow::Result; use krata::v1::{ - common::{Zone, ZoneErrorInfo, ZoneExitInfo, ZoneNetworkState, ZoneState, ZoneStatus}, + common::{Zone, ZoneErrorStatus, ZoneExitStatus, ZoneNetworkStatus, ZoneState, ZoneStatus}, control::ZoneChangedEvent, }; use krataoci::packer::service::OciPackerService; -use kratart::{Runtime, ZoneInfo}; +use kratart::Runtime; use log::{error, info, trace, warn}; use tokio::{ select, @@ -24,16 +34,7 @@ use tokio::{ }; use uuid::Uuid; -use crate::{ - db::ZoneStore, - devices::DaemonDeviceManager, - event::{DaemonEvent, DaemonEventContext}, - zlt::ZoneLookupTable, -}; - -use self::start::ZoneStarter; - -mod start; +mod create; const PARALLEL_LIMIT: u32 = 5; @@ -68,6 +69,8 @@ pub struct ZoneReconciler { tasks: Arc>>, zone_reconciler_notify: Sender, zone_reconcile_lock: Arc>, + ip_assignment: IpAssignment, + config: Arc, } impl ZoneReconciler { @@ -83,6 +86,8 @@ impl ZoneReconciler { kernel_path: PathBuf, initrd_path: PathBuf, modules_path: PathBuf, + ip_assignment: IpAssignment, + config: Arc, ) -> Result { Ok(Self { devices, @@ -97,6 +102,8 @@ impl ZoneReconciler { tasks: Arc::new(Mutex::new(HashMap::new())), zone_reconciler_notify, zone_reconcile_lock: Arc::new(RwLock::with_max_readers((), PARALLEL_LIMIT)), + ip_assignment, + config, }) } @@ -132,7 +139,7 @@ impl ZoneReconciler { error!("runtime reconciler failed: {}", error); } } - }; + } } })) } @@ -166,21 +173,21 @@ impl ZoneReconciler { let runtime_zone = runtime_zones.iter().find(|x| x.uuid == uuid); match runtime_zone { None => { - let mut state = stored_zone.state.as_mut().cloned().unwrap_or_default(); - if state.status() == ZoneStatus::Started { - state.status = ZoneStatus::Starting.into(); + let mut status = stored_zone.status.as_mut().cloned().unwrap_or_default(); + if status.state() == ZoneState::Created { + status.state = ZoneState::Creating.into(); } - stored_zone.state = Some(state); + stored_zone.status = Some(status); } Some(runtime) => { self.zlt.associate(uuid, runtime.domid).await; - let mut state = stored_zone.state.as_mut().cloned().unwrap_or_default(); + let mut status = stored_zone.status.as_mut().cloned().unwrap_or_default(); if let Some(code) = runtime.state.exit_code { - state.status = ZoneStatus::Exited.into(); - state.exit_info = Some(ZoneExitInfo { code }); + status.state = ZoneState::Exited.into(); + status.exit_status = Some(ZoneExitStatus { code }); } else { - state.status = ZoneStatus::Started.into(); + status.state = ZoneState::Created.into(); } for device in &stored_zone @@ -193,8 +200,11 @@ impl ZoneReconciler { device_claims.insert(device.name.clone(), uuid); } - state.network = Some(zoneinfo_to_networkstate(runtime)); - stored_zone.state = Some(state); + if let Some(reservation) = self.ip_assignment.retrieve(uuid).await? { + status.network_status = + Some(ip_reservation_to_network_status(&reservation)); + } + stored_zone.status = Some(status); } } @@ -228,20 +238,20 @@ impl ZoneReconciler { zone: Some(zone.clone()), }))?; - let start_status = zone.state.as_ref().map(|x| x.status()).unwrap_or_default(); - let result = match start_status { - ZoneStatus::Starting => self.start(uuid, &mut zone).await, - ZoneStatus::Exited => self.exited(&mut zone).await, - ZoneStatus::Destroying => self.destroy(uuid, &mut zone).await, + let start_state = zone.status.as_ref().map(|x| x.state()).unwrap_or_default(); + let result = match start_state { + ZoneState::Creating => self.create(uuid, &mut zone).await, + ZoneState::Exited => self.exited(&mut zone).await, + ZoneState::Destroying => self.destroy(uuid, &mut zone).await, _ => Ok(ZoneReconcilerResult::Unchanged), }; let result = match result { Ok(result) => result, Err(error) => { - zone.state = Some(zone.state.as_mut().cloned().unwrap_or_default()); - zone.state.as_mut().unwrap().status = ZoneStatus::Failed.into(); - zone.state.as_mut().unwrap().error_info = Some(ZoneErrorInfo { + zone.status = Some(zone.status.as_mut().cloned().unwrap_or_default()); + zone.status.as_mut().unwrap().state = ZoneState::Failed.into(); + zone.status.as_mut().unwrap().error_status = Some(ZoneErrorStatus { message: error.to_string(), }); warn!("failed to start zone {}: {}", zone.id, error); @@ -251,8 +261,8 @@ impl ZoneReconciler { info!("reconciled zone {}", uuid); - let status = zone.state.as_ref().map(|x| x.status()).unwrap_or_default(); - let destroyed = status == ZoneStatus::Destroyed; + let state = zone.status.as_ref().map(|x| x.state()).unwrap_or_default(); + let destroyed = state == ZoneState::Destroyed; let rerun = if let ZoneReconcilerResult::Changed { rerun } = result { let event = DaemonEvent::ZoneChanged(ZoneChangedEvent { @@ -276,22 +286,24 @@ impl ZoneReconciler { Ok(rerun) } - async fn start(&self, uuid: Uuid, zone: &mut Zone) -> Result { - let starter = ZoneStarter { + async fn create(&self, uuid: Uuid, zone: &mut Zone) -> Result { + let starter = ZoneCreator { devices: &self.devices, kernel_path: &self.kernel_path, initrd_path: &self.initrd_path, addons_path: &self.addons_path, packer: &self.packer, - glt: &self.zlt, + ip_assignment: &self.ip_assignment, + zlt: &self.zlt, runtime: &self.runtime, + config: &self.config, }; - starter.start(uuid, zone).await + starter.create(uuid, zone).await } async fn exited(&self, zone: &mut Zone) -> Result { - if let Some(ref mut state) = zone.state { - state.set_status(ZoneStatus::Destroying); + if let Some(ref mut status) = zone.status { + status.set_state(ZoneState::Destroying); Ok(ZoneReconcilerResult::Changed { rerun: true }) } else { Ok(ZoneReconcilerResult::Unchanged) @@ -303,18 +315,19 @@ impl ZoneReconciler { trace!("failed to destroy runtime zone {}: {}", uuid, error); } - let domid = zone.state.as_ref().map(|x| x.domid); + let domid = zone.status.as_ref().map(|x| x.domid); if let Some(domid) = domid { self.zlt.remove(uuid, domid).await; } info!("destroyed zone {}", uuid); - zone.state = Some(ZoneState { - status: ZoneStatus::Destroyed.into(), - network: None, - exit_info: None, - error_info: None, + self.ip_assignment.recall(uuid).await?; + zone.status = Some(ZoneStatus { + state: ZoneState::Destroyed.into(), + network_status: None, + exit_status: None, + error_status: None, host: self.zlt.host_uuid().to_string(), domid: domid.unwrap_or(u32::MAX), }); @@ -362,13 +375,13 @@ impl ZoneReconciler { } } -pub fn zoneinfo_to_networkstate(info: &ZoneInfo) -> ZoneNetworkState { - ZoneNetworkState { - zone_ipv4: info.zone_ipv4.map(|x| x.to_string()).unwrap_or_default(), - zone_ipv6: info.zone_ipv6.map(|x| x.to_string()).unwrap_or_default(), - zone_mac: info.zone_mac.as_ref().cloned().unwrap_or_default(), - gateway_ipv4: info.gateway_ipv4.map(|x| x.to_string()).unwrap_or_default(), - gateway_ipv6: info.gateway_ipv6.map(|x| x.to_string()).unwrap_or_default(), - gateway_mac: info.gateway_mac.as_ref().cloned().unwrap_or_default(), +pub fn ip_reservation_to_network_status(ip: &IpReservation) -> ZoneNetworkStatus { + ZoneNetworkStatus { + zone_ipv4: format!("{}/{}", ip.ipv4, ip.ipv4_prefix), + zone_ipv6: format!("{}/{}", ip.ipv6, ip.ipv6_prefix), + zone_mac: ip.mac.to_string().replace('-', ":"), + gateway_ipv4: format!("{}/{}", ip.gateway_ipv4, ip.ipv4_prefix), + gateway_ipv6: format!("{}/{}", ip.gateway_ipv6, ip.ipv6_prefix), + gateway_mac: ip.gateway_mac.to_string().replace('-', ":"), } } diff --git a/crates/krata/proto/krata/v1/common.proto b/crates/krata/proto/krata/v1/common.proto index a8b18d1..e60c9e5 100644 --- a/crates/krata/proto/krata/v1/common.proto +++ b/crates/krata/proto/krata/v1/common.proto @@ -11,7 +11,7 @@ import "google/protobuf/struct.proto"; message Zone { string id = 1; ZoneSpec spec = 2; - ZoneState state = 3; + ZoneStatus status = 3; } message ZoneSpec { @@ -21,7 +21,7 @@ message ZoneSpec { ZoneImageSpec kernel = 3; // If not specified, defaults to the daemon default initrd. ZoneImageSpec initrd = 4; - uint32 vcpus = 5; + uint32 cpus = 5; uint64 mem = 6; ZoneTaskSpec task = 7; repeated ZoneSpecAnnotation annotations = 8; @@ -67,26 +67,26 @@ message ZoneSpecDevice { string name = 1; } -message ZoneState { - ZoneStatus status = 1; - ZoneNetworkState network = 2; - ZoneExitInfo exit_info = 3; - ZoneErrorInfo error_info = 4; +message ZoneStatus { + ZoneState state = 1; + ZoneNetworkStatus network_status = 2; + ZoneExitStatus exit_status = 3; + ZoneErrorStatus error_status = 4; string host = 5; uint32 domid = 6; } -enum ZoneStatus { - ZONE_STATUS_UNKNOWN = 0; - ZONE_STATUS_STARTING = 1; - ZONE_STATUS_STARTED = 2; - ZONE_STATUS_EXITED = 3; - ZONE_STATUS_DESTROYING = 4; - ZONE_STATUS_DESTROYED = 5; - ZONE_STATUS_FAILED = 6; +enum ZoneState { + ZONE_STATE_UNKNOWN = 0; + ZONE_STATE_CREATING = 1; + ZONE_STATE_CREATED = 2; + ZONE_STATE_EXITED = 3; + ZONE_STATE_DESTROYING = 4; + ZONE_STATE_DESTROYED = 5; + ZONE_STATE_FAILED = 6; } -message ZoneNetworkState { +message ZoneNetworkStatus { string zone_ipv4 = 1; string zone_ipv6 = 2; string zone_mac = 3; @@ -95,11 +95,11 @@ message ZoneNetworkState { string gateway_mac = 6; } -message ZoneExitInfo { +message ZoneExitStatus { int32 code = 1; } -message ZoneErrorInfo { +message ZoneErrorStatus { string message = 1; } diff --git a/crates/krata/proto/krata/v1/control.proto b/crates/krata/proto/krata/v1/control.proto index e9f9be1..6f73d90 100644 --- a/crates/krata/proto/krata/v1/control.proto +++ b/crates/krata/proto/krata/v1/control.proto @@ -10,31 +10,34 @@ import "krata/idm/transport.proto"; import "krata/v1/common.proto"; service ControlService { - rpc IdentifyHost(IdentifyHostRequest) returns (IdentifyHostReply); - - rpc CreateZone(CreateZoneRequest) returns (CreateZoneReply); - rpc DestroyZone(DestroyZoneRequest) returns (DestroyZoneReply); - rpc ResolveZone(ResolveZoneRequest) returns (ResolveZoneReply); - rpc ListZones(ListZonesRequest) returns (ListZonesReply); - rpc ListDevices(ListDevicesRequest) returns (ListDevicesReply); - - rpc ExecZone(stream ExecZoneRequest) returns (stream ExecZoneReply); - - rpc AttachZoneConsole(stream ZoneConsoleRequest) returns (stream ZoneConsoleReply); - rpc ReadZoneMetrics(ReadZoneMetricsRequest) returns (ReadZoneMetricsReply); - + rpc HostStatus(HostStatusRequest) returns (HostStatusReply); rpc SnoopIdm(SnoopIdmRequest) returns (stream SnoopIdmReply); - rpc WatchEvents(WatchEventsRequest) returns (stream WatchEventsReply); + rpc GetHostCpuTopology(GetHostCpuTopologyRequest) returns (GetHostCpuTopologyReply); + rpc SetHostPowerManagementPolicy(SetHostPowerManagementPolicyRequest) returns (SetHostPowerManagementPolicyReply); + + rpc ListDevices(ListDevicesRequest) returns (ListDevicesReply); rpc PullImage(PullImageRequest) returns (stream PullImageReply); - rpc GetHostCpuTopology(HostCpuTopologyRequest) returns (HostCpuTopologyReply); - rpc SetHostPowerManagementPolicy(HostPowerManagementPolicy) returns (HostPowerManagementPolicy); + rpc CreateZone(CreateZoneRequest) returns (CreateZoneReply); + rpc DestroyZone(DestroyZoneRequest) returns (DestroyZoneReply); + + rpc ResolveZoneId(ResolveZoneIdRequest) returns (ResolveZoneIdReply); + + rpc GetZone(GetZoneRequest) returns (GetZoneReply); + + rpc ListZones(ListZonesRequest) returns (ListZonesReply); + + rpc AttachZoneConsole(stream ZoneConsoleRequest) returns (stream ZoneConsoleReply); + rpc ExecInsideZone(stream ExecInsideZoneRequest) returns (stream ExecInsideZoneReply); + rpc ReadZoneMetrics(ReadZoneMetricsRequest) returns (ReadZoneMetricsReply); + + rpc WatchEvents(WatchEventsRequest) returns (stream WatchEventsReply); } -message IdentifyHostRequest {} +message HostStatusRequest {} -message IdentifyHostReply { +message HostStatusReply { string host_uuid = 1; uint32 host_domid = 2; string krata_version = 3; @@ -45,36 +48,44 @@ message CreateZoneRequest { } message CreateZoneReply { - string Zone_id = 1; + string zone_id = 1; } message DestroyZoneRequest { - string Zone_id = 1; + string zone_id = 1; } message DestroyZoneReply {} -message ResolveZoneRequest { +message ResolveZoneIdRequest { string name = 1; } -message ResolveZoneReply { - krata.v1.common.Zone Zone = 1; +message ResolveZoneIdReply { + string zone_id = 1; +} + +message GetZoneRequest { + string zone_id = 1; +} + +message GetZoneReply { + krata.v1.common.Zone zone = 1; } message ListZonesRequest {} message ListZonesReply { - repeated krata.v1.common.Zone Zones = 1; + repeated krata.v1.common.Zone zones = 1; } -message ExecZoneRequest { - string Zone_id = 1; +message ExecInsideZoneRequest { + string zone_id = 1; krata.v1.common.ZoneTaskSpec task = 2; bytes data = 3; } -message ExecZoneReply { +message ExecInsideZoneReply { bool exited = 1; string error = 2; int32 exit_code = 3; @@ -83,7 +94,7 @@ message ExecZoneReply { } message ZoneConsoleRequest { - string Zone_id = 1; + string zone_id = 1; bytes data = 2; } @@ -95,16 +106,16 @@ message WatchEventsRequest {} message WatchEventsReply { oneof event { - ZoneChangedEvent Zone_changed = 1; + ZoneChangedEvent zone_changed = 1; } } message ZoneChangedEvent { - krata.v1.common.Zone Zone = 1; + krata.v1.common.Zone zone = 1; } message ReadZoneMetricsRequest { - string Zone_id = 1; + string zone_id = 1; } message ReadZoneMetricsReply { @@ -219,15 +230,15 @@ message HostCpuTopologyInfo { HostCpuTopologyClass class = 5; } -message HostCpuTopologyRequest {} +message GetHostCpuTopologyRequest {} -message HostCpuTopologyReply { +message GetHostCpuTopologyReply { repeated HostCpuTopologyInfo cpus = 1; } -message HostPowerManagementPolicyRequest {} - -message HostPowerManagementPolicy { +message SetHostPowerManagementPolicyRequest { string scheduler = 1; bool smt_awareness = 2; } + +message SetHostPowerManagementPolicyReply {} diff --git a/crates/krata/src/idm/client.rs b/crates/krata/src/idm/client.rs index 8e240f4..0fc7606 100644 --- a/crates/krata/src/idm/client.rs +++ b/crates/krata/src/idm/client.rs @@ -34,7 +34,7 @@ use super::{ type OneshotRequestMap = Arc::Response>>>>; type StreamRequestMap = Arc::Response>>>>; -type StreamRequestUpdateMap = Arc>>>; +type StreamRequestUpdateMap = Arc>>>; pub type IdmInternalClient = IdmClient; const IDM_PACKET_QUEUE_LEN: usize = 100; diff --git a/crates/network/src/autonet.rs b/crates/network/src/autonet.rs index 6a5477a..69fafa0 100644 --- a/crates/network/src/autonet.rs +++ b/crates/network/src/autonet.rs @@ -76,44 +76,44 @@ impl AutoNetworkWatcher { let mut networks: Vec = Vec::new(); for (uuid, zone) in &all_zones { - let Some(ref state) = zone.state else { + let Some(ref status) = zone.status else { continue; }; - if state.domid == u32::MAX { + if status.domid == u32::MAX { continue; } - let Some(ref network) = state.network else { + let Some(ref network_status) = status.network_status else { continue; }; - let Ok(zone_ipv4_cidr) = Ipv4Cidr::from_str(&network.zone_ipv4) else { + let Ok(zone_ipv4_cidr) = Ipv4Cidr::from_str(&network_status.zone_ipv4) else { continue; }; - let Ok(zone_ipv6_cidr) = Ipv6Cidr::from_str(&network.zone_ipv6) else { + let Ok(zone_ipv6_cidr) = Ipv6Cidr::from_str(&network_status.zone_ipv6) else { continue; }; - let Ok(zone_mac) = EthernetAddress::from_str(&network.zone_mac) else { + let Ok(zone_mac) = EthernetAddress::from_str(&network_status.zone_mac) else { continue; }; - let Ok(gateway_ipv4_cidr) = Ipv4Cidr::from_str(&network.gateway_ipv4) else { + let Ok(gateway_ipv4_cidr) = Ipv4Cidr::from_str(&network_status.gateway_ipv4) else { continue; }; - let Ok(gateway_ipv6_cidr) = Ipv6Cidr::from_str(&network.gateway_ipv6) else { + let Ok(gateway_ipv6_cidr) = Ipv6Cidr::from_str(&network_status.gateway_ipv6) else { continue; }; - let Ok(gateway_mac) = EthernetAddress::from_str(&network.gateway_mac) else { + let Ok(gateway_mac) = EthernetAddress::from_str(&network_status.gateway_mac) else { continue; }; networks.push(NetworkMetadata { - domid: state.domid, + domid: status.domid, uuid: *uuid, zone: NetworkSide { ipv4: zone_ipv4_cidr, @@ -187,7 +187,7 @@ impl AutoNetworkWatcher { _ = sleep(Duration::from_secs(10)) => { break; } - }; + } } Ok(()) } diff --git a/crates/oci/examples/squashify.rs b/crates/oci/examples/squashify.rs index e1023fd..c1d24d7 100644 --- a/crates/oci/examples/squashify.rs +++ b/crates/oci/examples/squashify.rs @@ -25,7 +25,7 @@ async fn main() -> Result<()> { let (context, mut receiver) = OciProgressContext::create(); tokio::task::spawn(async move { loop { - if (receiver.changed().await).is_err() { + if receiver.changed().await.is_err() { break; } let progress = receiver.borrow_and_update(); diff --git a/crates/oci/src/packer/backend.rs b/crates/oci/src/packer/backend.rs index f82982f..63b838b 100644 --- a/crates/oci/src/packer/backend.rs +++ b/crates/oci/src/packer/backend.rs @@ -97,13 +97,13 @@ impl OciPackerBackend for OciPackerMkSquashfs { status = &mut wait => { break status; } - }; + } } else { select! { status = &mut wait => { break status; } - }; + } } }; if let Some(writer) = writer { @@ -172,13 +172,13 @@ impl OciPackerBackend for OciPackerMkfsErofs { status = &mut wait => { break status; } - }; + } } else { select! { status = &mut wait => { break status; } - }; + } } }; if let Some(writer) = writer { diff --git a/crates/oci/src/progress.rs b/crates/oci/src/progress.rs index 68b675a..42b975e 100644 --- a/crates/oci/src/progress.rs +++ b/crates/oci/src/progress.rs @@ -228,7 +228,7 @@ impl OciBoundProgress { context.update(&progress); let mut receiver = self.context.subscribe(); tokio::task::spawn(async move { - while (receiver.changed().await).is_ok() { + while receiver.changed().await.is_ok() { context .sender .send_replace(receiver.borrow_and_update().clone()); diff --git a/crates/runtime/src/channel.rs b/crates/runtime/src/channel.rs index 30e9418..3ecbb2b 100644 --- a/crates/runtime/src/channel.rs +++ b/crates/runtime/src/channel.rs @@ -60,11 +60,11 @@ impl ChannelService { let (input_sender, input_receiver) = channel(GROUPED_CHANNEL_QUEUE_LEN); let (output_sender, output_receiver) = channel(GROUPED_CHANNEL_QUEUE_LEN); - debug!("opening Xen event channel"); + debug!("opening xenevtchn"); let evtchn = EventChannelService::open().await?; - debug!("opening XenStore"); + debug!("opening xenstore"); let store = XsdClient::open().await?; - debug!("opening GrantTab"); + debug!("opening xengnt"); let gnttab = GrantTab::open()?; Ok(( @@ -503,7 +503,7 @@ impl KrataChannelBackendProcessor { break; } } - }; + } } Ok(()) } diff --git a/crates/runtime/src/launch.rs b/crates/runtime/src/launch.rs index d0e7845..c3e14a3 100644 --- a/crates/runtime/src/launch.rs +++ b/crates/runtime/src/launch.rs @@ -1,19 +1,21 @@ use std::collections::HashMap; use std::fs; -use std::net::IpAddr; use std::path::PathBuf; use std::sync::Arc; use advmac::MacAddr6; use anyhow::{anyhow, Result}; -use ipnetwork::IpNetwork; +use tokio::sync::Semaphore; +use uuid::Uuid; + use krata::launchcfg::{ LaunchInfo, LaunchNetwork, LaunchNetworkIpv4, LaunchNetworkIpv6, LaunchNetworkResolver, LaunchPackedFormat, LaunchRoot, }; use krataoci::packer::OciPackedImage; -use tokio::sync::Semaphore; -use uuid::Uuid; +pub use xenclient::{ + pci::PciBdf, DomainPciDevice as PciDevice, DomainPciRdmReservePolicy as PciRdmReservePolicy, +}; use xenclient::{DomainChannel, DomainConfig, DomainDisk, DomainNetworkInterface}; use xenplatform::domain::BaseDomainConfig; @@ -22,10 +24,6 @@ use crate::RuntimeContext; use super::{ZoneInfo, ZoneState}; -pub use xenclient::{ - pci::PciBdf, DomainPciDevice as PciDevice, DomainPciRdmReservePolicy as PciRdmReservePolicy, -}; - pub struct ZoneLaunchRequest { pub format: LaunchPackedFormat, pub kernel: Vec, @@ -40,6 +38,18 @@ pub struct ZoneLaunchRequest { pub debug: bool, pub image: OciPackedImage, pub addons_image: Option, + pub network: ZoneLaunchNetwork, +} + +pub struct ZoneLaunchNetwork { + pub ipv4: String, + pub ipv4_prefix: u8, + pub ipv6: String, + pub ipv6_prefix: u8, + pub gateway_ipv4: String, + pub gateway_ipv6: String, + pub zone_mac: MacAddr6, + pub nameservers: Vec, } pub struct ZoneLauncher { @@ -58,15 +68,7 @@ impl ZoneLauncher { ) -> Result { let uuid = request.uuid.unwrap_or_else(Uuid::new_v4); let xen_name = format!("krata-{uuid}"); - let mut gateway_mac = MacAddr6::random(); - gateway_mac.set_local(true); - gateway_mac.set_multicast(false); - let mut zone_mac = MacAddr6::random(); - zone_mac.set_local(true); - zone_mac.set_multicast(false); - let _launch_permit = self.launch_semaphore.acquire().await?; - let mut ip = context.ipvendor.assign(uuid).await?; let launch_config = LaunchInfo { root: LaunchRoot { format: request.format.clone(), @@ -81,20 +83,15 @@ impl ZoneLauncher { network: Some(LaunchNetwork { link: "eth0".to_string(), ipv4: LaunchNetworkIpv4 { - address: format!("{}/{}", ip.ipv4, ip.ipv4_prefix), - gateway: ip.gateway_ipv4.to_string(), + address: format!("{}/{}", request.network.ipv4, request.network.ipv4_prefix), + gateway: request.network.gateway_ipv4, }, ipv6: LaunchNetworkIpv6 { - address: format!("{}/{}", ip.ipv6, ip.ipv6_prefix), - gateway: ip.gateway_ipv6.to_string(), + address: format!("{}/{}", request.network.ipv6, request.network.ipv6_prefix), + gateway: request.network.gateway_ipv6.to_string(), }, resolver: LaunchNetworkResolver { - nameservers: vec![ - "1.1.1.1".to_string(), - "1.0.0.1".to_string(), - "2606:4700:4700::1111".to_string(), - "2606:4700:4700::1001".to_string(), - ], + nameservers: request.network.nameservers, }, }), env: request.env, @@ -145,8 +142,7 @@ impl ZoneLauncher { } let cmdline = cmdline_options.join(" "); - let zone_mac_string = zone_mac.to_string().replace('-', ":"); - let gateway_mac_string = gateway_mac.to_string().replace('-', ":"); + let zone_mac_string = request.network.zone_mac.to_string().replace('-', ":"); let mut disks = vec![ DomainDisk { @@ -190,30 +186,6 @@ impl ZoneLauncher { let mut extra_keys = vec![ ("krata/uuid".to_string(), uuid.to_string()), ("krata/loops".to_string(), loops.join(",")), - ( - "krata/network/zone/ipv4".to_string(), - format!("{}/{}", ip.ipv4, ip.ipv4_prefix), - ), - ( - "krata/network/zone/ipv6".to_string(), - format!("{}/{}", ip.ipv6, ip.ipv6_prefix), - ), - ( - "krata/network/zone/mac".to_string(), - zone_mac_string.clone(), - ), - ( - "krata/network/gateway/ipv4".to_string(), - format!("{}/{}", ip.gateway_ipv4, ip.ipv4_prefix), - ), - ( - "krata/network/gateway/ipv6".to_string(), - format!("{}/{}", ip.gateway_ipv6, ip.ipv6_prefix), - ), - ( - "krata/network/gateway/mac".to_string(), - gateway_mac_string.clone(), - ), ]; if let Some(name) = request.name.as_ref() { @@ -251,29 +223,14 @@ impl ZoneLauncher { extra_rw_paths: vec!["krata/zone".to_string()], }; match context.xen.create(&config).await { - Ok(created) => { - ip.commit().await?; - Ok(ZoneInfo { - name: request.name.as_ref().map(|x| x.to_string()), - uuid, - domid: created.domid, - image: request.image.digest, - loops: vec![], - zone_ipv4: Some(IpNetwork::new(IpAddr::V4(ip.ipv4), ip.ipv4_prefix)?), - zone_ipv6: Some(IpNetwork::new(IpAddr::V6(ip.ipv6), ip.ipv6_prefix)?), - zone_mac: Some(zone_mac_string.clone()), - gateway_ipv4: Some(IpNetwork::new( - IpAddr::V4(ip.gateway_ipv4), - ip.ipv4_prefix, - )?), - gateway_ipv6: Some(IpNetwork::new( - IpAddr::V6(ip.gateway_ipv6), - ip.ipv6_prefix, - )?), - gateway_mac: Some(gateway_mac_string.clone()), - state: ZoneState { exit_code: None }, - }) - } + Ok(created) => Ok(ZoneInfo { + name: request.name.as_ref().map(|x| x.to_string()), + uuid, + domid: created.domid, + image: request.image.digest, + loops: vec![], + state: ZoneState { exit_code: None }, + }), Err(error) => { let _ = context.autoloop.unloop(&image_squashfs_loop.path).await; let _ = context.autoloop.unloop(&cfgblk_squashfs_loop.path).await; diff --git a/crates/runtime/src/lib.rs b/crates/runtime/src/lib.rs index 92dd589..d0d9c80 100644 --- a/crates/runtime/src/lib.rs +++ b/crates/runtime/src/lib.rs @@ -1,12 +1,10 @@ -use std::{fs, net::Ipv4Addr, path::PathBuf, str::FromStr, sync::Arc}; +use std::{fs, path::PathBuf, str::FromStr, sync::Arc}; use anyhow::{anyhow, Result}; -use ip::IpVendor; -use ipnetwork::{IpNetwork, Ipv4Network, Ipv6Network}; use krataloopdev::LoopControl; -use log::{debug, error}; use tokio::sync::Semaphore; use uuid::Uuid; + use xenclient::XenClient; use xenstore::{XsdClient, XsdInterface}; @@ -19,7 +17,6 @@ use self::{ pub mod autoloop; pub mod cfgblk; pub mod channel; -pub mod ip; pub mod launch; pub mod power; @@ -48,12 +45,6 @@ pub struct ZoneInfo { pub domid: u32, pub image: String, pub loops: Vec, - pub zone_ipv4: Option, - pub zone_ipv6: Option, - pub zone_mac: Option, - pub gateway_ipv4: Option, - pub gateway_ipv6: Option, - pub gateway_mac: Option, pub state: ZoneState, } @@ -61,28 +52,14 @@ pub struct ZoneInfo { pub struct RuntimeContext { pub autoloop: AutoLoop, pub xen: XenClient, - pub ipvendor: IpVendor, } impl RuntimeContext { - pub async fn new(host_uuid: Uuid) -> Result { - debug!("initializing XenClient"); + pub async fn new() -> Result { let xen = XenClient::new(0, RuntimePlatform::new()).await?; - - debug!("initializing ip allocation vendor"); - let ipv4_network = Ipv4Network::new(Ipv4Addr::new(10, 75, 80, 0), 24)?; - let ipv6_network = Ipv6Network::from_str("fdd4:1476:6c7e::/48")?; - let ipvendor = - IpVendor::new(xen.store.clone(), host_uuid, ipv4_network, ipv6_network).await?; - - debug!("initializing loop devices"); - let autoloop = AutoLoop::new(LoopControl::open()?); - - debug!("krata runtime initialized!"); Ok(RuntimeContext { - autoloop, + autoloop: AutoLoop::new(LoopControl::open()?), xen, - ipvendor, }) } @@ -123,61 +100,6 @@ impl RuntimeContext { .store .read_string(&format!("{}/krata/loops", &dom_path)) .await?; - let zone_ipv4 = self - .xen - .store - .read_string(&format!("{}/krata/network/zone/ipv4", &dom_path)) - .await?; - let zone_ipv6 = self - .xen - .store - .read_string(&format!("{}/krata/network/zone/ipv6", &dom_path)) - .await?; - let zone_mac = self - .xen - .store - .read_string(&format!("{}/krata/network/zone/mac", &dom_path)) - .await?; - let gateway_ipv4 = self - .xen - .store - .read_string(&format!("{}/krata/network/gateway/ipv4", &dom_path)) - .await?; - let gateway_ipv6 = self - .xen - .store - .read_string(&format!("{}/krata/network/gateway/ipv6", &dom_path)) - .await?; - let gateway_mac = self - .xen - .store - .read_string(&format!("{}/krata/network/gateway/mac", &dom_path)) - .await?; - - let zone_ipv4 = if let Some(zone_ipv4) = zone_ipv4 { - IpNetwork::from_str(&zone_ipv4).ok() - } else { - None - }; - - let zone_ipv6 = if let Some(zone_ipv6) = zone_ipv6 { - IpNetwork::from_str(&zone_ipv6).ok() - } else { - None - }; - - let gateway_ipv4 = if let Some(gateway_ipv4) = gateway_ipv4 { - IpNetwork::from_str(&gateway_ipv4).ok() - } else { - None - }; - - let gateway_ipv6 = if let Some(gateway_ipv6) = gateway_ipv6 { - IpNetwork::from_str(&gateway_ipv6).ok() - } else { - None - }; - let exit_code = self .xen .store @@ -198,12 +120,6 @@ impl RuntimeContext { domid, image, loops, - zone_ipv4, - zone_ipv6, - zone_mac, - gateway_ipv4, - gateway_ipv6, - gateway_mac, state, }); } @@ -245,16 +161,14 @@ impl RuntimeContext { #[derive(Clone)] pub struct Runtime { - host_uuid: Uuid, context: RuntimeContext, launch_semaphore: Arc, } impl Runtime { - pub async fn new(host_uuid: Uuid) -> Result { - let context = RuntimeContext::new(host_uuid).await?; + pub async fn new() -> Result { + let context = RuntimeContext::new().await?; Ok(Self { - host_uuid, context, launch_semaphore: Arc::new(Semaphore::new(10)), }) @@ -290,11 +204,6 @@ impl Runtime { return Err(anyhow!("unable to find krata uuid based on the domain",)); } let uuid = Uuid::parse_str(&uuid)?; - let ip = self - .context - .ipvendor - .read_domain_assignment(uuid, domid) - .await?; let loops = store .read_string(format!("{}/krata/loops", dom_path).as_str()) .await?; @@ -314,16 +223,6 @@ impl Runtime { } } } - - if let Some(ip) = ip { - if let Err(error) = self.context.ipvendor.recall(&ip).await { - error!( - "failed to recall ip assignment for zone {}: {}", - uuid, error - ); - } - } - Ok(uuid) } @@ -332,11 +231,11 @@ impl Runtime { } pub async fn dupe(&self) -> Result { - Runtime::new(self.host_uuid).await + Runtime::new().await } pub async fn power_management_context(&self) -> Result { - let context = RuntimeContext::new(self.host_uuid).await?; + let context = RuntimeContext::new().await?; Ok(PowerManagementContext { context }) } } diff --git a/crates/xen/xenclient/src/lib.rs b/crates/xen/xenclient/src/lib.rs index 5c3f678..7954dda 100644 --- a/crates/xen/xenclient/src/lib.rs +++ b/crates/xen/xenclient/src/lib.rs @@ -130,8 +130,7 @@ impl XenClient

{ match self.init(created.domid, config, &created).await { Ok(_) => Ok(created), Err(err) => { - // ignore since destroying a domain is best - // effort when an error occurs + // ignore since destroying a domain is best-effort when an error occurs let _ = self.domain_manager.destroy(created.domid).await; Err(err) } diff --git a/crates/xen/xenevtchn/src/lib.rs b/crates/xen/xenevtchn/src/lib.rs index 1960343..61a4e4f 100644 --- a/crates/xen/xenevtchn/src/lib.rs +++ b/crates/xen/xenevtchn/src/lib.rs @@ -7,7 +7,7 @@ use crate::sys::{BindInterdomain, BindUnboundPort, BindVirq, Notify, UnbindPort} use crate::raw::EVENT_CHANNEL_DEVICE; use byteorder::{LittleEndian, ReadBytesExt}; -use log::warn; +use log::error; use std::collections::hash_map::Entry; use std::collections::HashMap; use std::mem::size_of; @@ -16,7 +16,6 @@ use std::os::raw::c_void; use std::sync::atomic::{AtomicBool, Ordering}; use std::sync::Arc; use tokio::fs::{File, OpenOptions}; -use tokio::io::AsyncReadExt; use tokio::sync::mpsc::{channel, Receiver, Sender}; use tokio::sync::{Mutex, RwLock}; @@ -185,9 +184,10 @@ impl EventChannelProcessor { if self.flag.load(Ordering::Acquire) { break; } - warn!("failed to process event channel notifications: {}", error); + error!("failed to process event channel wakes: {}", error); } }); + Ok(()) } diff --git a/crates/xen/xenstore/src/bus.rs b/crates/xen/xenstore/src/bus.rs index af481a1..ba14f7c 100644 --- a/crates/xen/xenstore/src/bus.rs +++ b/crates/xen/xenstore/src/bus.rs @@ -298,7 +298,7 @@ impl XsdSocketProcessor { break; } } - }; + } } Ok(()) } diff --git a/crates/zone/src/background.rs b/crates/zone/src/background.rs index ea103bd..eb73aaa 100644 --- a/crates/zone/src/background.rs +++ b/crates/zone/src/background.rs @@ -95,7 +95,7 @@ impl ZoneBackground { break; } } - }; + } } Ok(()) }