mirror of
https://github.com/edera-dev/krata.git
synced 2025-08-03 21:21:32 +00:00
Compare commits
6 Commits
Author | SHA1 | Date | |
---|---|---|---|
1d75dfb88a | |||
18bf370f74 | |||
506d2ccf46 | |||
6096dee2fe | |||
bf3b73bf24 | |||
87530edf70 |
10
CHANGELOG.md
10
CHANGELOG.md
@ -6,6 +6,16 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|||||||
|
|
||||||
## [Unreleased]
|
## [Unreleased]
|
||||||
|
|
||||||
|
## [0.0.17](https://github.com/edera-dev/krata/compare/v0.0.16...v0.0.17) - 2024-08-15
|
||||||
|
|
||||||
|
### Added
|
||||||
|
- *(krata)* first pass on cpu hotplug support ([#340](https://github.com/edera-dev/krata/pull/340))
|
||||||
|
- *(exec)* implement tty support (fixes [#335](https://github.com/edera-dev/krata/pull/335)) ([#336](https://github.com/edera-dev/krata/pull/336))
|
||||||
|
- *(krata)* dynamic resource allocation (closes [#298](https://github.com/edera-dev/krata/pull/298)) ([#333](https://github.com/edera-dev/krata/pull/333))
|
||||||
|
|
||||||
|
### Other
|
||||||
|
- update Cargo.toml dependencies
|
||||||
|
|
||||||
## [0.0.16](https://github.com/edera-dev/krata/compare/v0.0.15...v0.0.16) - 2024-08-14
|
## [0.0.16](https://github.com/edera-dev/krata/compare/v0.0.15...v0.0.16) - 2024-08-14
|
||||||
|
|
||||||
### Added
|
### Added
|
||||||
|
188
Cargo.lock
generated
188
Cargo.lock
generated
@ -190,7 +190,7 @@ dependencies = [
|
|||||||
"rustversion",
|
"rustversion",
|
||||||
"serde",
|
"serde",
|
||||||
"sync_wrapper 1.0.1",
|
"sync_wrapper 1.0.1",
|
||||||
"tower",
|
"tower 0.4.13",
|
||||||
"tower-layer",
|
"tower-layer",
|
||||||
"tower-service",
|
"tower-service",
|
||||||
]
|
]
|
||||||
@ -431,7 +431,7 @@ version = "7.1.1"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "b34115915337defe99b2aff5c2ce6771e5fbc4079f4b506301f5cf394c8452f7"
|
checksum = "b34115915337defe99b2aff5c2ce6771e5fbc4079f4b506301f5cf394c8452f7"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"crossterm",
|
"crossterm 0.27.0",
|
||||||
"strum",
|
"strum",
|
||||||
"strum_macros",
|
"strum_macros",
|
||||||
"unicode-width",
|
"unicode-width",
|
||||||
@ -439,13 +439,14 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "compact_str"
|
name = "compact_str"
|
||||||
version = "0.7.1"
|
version = "0.8.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "f86b9c4c00838774a6d902ef931eff7470720c51d90c2e32cfe15dc304737b3f"
|
checksum = "6050c3a16ddab2e412160b31f2c871015704239bca62f72f6e5f0be631d3f644"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"castaway",
|
"castaway",
|
||||||
"cfg-if",
|
"cfg-if",
|
||||||
"itoa",
|
"itoa",
|
||||||
|
"rustversion",
|
||||||
"ryu",
|
"ryu",
|
||||||
"static_assertions",
|
"static_assertions",
|
||||||
]
|
]
|
||||||
@ -520,10 +521,23 @@ checksum = "f476fe445d41c9e991fd07515a6f463074b782242ccf4a5b7b1d1012e70824df"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"bitflags 2.6.0",
|
"bitflags 2.6.0",
|
||||||
"crossterm_winapi",
|
"crossterm_winapi",
|
||||||
"futures-core",
|
|
||||||
"libc",
|
"libc",
|
||||||
"mio 0.8.11",
|
|
||||||
"parking_lot",
|
"parking_lot",
|
||||||
|
"winapi",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "crossterm"
|
||||||
|
version = "0.28.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "829d955a0bb380ef178a640b91779e3987da38c9aea133b20614cfed8cdea9c6"
|
||||||
|
dependencies = [
|
||||||
|
"bitflags 2.6.0",
|
||||||
|
"crossterm_winapi",
|
||||||
|
"futures-core",
|
||||||
|
"mio",
|
||||||
|
"parking_lot",
|
||||||
|
"rustix",
|
||||||
"signal-hook",
|
"signal-hook",
|
||||||
"signal-hook-mio",
|
"signal-hook-mio",
|
||||||
"winapi",
|
"winapi",
|
||||||
@ -1148,7 +1162,7 @@ dependencies = [
|
|||||||
"pin-project-lite",
|
"pin-project-lite",
|
||||||
"socket2",
|
"socket2",
|
||||||
"tokio",
|
"tokio",
|
||||||
"tower",
|
"tower 0.4.13",
|
||||||
"tower-service",
|
"tower-service",
|
||||||
"tracing",
|
"tracing",
|
||||||
]
|
]
|
||||||
@ -1202,6 +1216,16 @@ dependencies = [
|
|||||||
"unicode-width",
|
"unicode-width",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "instability"
|
||||||
|
version = "0.3.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "b23a0c8dfe501baac4adf6ebbfa6eddf8f0c07f56b058cc1288017e32397846c"
|
||||||
|
dependencies = [
|
||||||
|
"quote",
|
||||||
|
"syn 2.0.74",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "instant"
|
name = "instant"
|
||||||
version = "0.1.13"
|
version = "0.1.13"
|
||||||
@ -1267,7 +1291,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "krata"
|
name = "krata"
|
||||||
version = "0.0.16"
|
version = "0.0.17"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"async-trait",
|
"async-trait",
|
||||||
@ -1290,7 +1314,7 @@ dependencies = [
|
|||||||
"tokio-stream",
|
"tokio-stream",
|
||||||
"tonic",
|
"tonic",
|
||||||
"tonic-build",
|
"tonic-build",
|
||||||
"tower",
|
"tower 0.5.0",
|
||||||
"url",
|
"url",
|
||||||
]
|
]
|
||||||
|
|
||||||
@ -1307,7 +1331,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "krata-buildtools"
|
name = "krata-buildtools"
|
||||||
version = "0.0.16"
|
version = "0.0.17"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"env_logger",
|
"env_logger",
|
||||||
@ -1322,14 +1346,14 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "krata-ctl"
|
name = "krata-ctl"
|
||||||
version = "0.0.16"
|
version = "0.0.17"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"async-stream",
|
"async-stream",
|
||||||
"base64",
|
"base64",
|
||||||
"clap",
|
"clap",
|
||||||
"comfy-table",
|
"comfy-table",
|
||||||
"crossterm",
|
"crossterm 0.28.1",
|
||||||
"ctrlc",
|
"ctrlc",
|
||||||
"env_logger",
|
"env_logger",
|
||||||
"fancy-duration",
|
"fancy-duration",
|
||||||
@ -1347,12 +1371,12 @@ dependencies = [
|
|||||||
"tokio",
|
"tokio",
|
||||||
"tokio-stream",
|
"tokio-stream",
|
||||||
"tonic",
|
"tonic",
|
||||||
"tower",
|
"tower 0.5.0",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "krata-daemon"
|
name = "krata-daemon"
|
||||||
version = "0.0.16"
|
version = "0.0.17"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"async-stream",
|
"async-stream",
|
||||||
@ -1384,14 +1408,14 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "krata-loopdev"
|
name = "krata-loopdev"
|
||||||
version = "0.0.16"
|
version = "0.0.17"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"libc",
|
"libc",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "krata-network"
|
name = "krata-network"
|
||||||
version = "0.0.16"
|
version = "0.0.17"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"async-trait",
|
"async-trait",
|
||||||
@ -1415,7 +1439,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "krata-oci"
|
name = "krata-oci"
|
||||||
version = "0.0.16"
|
version = "0.0.17"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"async-compression",
|
"async-compression",
|
||||||
@ -1442,7 +1466,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "krata-runtime"
|
name = "krata-runtime"
|
||||||
version = "0.0.16"
|
version = "0.0.17"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"backhand",
|
"backhand",
|
||||||
@ -1483,7 +1507,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "krata-xencall"
|
name = "krata-xencall"
|
||||||
version = "0.0.16"
|
version = "0.0.17"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"env_logger",
|
"env_logger",
|
||||||
"libc",
|
"libc",
|
||||||
@ -1496,7 +1520,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "krata-xenclient"
|
name = "krata-xenclient"
|
||||||
version = "0.0.16"
|
version = "0.0.17"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"async-trait",
|
"async-trait",
|
||||||
"env_logger",
|
"env_logger",
|
||||||
@ -1514,7 +1538,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "krata-xenevtchn"
|
name = "krata-xenevtchn"
|
||||||
version = "0.0.16"
|
version = "0.0.17"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"byteorder",
|
"byteorder",
|
||||||
"libc",
|
"libc",
|
||||||
@ -1526,7 +1550,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "krata-xengnt"
|
name = "krata-xengnt"
|
||||||
version = "0.0.16"
|
version = "0.0.17"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"libc",
|
"libc",
|
||||||
"nix 0.29.0",
|
"nix 0.29.0",
|
||||||
@ -1535,7 +1559,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "krata-xenplatform"
|
name = "krata-xenplatform"
|
||||||
version = "0.0.16"
|
version = "0.0.17"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"async-trait",
|
"async-trait",
|
||||||
"c2rust-bitfields",
|
"c2rust-bitfields",
|
||||||
@ -1558,7 +1582,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "krata-xenstore"
|
name = "krata-xenstore"
|
||||||
version = "0.0.16"
|
version = "0.0.17"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"byteorder",
|
"byteorder",
|
||||||
"env_logger",
|
"env_logger",
|
||||||
@ -1570,7 +1594,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "krata-zone"
|
name = "krata-zone"
|
||||||
version = "0.0.16"
|
version = "0.0.17"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"cgroups-rs",
|
"cgroups-rs",
|
||||||
@ -1585,6 +1609,7 @@ dependencies = [
|
|||||||
"oci-spec",
|
"oci-spec",
|
||||||
"path-absolutize",
|
"path-absolutize",
|
||||||
"platform-info",
|
"platform-info",
|
||||||
|
"pty-process",
|
||||||
"rtnetlink",
|
"rtnetlink",
|
||||||
"serde",
|
"serde",
|
||||||
"serde_json",
|
"serde_json",
|
||||||
@ -1691,18 +1716,6 @@ dependencies = [
|
|||||||
"adler",
|
"adler",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "mio"
|
|
||||||
version = "0.8.11"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "a4a650543ca06a924e8b371db273b2756685faae30f8487da1b56505a8f78b0c"
|
|
||||||
dependencies = [
|
|
||||||
"libc",
|
|
||||||
"log",
|
|
||||||
"wasi",
|
|
||||||
"windows-sys 0.48.0",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "mio"
|
name = "mio"
|
||||||
version = "1.0.2"
|
version = "1.0.2"
|
||||||
@ -1711,6 +1724,7 @@ checksum = "80e04d1dcff3aae0704555fe5fee3bcfaf3d1fdf8a7e521d5b9d2b42acb52cec"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"hermit-abi",
|
"hermit-abi",
|
||||||
"libc",
|
"libc",
|
||||||
|
"log",
|
||||||
"wasi",
|
"wasi",
|
||||||
"windows-sys 0.52.0",
|
"windows-sys 0.52.0",
|
||||||
]
|
]
|
||||||
@ -2168,6 +2182,17 @@ dependencies = [
|
|||||||
"prost",
|
"prost",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "pty-process"
|
||||||
|
version = "0.4.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "8749b545e244c90bf74a5767764cc2194f1888bb42f84015486a64c82bea5cc0"
|
||||||
|
dependencies = [
|
||||||
|
"libc",
|
||||||
|
"rustix",
|
||||||
|
"tokio",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "quinn"
|
name = "quinn"
|
||||||
version = "0.11.3"
|
version = "0.11.3"
|
||||||
@ -2263,18 +2288,18 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "ratatui"
|
name = "ratatui"
|
||||||
version = "0.27.0"
|
version = "0.28.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "d16546c5b5962abf8ce6e2881e722b4e0ae3b6f1a08a26ae3573c55853ca68d3"
|
checksum = "5ba6a365afbe5615999275bea2446b970b10a41102500e27ce7678d50d978303"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bitflags 2.6.0",
|
"bitflags 2.6.0",
|
||||||
"cassowary",
|
"cassowary",
|
||||||
"compact_str",
|
"compact_str",
|
||||||
"crossterm",
|
"crossterm 0.28.1",
|
||||||
|
"instability",
|
||||||
"itertools",
|
"itertools",
|
||||||
"lru",
|
"lru",
|
||||||
"paste",
|
"paste",
|
||||||
"stability",
|
|
||||||
"strum",
|
"strum",
|
||||||
"strum_macros",
|
"strum_macros",
|
||||||
"unicode-segmentation",
|
"unicode-segmentation",
|
||||||
@ -2459,6 +2484,7 @@ checksum = "70dc5ec042f7a43c4a73241207cecc9873a06d45debb38b329f8541d85c2730f"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"bitflags 2.6.0",
|
"bitflags 2.6.0",
|
||||||
"errno",
|
"errno",
|
||||||
|
"itoa",
|
||||||
"libc",
|
"libc",
|
||||||
"linux-raw-sys",
|
"linux-raw-sys",
|
||||||
"windows-sys 0.52.0",
|
"windows-sys 0.52.0",
|
||||||
@ -2565,9 +2591,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "serde_json"
|
name = "serde_json"
|
||||||
version = "1.0.124"
|
version = "1.0.125"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "66ad62847a56b3dba58cc891acd13884b9c61138d330c0d7b6181713d4fce38d"
|
checksum = "83c8e735a073ccf5be70aa8066aa984eaf2fa000db6c8d0100ae605b366d31ed"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"itoa",
|
"itoa",
|
||||||
"memchr",
|
"memchr",
|
||||||
@ -2650,7 +2676,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||||||
checksum = "34db1a06d485c9142248b7a054f034b349b212551f3dfd19c94d45a754a217cd"
|
checksum = "34db1a06d485c9142248b7a054f034b349b212551f3dfd19c94d45a754a217cd"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"libc",
|
"libc",
|
||||||
"mio 0.8.11",
|
"mio",
|
||||||
"signal-hook",
|
"signal-hook",
|
||||||
]
|
]
|
||||||
|
|
||||||
@ -2727,16 +2753,6 @@ version = "0.9.8"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67"
|
checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "stability"
|
|
||||||
version = "0.2.1"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "d904e7009df136af5297832a3ace3370cd14ff1546a232f4f185036c2736fcac"
|
|
||||||
dependencies = [
|
|
||||||
"quote",
|
|
||||||
"syn 2.0.74",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "stable_deref_trait"
|
name = "stable_deref_trait"
|
||||||
version = "1.2.0"
|
version = "1.2.0"
|
||||||
@ -2832,15 +2848,14 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "sysinfo"
|
name = "sysinfo"
|
||||||
version = "0.30.13"
|
version = "0.31.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "0a5b4ddaee55fb2bea2bf0e5000747e5f5c0de765e5a5ff87f4cd106439f4bb3"
|
checksum = "d4115055da5f572fff541dd0c4e61b0262977f453cc9fe04be83aba25a89bdab"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cfg-if",
|
|
||||||
"core-foundation-sys",
|
"core-foundation-sys",
|
||||||
"libc",
|
"libc",
|
||||||
|
"memchr",
|
||||||
"ntapi",
|
"ntapi",
|
||||||
"once_cell",
|
|
||||||
"rayon",
|
"rayon",
|
||||||
"windows",
|
"windows",
|
||||||
]
|
]
|
||||||
@ -2914,7 +2929,7 @@ dependencies = [
|
|||||||
"backtrace",
|
"backtrace",
|
||||||
"bytes",
|
"bytes",
|
||||||
"libc",
|
"libc",
|
||||||
"mio 1.0.2",
|
"mio",
|
||||||
"parking_lot",
|
"parking_lot",
|
||||||
"pin-project-lite",
|
"pin-project-lite",
|
||||||
"signal-hook-registry",
|
"signal-hook-registry",
|
||||||
@ -3052,7 +3067,7 @@ dependencies = [
|
|||||||
"tokio",
|
"tokio",
|
||||||
"tokio-rustls",
|
"tokio-rustls",
|
||||||
"tokio-stream",
|
"tokio-stream",
|
||||||
"tower",
|
"tower 0.4.13",
|
||||||
"tower-layer",
|
"tower-layer",
|
||||||
"tower-service",
|
"tower-service",
|
||||||
"tracing",
|
"tracing",
|
||||||
@ -3091,6 +3106,16 @@ dependencies = [
|
|||||||
"tracing",
|
"tracing",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "tower"
|
||||||
|
version = "0.5.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "36b837f86b25d7c0d7988f00a54e74739be6477f2aac6201b8f429a7569991b7"
|
||||||
|
dependencies = [
|
||||||
|
"tower-layer",
|
||||||
|
"tower-service",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "tower-layer"
|
name = "tower-layer"
|
||||||
version = "0.3.3"
|
version = "0.3.3"
|
||||||
@ -3109,7 +3134,6 @@ version = "0.1.40"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "c3523ab5a71916ccf420eebdf5521fcef02141234bbc0b8a49f2fdc4544364ef"
|
checksum = "c3523ab5a71916ccf420eebdf5521fcef02141234bbc0b8a49f2fdc4544364ef"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"log",
|
|
||||||
"pin-project-lite",
|
"pin-project-lite",
|
||||||
"tracing-attributes",
|
"tracing-attributes",
|
||||||
"tracing-core",
|
"tracing-core",
|
||||||
@ -3390,9 +3414,9 @@ checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "windows"
|
name = "windows"
|
||||||
version = "0.52.0"
|
version = "0.57.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "e48a53791691ab099e5e2ad123536d0fff50652600abaf43bbf952894110d0be"
|
checksum = "12342cb4d8e3b046f3d80effd474a7a02447231330ef77d71daa6fbc40681143"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"windows-core",
|
"windows-core",
|
||||||
"windows-targets 0.52.6",
|
"windows-targets 0.52.6",
|
||||||
@ -3400,9 +3424,43 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "windows-core"
|
name = "windows-core"
|
||||||
version = "0.52.0"
|
version = "0.57.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9"
|
checksum = "d2ed2439a290666cd67ecce2b0ffaad89c2a56b976b736e6ece670297897832d"
|
||||||
|
dependencies = [
|
||||||
|
"windows-implement",
|
||||||
|
"windows-interface",
|
||||||
|
"windows-result",
|
||||||
|
"windows-targets 0.52.6",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows-implement"
|
||||||
|
version = "0.57.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "9107ddc059d5b6fbfbffdfa7a7fe3e22a226def0b2608f72e9d552763d3e1ad7"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn 2.0.74",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows-interface"
|
||||||
|
version = "0.57.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "29bee4b38ea3cde66011baa44dba677c432a78593e202392d1e9070cf2a7fca7"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn 2.0.74",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows-result"
|
||||||
|
version = "0.1.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "5e383302e8ec8515204254685643de10811af0ed97ea37210dc26fb0032647f8"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"windows-targets 0.52.6",
|
"windows-targets 0.52.6",
|
||||||
]
|
]
|
||||||
|
13
Cargo.toml
13
Cargo.toml
@ -18,7 +18,7 @@ members = [
|
|||||||
resolver = "2"
|
resolver = "2"
|
||||||
|
|
||||||
[workspace.package]
|
[workspace.package]
|
||||||
version = "0.0.16"
|
version = "0.0.17"
|
||||||
homepage = "https://krata.dev"
|
homepage = "https://krata.dev"
|
||||||
license = "Apache-2.0"
|
license = "Apache-2.0"
|
||||||
repository = "https://github.com/edera-dev/krata"
|
repository = "https://github.com/edera-dev/krata"
|
||||||
@ -37,7 +37,7 @@ c2rust-bitfields = "0.18.0"
|
|||||||
cgroups-rs = "0.3.4"
|
cgroups-rs = "0.3.4"
|
||||||
circular-buffer = "0.1.7"
|
circular-buffer = "0.1.7"
|
||||||
comfy-table = "7.1.1"
|
comfy-table = "7.1.1"
|
||||||
crossterm = "0.27.0"
|
crossterm = "0.28.1"
|
||||||
ctrlc = "3.4.5"
|
ctrlc = "3.4.5"
|
||||||
elf = "0.7.4"
|
elf = "0.7.4"
|
||||||
env_logger = "0.11.5"
|
env_logger = "0.11.5"
|
||||||
@ -68,25 +68,26 @@ prost = "0.13.1"
|
|||||||
prost-build = "0.13.1"
|
prost-build = "0.13.1"
|
||||||
prost-reflect-build = "0.14.0"
|
prost-reflect-build = "0.14.0"
|
||||||
prost-types = "0.13.1"
|
prost-types = "0.13.1"
|
||||||
|
pty-process = "0.4.0"
|
||||||
rand = "0.8.5"
|
rand = "0.8.5"
|
||||||
ratatui = "0.27.0"
|
ratatui = "0.28.0"
|
||||||
redb = "2.1.1"
|
redb = "2.1.1"
|
||||||
regex = "1.10.6"
|
regex = "1.10.6"
|
||||||
rtnetlink = "0.14.1"
|
rtnetlink = "0.14.1"
|
||||||
scopeguard = "1.2.0"
|
scopeguard = "1.2.0"
|
||||||
serde_json = "1.0.124"
|
serde_json = "1.0.125"
|
||||||
serde_yaml = "0.9"
|
serde_yaml = "0.9"
|
||||||
sha256 = "1.5.0"
|
sha256 = "1.5.0"
|
||||||
signal-hook = "0.3.17"
|
signal-hook = "0.3.17"
|
||||||
slice-copy = "0.3.0"
|
slice-copy = "0.3.0"
|
||||||
smoltcp = "0.11.0"
|
smoltcp = "0.11.0"
|
||||||
sysinfo = "0.30.13"
|
sysinfo = "0.31.2"
|
||||||
termtree = "0.5.1"
|
termtree = "0.5.1"
|
||||||
thiserror = "1.0"
|
thiserror = "1.0"
|
||||||
tokio-tun = "0.11.5"
|
tokio-tun = "0.11.5"
|
||||||
toml = "0.8.19"
|
toml = "0.8.19"
|
||||||
tonic-build = "0.12.1"
|
tonic-build = "0.12.1"
|
||||||
tower = "0.4.13"
|
tower = "0.5.0"
|
||||||
udp-stream = "0.0.12"
|
udp-stream = "0.0.12"
|
||||||
url = "2.5.2"
|
url = "2.5.2"
|
||||||
walkdir = "2"
|
walkdir = "2"
|
||||||
|
@ -16,7 +16,7 @@ oci-spec = { workspace = true }
|
|||||||
scopeguard = { workspace = true }
|
scopeguard = { workspace = true }
|
||||||
tokio = { workspace = true }
|
tokio = { workspace = true }
|
||||||
tokio-stream = { workspace = true }
|
tokio-stream = { workspace = true }
|
||||||
krata-oci = { path = "../oci", version = "^0.0.16" }
|
krata-oci = { path = "../oci", version = "^0.0.17" }
|
||||||
krata-tokio-tar = { workspace = true }
|
krata-tokio-tar = { workspace = true }
|
||||||
uuid = { workspace = true }
|
uuid = { workspace = true }
|
||||||
|
|
||||||
|
@ -20,7 +20,7 @@ env_logger = { workspace = true }
|
|||||||
fancy-duration = { workspace = true }
|
fancy-duration = { workspace = true }
|
||||||
human_bytes = { workspace = true }
|
human_bytes = { workspace = true }
|
||||||
indicatif = { workspace = true }
|
indicatif = { workspace = true }
|
||||||
krata = { path = "../krata", version = "^0.0.16" }
|
krata = { path = "../krata", version = "^0.0.17" }
|
||||||
log = { workspace = true }
|
log = { workspace = true }
|
||||||
prost-reflect = { workspace = true, features = ["serde"] }
|
prost-reflect = { workspace = true, features = ["serde"] }
|
||||||
prost-types = { workspace = true }
|
prost-types = { workspace = true }
|
||||||
|
@ -21,6 +21,8 @@ pub struct ZoneExecCommand {
|
|||||||
env: Option<Vec<String>>,
|
env: Option<Vec<String>>,
|
||||||
#[arg(short = 'w', long, help = "Working directory")]
|
#[arg(short = 'w', long, help = "Working directory")]
|
||||||
working_directory: Option<String>,
|
working_directory: Option<String>,
|
||||||
|
#[arg(short = 't', long, help = "Allocate tty")]
|
||||||
|
tty: bool,
|
||||||
#[arg(help = "Zone to exec inside, either the name or the uuid")]
|
#[arg(help = "Zone to exec inside, either the name or the uuid")]
|
||||||
zone: String,
|
zone: String,
|
||||||
#[arg(
|
#[arg(
|
||||||
@ -46,8 +48,10 @@ impl ZoneExecCommand {
|
|||||||
.collect(),
|
.collect(),
|
||||||
command: self.command,
|
command: self.command,
|
||||||
working_directory: self.working_directory.unwrap_or_default(),
|
working_directory: self.working_directory.unwrap_or_default(),
|
||||||
|
tty: self.tty,
|
||||||
}),
|
}),
|
||||||
data: vec![],
|
stdin: vec![],
|
||||||
|
stdin_closed: false,
|
||||||
};
|
};
|
||||||
|
|
||||||
let stream = StdioConsoleStream::stdin_stream_exec(initial).await;
|
let stream = StdioConsoleStream::stdin_stream_exec(initial).await;
|
||||||
@ -57,7 +61,7 @@ impl ZoneExecCommand {
|
|||||||
.await?
|
.await?
|
||||||
.into_inner();
|
.into_inner();
|
||||||
|
|
||||||
let code = StdioConsoleStream::exec_output(response).await?;
|
let code = StdioConsoleStream::exec_output(response, self.tty).await?;
|
||||||
std::process::exit(code);
|
std::process::exit(code);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -6,8 +6,9 @@ use krata::{
|
|||||||
events::EventStream,
|
events::EventStream,
|
||||||
v1::{
|
v1::{
|
||||||
common::{
|
common::{
|
||||||
zone_image_spec::Image, OciImageFormat, ZoneImageSpec, ZoneOciImageSpec, ZoneSpec,
|
zone_image_spec::Image, OciImageFormat, ZoneImageSpec, ZoneOciImageSpec,
|
||||||
ZoneSpecDevice, ZoneState, ZoneTaskSpec, ZoneTaskSpecEnvVar,
|
ZoneResourceSpec, ZoneSpec, ZoneSpecDevice, ZoneState, ZoneTaskSpec,
|
||||||
|
ZoneTaskSpecEnvVar,
|
||||||
},
|
},
|
||||||
control::{
|
control::{
|
||||||
control_service_client::ControlServiceClient, watch_events_reply::Event,
|
control_service_client::ControlServiceClient, watch_events_reply::Event,
|
||||||
@ -38,19 +39,40 @@ pub struct ZoneLaunchCommand {
|
|||||||
pull_update: bool,
|
pull_update: bool,
|
||||||
#[arg(short, long, help = "Name of the zone")]
|
#[arg(short, long, help = "Name of the zone")]
|
||||||
name: Option<String>,
|
name: Option<String>,
|
||||||
#[arg(short, long, default_value_t = 1, help = "vCPUs available to the zone")]
|
|
||||||
cpus: u32,
|
|
||||||
#[arg(
|
#[arg(
|
||||||
short,
|
short = 'C',
|
||||||
long,
|
long = "max-cpus",
|
||||||
default_value_t = 512,
|
default_value_t = 4,
|
||||||
help = "Memory available to the zone, in megabytes"
|
help = "Maximum vCPUs available for the zone"
|
||||||
)]
|
)]
|
||||||
mem: u64,
|
max_cpus: u32,
|
||||||
|
#[arg(
|
||||||
|
short = 'c',
|
||||||
|
long = "target-cpus",
|
||||||
|
default_value_t = 1,
|
||||||
|
help = "Target vCPUs for the zone to use"
|
||||||
|
)]
|
||||||
|
target_cpus: u32,
|
||||||
|
#[arg(
|
||||||
|
short = 'M',
|
||||||
|
long = "max-memory",
|
||||||
|
default_value_t = 1024,
|
||||||
|
help = "Maximum memory available to the zone, in megabytes"
|
||||||
|
)]
|
||||||
|
max_memory: u64,
|
||||||
|
#[arg(
|
||||||
|
short = 'm',
|
||||||
|
long = "target-memory",
|
||||||
|
default_value_t = 1024,
|
||||||
|
help = "Target memory for the zone to use, in megabytes"
|
||||||
|
)]
|
||||||
|
target_memory: u64,
|
||||||
#[arg[short = 'D', long = "device", help = "Devices to request for the zone"]]
|
#[arg[short = 'D', long = "device", help = "Devices to request for the zone"]]
|
||||||
device: Vec<String>,
|
device: Vec<String>,
|
||||||
#[arg[short, long, help = "Environment variables set in the zone"]]
|
#[arg[short, long, help = "Environment variables set in the zone"]]
|
||||||
env: Option<Vec<String>>,
|
env: Option<Vec<String>>,
|
||||||
|
#[arg(short = 't', long, help = "Allocate tty for task")]
|
||||||
|
tty: bool,
|
||||||
#[arg(
|
#[arg(
|
||||||
short,
|
short,
|
||||||
long,
|
long,
|
||||||
@ -120,8 +142,12 @@ impl ZoneLaunchCommand {
|
|||||||
image: Some(image),
|
image: Some(image),
|
||||||
kernel,
|
kernel,
|
||||||
initrd,
|
initrd,
|
||||||
cpus: self.cpus,
|
initial_resources: Some(ZoneResourceSpec {
|
||||||
mem: self.mem,
|
max_memory: self.max_memory,
|
||||||
|
target_memory: self.target_memory,
|
||||||
|
max_cpus: self.max_cpus,
|
||||||
|
target_cpus: self.target_cpus,
|
||||||
|
}),
|
||||||
task: Some(ZoneTaskSpec {
|
task: Some(ZoneTaskSpec {
|
||||||
environment: env_map(&self.env.unwrap_or_default())
|
environment: env_map(&self.env.unwrap_or_default())
|
||||||
.iter()
|
.iter()
|
||||||
@ -132,6 +158,7 @@ impl ZoneLaunchCommand {
|
|||||||
.collect(),
|
.collect(),
|
||||||
command: self.command,
|
command: self.command,
|
||||||
working_directory: self.working_directory.unwrap_or_default(),
|
working_directory: self.working_directory.unwrap_or_default(),
|
||||||
|
tty: self.tty,
|
||||||
}),
|
}),
|
||||||
annotations: vec![],
|
annotations: vec![],
|
||||||
devices: self
|
devices: self
|
||||||
|
@ -14,6 +14,7 @@ use crate::cli::zone::logs::ZoneLogsCommand;
|
|||||||
use crate::cli::zone::metrics::ZoneMetricsCommand;
|
use crate::cli::zone::metrics::ZoneMetricsCommand;
|
||||||
use crate::cli::zone::resolve::ZoneResolveCommand;
|
use crate::cli::zone::resolve::ZoneResolveCommand;
|
||||||
use crate::cli::zone::top::ZoneTopCommand;
|
use crate::cli::zone::top::ZoneTopCommand;
|
||||||
|
use crate::cli::zone::update_resources::ZoneUpdateResourcesCommand;
|
||||||
use crate::cli::zone::watch::ZoneWatchCommand;
|
use crate::cli::zone::watch::ZoneWatchCommand;
|
||||||
|
|
||||||
pub mod attach;
|
pub mod attach;
|
||||||
@ -25,6 +26,7 @@ pub mod logs;
|
|||||||
pub mod metrics;
|
pub mod metrics;
|
||||||
pub mod resolve;
|
pub mod resolve;
|
||||||
pub mod top;
|
pub mod top;
|
||||||
|
mod update_resources;
|
||||||
pub mod watch;
|
pub mod watch;
|
||||||
|
|
||||||
#[derive(Parser)]
|
#[derive(Parser)]
|
||||||
@ -56,6 +58,7 @@ pub enum ZoneCommands {
|
|||||||
Resolve(ZoneResolveCommand),
|
Resolve(ZoneResolveCommand),
|
||||||
Top(ZoneTopCommand),
|
Top(ZoneTopCommand),
|
||||||
Watch(ZoneWatchCommand),
|
Watch(ZoneWatchCommand),
|
||||||
|
UpdateResources(ZoneUpdateResourcesCommand),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ZoneCommands {
|
impl ZoneCommands {
|
||||||
@ -84,6 +87,8 @@ impl ZoneCommands {
|
|||||||
ZoneCommands::Top(top) => top.run(client, events).await,
|
ZoneCommands::Top(top) => top.run(client, events).await,
|
||||||
|
|
||||||
ZoneCommands::Exec(exec) => exec.run(client).await,
|
ZoneCommands::Exec(exec) => exec.run(client).await,
|
||||||
|
|
||||||
|
ZoneCommands::UpdateResources(update_resources) => update_resources.run(client).await,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -112,7 +112,7 @@ impl ZoneTopApp {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn render_frame(&mut self, frame: &mut Frame) {
|
fn render_frame(&mut self, frame: &mut Frame) {
|
||||||
frame.render_widget(self, frame.size());
|
frame.render_widget(self, frame.area());
|
||||||
}
|
}
|
||||||
|
|
||||||
fn handle_event(&mut self, event: Event) -> io::Result<()> {
|
fn handle_event(&mut self, event: Event) -> io::Result<()> {
|
||||||
|
93
crates/ctl/src/cli/zone/update_resources.rs
Normal file
93
crates/ctl/src/cli/zone/update_resources.rs
Normal file
@ -0,0 +1,93 @@
|
|||||||
|
use anyhow::Result;
|
||||||
|
use clap::Parser;
|
||||||
|
use krata::v1::{
|
||||||
|
common::ZoneResourceSpec,
|
||||||
|
control::{control_service_client::ControlServiceClient, UpdateZoneResourcesRequest},
|
||||||
|
};
|
||||||
|
|
||||||
|
use crate::cli::resolve_zone;
|
||||||
|
use krata::v1::control::GetZoneRequest;
|
||||||
|
use tonic::{transport::Channel, Request};
|
||||||
|
|
||||||
|
#[derive(Parser)]
|
||||||
|
#[command(about = "Update the available resources to a zone")]
|
||||||
|
pub struct ZoneUpdateResourcesCommand {
|
||||||
|
#[arg(help = "Zone to update resources of, either the name or the uuid")]
|
||||||
|
zone: String,
|
||||||
|
#[arg(
|
||||||
|
short = 'C',
|
||||||
|
long = "max-cpus",
|
||||||
|
default_value_t = 0,
|
||||||
|
help = "Maximum vCPUs available to the zone (0 means previous value)"
|
||||||
|
)]
|
||||||
|
max_cpus: u32,
|
||||||
|
#[arg(
|
||||||
|
short = 'c',
|
||||||
|
long = "target-cpus",
|
||||||
|
default_value_t = 0,
|
||||||
|
help = "Target vCPUs for the zone to use (0 means previous value)"
|
||||||
|
)]
|
||||||
|
target_cpus: u32,
|
||||||
|
#[arg(
|
||||||
|
short = 'M',
|
||||||
|
long = "max-memory",
|
||||||
|
default_value_t = 0,
|
||||||
|
help = "Maximum memory available to the zone, in megabytes (0 means previous value)"
|
||||||
|
)]
|
||||||
|
max_memory: u64,
|
||||||
|
#[arg(
|
||||||
|
short = 'm',
|
||||||
|
long = "target-memory",
|
||||||
|
default_value_t = 0,
|
||||||
|
help = "Target memory for the zone to use, in megabytes (0 means previous value)"
|
||||||
|
)]
|
||||||
|
target_memory: u64,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ZoneUpdateResourcesCommand {
|
||||||
|
pub async fn run(self, mut client: ControlServiceClient<Channel>) -> Result<()> {
|
||||||
|
let zone_id = resolve_zone(&mut client, &self.zone).await?;
|
||||||
|
let zone = client
|
||||||
|
.get_zone(GetZoneRequest { zone_id })
|
||||||
|
.await?
|
||||||
|
.into_inner()
|
||||||
|
.zone
|
||||||
|
.unwrap_or_default();
|
||||||
|
let active_resources = zone
|
||||||
|
.status
|
||||||
|
.clone()
|
||||||
|
.unwrap_or_default()
|
||||||
|
.resource_status
|
||||||
|
.unwrap_or_default()
|
||||||
|
.active_resources
|
||||||
|
.unwrap_or_default();
|
||||||
|
client
|
||||||
|
.update_zone_resources(Request::new(UpdateZoneResourcesRequest {
|
||||||
|
zone_id: zone.id.clone(),
|
||||||
|
resources: Some(ZoneResourceSpec {
|
||||||
|
max_memory: if self.max_memory == 0 {
|
||||||
|
active_resources.max_memory
|
||||||
|
} else {
|
||||||
|
self.max_memory
|
||||||
|
},
|
||||||
|
target_memory: if self.target_memory == 0 {
|
||||||
|
active_resources.target_memory
|
||||||
|
} else {
|
||||||
|
self.target_memory
|
||||||
|
},
|
||||||
|
max_cpus: if self.max_cpus == 0 {
|
||||||
|
active_resources.max_cpus
|
||||||
|
} else {
|
||||||
|
self.max_cpus
|
||||||
|
},
|
||||||
|
target_cpus: if self.target_cpus == 0 {
|
||||||
|
active_resources.target_cpus
|
||||||
|
} else {
|
||||||
|
self.target_cpus
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
}))
|
||||||
|
.await?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
@ -62,11 +62,15 @@ impl StdioConsoleStream {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
let data = buffer[0..size].to_vec();
|
let stdin = buffer[0..size].to_vec();
|
||||||
if size == 1 && buffer[0] == 0x1d {
|
if size == 1 && buffer[0] == 0x1d {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
yield ExecInsideZoneRequest { zone_id: String::default(), task: None, data };
|
let stdin_closed = size == 0;
|
||||||
|
yield ExecInsideZoneRequest { zone_id: String::default(), task: None, stdin, stdin_closed, };
|
||||||
|
if stdin_closed {
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -88,7 +92,11 @@ impl StdioConsoleStream {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn exec_output(mut stream: Streaming<ExecInsideZoneReply>) -> Result<i32> {
|
pub async fn exec_output(mut stream: Streaming<ExecInsideZoneReply>, raw: bool) -> Result<i32> {
|
||||||
|
if raw && stdin().is_tty() {
|
||||||
|
enable_raw_mode()?;
|
||||||
|
StdioConsoleStream::register_terminal_restore_hook()?;
|
||||||
|
}
|
||||||
let mut stdout = stdout();
|
let mut stdout = stdout();
|
||||||
let mut stderr = stderr();
|
let mut stderr = stderr();
|
||||||
while let Some(reply) = stream.next().await {
|
while let Some(reply) = stream.next().await {
|
||||||
|
@ -19,9 +19,9 @@ clap = { workspace = true }
|
|||||||
env_logger = { workspace = true }
|
env_logger = { workspace = true }
|
||||||
futures = { workspace = true }
|
futures = { workspace = true }
|
||||||
ipnetwork = { workspace = true }
|
ipnetwork = { workspace = true }
|
||||||
krata = { path = "../krata", version = "^0.0.16" }
|
krata = { path = "../krata", version = "^0.0.17" }
|
||||||
krata-oci = { path = "../oci", version = "^0.0.16" }
|
krata-oci = { path = "../oci", version = "^0.0.17" }
|
||||||
krata-runtime = { path = "../runtime", version = "^0.0.16" }
|
krata-runtime = { path = "../runtime", version = "^0.0.17" }
|
||||||
log = { workspace = true }
|
log = { workspace = true }
|
||||||
prost = { workspace = true }
|
prost = { workspace = true }
|
||||||
redb = { workspace = true }
|
redb = { workspace = true }
|
||||||
|
@ -6,6 +6,7 @@ use crate::{
|
|||||||
};
|
};
|
||||||
use async_stream::try_stream;
|
use async_stream::try_stream;
|
||||||
use futures::Stream;
|
use futures::Stream;
|
||||||
|
use krata::v1::common::ZoneResourceStatus;
|
||||||
use krata::v1::control::{
|
use krata::v1::control::{
|
||||||
GetZoneReply, GetZoneRequest, SetHostPowerManagementPolicyReply,
|
GetZoneReply, GetZoneRequest, SetHostPowerManagementPolicyReply,
|
||||||
SetHostPowerManagementPolicyRequest,
|
SetHostPowerManagementPolicyRequest,
|
||||||
@ -25,8 +26,8 @@ use krata::{
|
|||||||
HostCpuTopologyInfo, HostStatusReply, HostStatusRequest, ListDevicesReply,
|
HostCpuTopologyInfo, HostStatusReply, HostStatusRequest, ListDevicesReply,
|
||||||
ListDevicesRequest, ListZonesReply, ListZonesRequest, PullImageReply, PullImageRequest,
|
ListDevicesRequest, ListZonesReply, ListZonesRequest, PullImageReply, PullImageRequest,
|
||||||
ReadZoneMetricsReply, ReadZoneMetricsRequest, ResolveZoneIdReply, ResolveZoneIdRequest,
|
ReadZoneMetricsReply, ReadZoneMetricsRequest, ResolveZoneIdReply, ResolveZoneIdRequest,
|
||||||
SnoopIdmReply, SnoopIdmRequest, WatchEventsReply, WatchEventsRequest, ZoneConsoleReply,
|
SnoopIdmReply, SnoopIdmRequest, UpdateZoneResourcesReply, UpdateZoneResourcesRequest,
|
||||||
ZoneConsoleRequest,
|
WatchEventsReply, WatchEventsRequest, ZoneConsoleReply, ZoneConsoleRequest,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
@ -165,6 +166,7 @@ impl ControlService for DaemonControlService {
|
|||||||
network_status: None,
|
network_status: None,
|
||||||
exit_status: None,
|
exit_status: None,
|
||||||
error_status: None,
|
error_status: None,
|
||||||
|
resource_status: None,
|
||||||
host: self.glt.host_uuid().to_string(),
|
host: self.glt.host_uuid().to_string(),
|
||||||
domid: u32::MAX,
|
domid: u32::MAX,
|
||||||
}),
|
}),
|
||||||
@ -224,6 +226,7 @@ impl ControlService for DaemonControlService {
|
|||||||
.collect(),
|
.collect(),
|
||||||
command: task.command,
|
command: task.command,
|
||||||
working_directory: task.working_directory,
|
working_directory: task.working_directory,
|
||||||
|
tty: task.tty,
|
||||||
})),
|
})),
|
||||||
})),
|
})),
|
||||||
};
|
};
|
||||||
@ -241,11 +244,12 @@ impl ControlService for DaemonControlService {
|
|||||||
}.into());
|
}.into());
|
||||||
|
|
||||||
if let Ok(update) = update {
|
if let Ok(update) = update {
|
||||||
if !update.data.is_empty() {
|
if !update.stdin.is_empty() {
|
||||||
let _ = handle.update(IdmRequest {
|
let _ = handle.update(IdmRequest {
|
||||||
request: Some(IdmRequestType::ExecStream(ExecStreamRequestUpdate {
|
request: Some(IdmRequestType::ExecStream(ExecStreamRequestUpdate {
|
||||||
update: Some(Update::Stdin(ExecStreamRequestStdin {
|
update: Some(Update::Stdin(ExecStreamRequestStdin {
|
||||||
data: update.data,
|
data: update.stdin,
|
||||||
|
closed: update.stdin_closed,
|
||||||
})),
|
})),
|
||||||
}))}).await;
|
}))}).await;
|
||||||
}
|
}
|
||||||
@ -261,7 +265,7 @@ impl ControlService for DaemonControlService {
|
|||||||
error: update.error,
|
error: update.error,
|
||||||
exit_code: update.exit_code,
|
exit_code: update.exit_code,
|
||||||
stdout: update.stdout,
|
stdout: update.stdout,
|
||||||
stderr: update.stderr
|
stderr: update.stderr,
|
||||||
};
|
};
|
||||||
yield reply;
|
yield reply;
|
||||||
},
|
},
|
||||||
@ -623,4 +627,87 @@ impl ControlService for DaemonControlService {
|
|||||||
zone: zone.cloned(),
|
zone: zone.cloned(),
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async fn update_zone_resources(
|
||||||
|
&self,
|
||||||
|
request: Request<UpdateZoneResourcesRequest>,
|
||||||
|
) -> Result<Response<UpdateZoneResourcesReply>, Status> {
|
||||||
|
let request = request.into_inner();
|
||||||
|
let uuid = Uuid::from_str(&request.zone_id).map_err(|error| ApiError {
|
||||||
|
message: error.to_string(),
|
||||||
|
})?;
|
||||||
|
let Some(mut zone) = self.zones.read(uuid).await.map_err(ApiError::from)? else {
|
||||||
|
return Err(ApiError {
|
||||||
|
message: "zone not found".to_string(),
|
||||||
|
}
|
||||||
|
.into());
|
||||||
|
};
|
||||||
|
|
||||||
|
let Some(ref mut status) = zone.status else {
|
||||||
|
return Err(ApiError {
|
||||||
|
message: "zone state not available".to_string(),
|
||||||
|
}
|
||||||
|
.into());
|
||||||
|
};
|
||||||
|
|
||||||
|
if status.state() != ZoneState::Created {
|
||||||
|
return Err(ApiError {
|
||||||
|
message: "zone is in an invalid state".to_string(),
|
||||||
|
}
|
||||||
|
.into());
|
||||||
|
}
|
||||||
|
|
||||||
|
if status.domid == 0 || status.domid == u32::MAX {
|
||||||
|
return Err(ApiError {
|
||||||
|
message: "zone domid is invalid".to_string(),
|
||||||
|
}
|
||||||
|
.into());
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut resources = request.resources.unwrap_or_default();
|
||||||
|
if resources.target_memory > resources.max_memory {
|
||||||
|
resources.max_memory = resources.target_memory;
|
||||||
|
}
|
||||||
|
|
||||||
|
if resources.target_cpus < 1 {
|
||||||
|
resources.target_cpus = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
let initial_resources = zone
|
||||||
|
.spec
|
||||||
|
.clone()
|
||||||
|
.unwrap_or_default()
|
||||||
|
.initial_resources
|
||||||
|
.unwrap_or_default();
|
||||||
|
if resources.target_cpus > initial_resources.max_cpus {
|
||||||
|
resources.target_cpus = initial_resources.max_cpus;
|
||||||
|
}
|
||||||
|
resources.max_cpus = initial_resources.max_cpus;
|
||||||
|
|
||||||
|
self.runtime
|
||||||
|
.set_memory_resources(
|
||||||
|
status.domid,
|
||||||
|
resources.target_memory * 1024 * 1024,
|
||||||
|
resources.max_memory * 1024 * 1024,
|
||||||
|
)
|
||||||
|
.await
|
||||||
|
.map_err(|error| ApiError {
|
||||||
|
message: format!("failed to set memory resources: {}", error),
|
||||||
|
})?;
|
||||||
|
self.runtime
|
||||||
|
.set_cpu_resources(status.domid, resources.target_cpus)
|
||||||
|
.await
|
||||||
|
.map_err(|error| ApiError {
|
||||||
|
message: format!("failed to set cpu resources: {}", error),
|
||||||
|
})?;
|
||||||
|
status.resource_status = Some(ZoneResourceStatus {
|
||||||
|
active_resources: Some(resources),
|
||||||
|
});
|
||||||
|
|
||||||
|
self.zones
|
||||||
|
.update(uuid, zone)
|
||||||
|
.await
|
||||||
|
.map_err(ApiError::from)?;
|
||||||
|
Ok(Response::new(UpdateZoneResourcesReply {}))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -137,6 +137,7 @@ impl DaemonEventGenerator {
|
|||||||
network_status: zone.status.clone().unwrap_or_default().network_status,
|
network_status: zone.status.clone().unwrap_or_default().network_status,
|
||||||
exit_status: Some(ZoneExitStatus { code }),
|
exit_status: Some(ZoneExitStatus { code }),
|
||||||
error_status: None,
|
error_status: None,
|
||||||
|
resource_status: zone.status.clone().unwrap_or_default().resource_status,
|
||||||
host: zone.status.clone().map(|x| x.host).unwrap_or_default(),
|
host: zone.status.clone().map(|x| x.host).unwrap_or_default(),
|
||||||
domid: zone.status.clone().map(|x| x.domid).unwrap_or(u32::MAX),
|
domid: zone.status.clone().map(|x| x.domid).unwrap_or(u32::MAX),
|
||||||
});
|
});
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
use anyhow::{anyhow, Result};
|
use anyhow::{anyhow, Result};
|
||||||
use futures::StreamExt;
|
use futures::StreamExt;
|
||||||
use krata::launchcfg::LaunchPackedFormat;
|
use krata::launchcfg::LaunchPackedFormat;
|
||||||
use krata::v1::common::ZoneOciImageSpec;
|
|
||||||
use krata::v1::common::{OciImageFormat, Zone, ZoneState, ZoneStatus};
|
use krata::v1::common::{OciImageFormat, Zone, ZoneState, ZoneStatus};
|
||||||
|
use krata::v1::common::{ZoneOciImageSpec, ZoneResourceStatus};
|
||||||
use krataoci::packer::{service::OciPackerService, OciPackedFormat};
|
use krataoci::packer::{service::OciPackerService, OciPackedFormat};
|
||||||
use kratart::launch::{PciBdf, PciDevice, PciRdmReservePolicy, ZoneLaunchNetwork};
|
use kratart::launch::{PciBdf, PciDevice, PciRdmReservePolicy, ZoneLaunchNetwork};
|
||||||
use kratart::{launch::ZoneLaunchRequest, Runtime};
|
use kratart::{launch::ZoneLaunchRequest, Runtime};
|
||||||
@ -76,7 +76,7 @@ impl ZoneCreator<'_> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub async fn create(&self, uuid: Uuid, zone: &mut Zone) -> Result<ZoneReconcilerResult> {
|
pub async fn create(&self, uuid: Uuid, zone: &mut Zone) -> Result<ZoneReconcilerResult> {
|
||||||
let Some(ref spec) = zone.spec else {
|
let Some(ref mut spec) = zone.spec else {
|
||||||
return Err(anyhow!("zone spec not specified"));
|
return Err(anyhow!("zone spec not specified"));
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -176,6 +176,14 @@ impl ZoneCreator<'_> {
|
|||||||
|
|
||||||
let reservation = self.ip_assignment.assign(uuid).await?;
|
let reservation = self.ip_assignment.assign(uuid).await?;
|
||||||
|
|
||||||
|
let mut initial_resources = spec.initial_resources.unwrap_or_default();
|
||||||
|
if initial_resources.target_cpus < 1 {
|
||||||
|
initial_resources.target_cpus = 1;
|
||||||
|
}
|
||||||
|
if initial_resources.target_cpus > initial_resources.max_cpus {
|
||||||
|
initial_resources.max_cpus = initial_resources.target_cpus;
|
||||||
|
}
|
||||||
|
spec.initial_resources = Some(initial_resources);
|
||||||
let info = self
|
let info = self
|
||||||
.runtime
|
.runtime
|
||||||
.launch(ZoneLaunchRequest {
|
.launch(ZoneLaunchRequest {
|
||||||
@ -189,8 +197,10 @@ impl ZoneCreator<'_> {
|
|||||||
image,
|
image,
|
||||||
kernel,
|
kernel,
|
||||||
initrd,
|
initrd,
|
||||||
vcpus: spec.cpus,
|
target_cpus: initial_resources.target_cpus,
|
||||||
mem: spec.mem,
|
max_cpus: initial_resources.max_cpus,
|
||||||
|
max_memory: initial_resources.max_memory,
|
||||||
|
target_memory: initial_resources.target_memory,
|
||||||
pcis,
|
pcis,
|
||||||
env: task
|
env: task
|
||||||
.environment
|
.environment
|
||||||
@ -219,6 +229,9 @@ impl ZoneCreator<'_> {
|
|||||||
network_status: Some(ip_reservation_to_network_status(&reservation)),
|
network_status: Some(ip_reservation_to_network_status(&reservation)),
|
||||||
exit_status: None,
|
exit_status: None,
|
||||||
error_status: None,
|
error_status: None,
|
||||||
|
resource_status: Some(ZoneResourceStatus {
|
||||||
|
active_resources: Some(initial_resources),
|
||||||
|
}),
|
||||||
host: self.zlt.host_uuid().to_string(),
|
host: self.zlt.host_uuid().to_string(),
|
||||||
domid: info.domid,
|
domid: info.domid,
|
||||||
});
|
});
|
||||||
|
@ -328,6 +328,7 @@ impl ZoneReconciler {
|
|||||||
network_status: None,
|
network_status: None,
|
||||||
exit_status: None,
|
exit_status: None,
|
||||||
error_status: None,
|
error_status: None,
|
||||||
|
resource_status: None,
|
||||||
host: self.zlt.host_uuid().to_string(),
|
host: self.zlt.host_uuid().to_string(),
|
||||||
domid: domid.unwrap_or(u32::MAX),
|
domid: domid.unwrap_or(u32::MAX),
|
||||||
});
|
});
|
||||||
|
@ -45,10 +45,12 @@ message ExecStreamRequestStart {
|
|||||||
repeated ExecEnvVar environment = 1;
|
repeated ExecEnvVar environment = 1;
|
||||||
repeated string command = 2;
|
repeated string command = 2;
|
||||||
string working_directory = 3;
|
string working_directory = 3;
|
||||||
|
bool tty = 4;
|
||||||
}
|
}
|
||||||
|
|
||||||
message ExecStreamRequestStdin {
|
message ExecStreamRequestStdin {
|
||||||
bytes data = 1;
|
bytes data = 1;
|
||||||
|
bool closed = 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
message ExecStreamRequestUpdate {
|
message ExecStreamRequestUpdate {
|
||||||
|
@ -21,11 +21,17 @@ message ZoneSpec {
|
|||||||
ZoneImageSpec kernel = 3;
|
ZoneImageSpec kernel = 3;
|
||||||
// If not specified, defaults to the daemon default initrd.
|
// If not specified, defaults to the daemon default initrd.
|
||||||
ZoneImageSpec initrd = 4;
|
ZoneImageSpec initrd = 4;
|
||||||
uint32 cpus = 5;
|
ZoneResourceSpec initial_resources = 5;
|
||||||
uint64 mem = 6;
|
ZoneTaskSpec task = 6;
|
||||||
ZoneTaskSpec task = 7;
|
repeated ZoneSpecAnnotation annotations = 7;
|
||||||
repeated ZoneSpecAnnotation annotations = 8;
|
repeated ZoneSpecDevice devices = 8;
|
||||||
repeated ZoneSpecDevice devices = 9;
|
}
|
||||||
|
|
||||||
|
message ZoneResourceSpec {
|
||||||
|
uint64 max_memory = 1;
|
||||||
|
uint64 target_memory = 2;
|
||||||
|
uint32 max_cpus = 3;
|
||||||
|
uint32 target_cpus = 4;
|
||||||
}
|
}
|
||||||
|
|
||||||
message ZoneImageSpec {
|
message ZoneImageSpec {
|
||||||
@ -51,6 +57,7 @@ message ZoneTaskSpec {
|
|||||||
repeated ZoneTaskSpecEnvVar environment = 1;
|
repeated ZoneTaskSpecEnvVar environment = 1;
|
||||||
repeated string command = 2;
|
repeated string command = 2;
|
||||||
string working_directory = 3;
|
string working_directory = 3;
|
||||||
|
bool tty = 4;
|
||||||
}
|
}
|
||||||
|
|
||||||
message ZoneTaskSpecEnvVar {
|
message ZoneTaskSpecEnvVar {
|
||||||
@ -74,6 +81,7 @@ message ZoneStatus {
|
|||||||
ZoneErrorStatus error_status = 4;
|
ZoneErrorStatus error_status = 4;
|
||||||
string host = 5;
|
string host = 5;
|
||||||
uint32 domid = 6;
|
uint32 domid = 6;
|
||||||
|
ZoneResourceStatus resource_status = 7;
|
||||||
}
|
}
|
||||||
|
|
||||||
enum ZoneState {
|
enum ZoneState {
|
||||||
@ -103,6 +111,10 @@ message ZoneErrorStatus {
|
|||||||
string message = 1;
|
string message = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
message ZoneResourceStatus {
|
||||||
|
ZoneResourceSpec active_resources = 1;
|
||||||
|
}
|
||||||
|
|
||||||
message ZoneMetricNode {
|
message ZoneMetricNode {
|
||||||
string name = 1;
|
string name = 1;
|
||||||
google.protobuf.Value value = 2;
|
google.protobuf.Value value = 2;
|
||||||
|
@ -26,6 +26,8 @@ service ControlService {
|
|||||||
|
|
||||||
rpc GetZone(GetZoneRequest) returns (GetZoneReply);
|
rpc GetZone(GetZoneRequest) returns (GetZoneReply);
|
||||||
|
|
||||||
|
rpc UpdateZoneResources(UpdateZoneResourcesRequest) returns (UpdateZoneResourcesReply);
|
||||||
|
|
||||||
rpc ListZones(ListZonesRequest) returns (ListZonesReply);
|
rpc ListZones(ListZonesRequest) returns (ListZonesReply);
|
||||||
|
|
||||||
rpc AttachZoneConsole(stream ZoneConsoleRequest) returns (stream ZoneConsoleReply);
|
rpc AttachZoneConsole(stream ZoneConsoleRequest) returns (stream ZoneConsoleReply);
|
||||||
@ -82,7 +84,8 @@ message ListZonesReply {
|
|||||||
message ExecInsideZoneRequest {
|
message ExecInsideZoneRequest {
|
||||||
string zone_id = 1;
|
string zone_id = 1;
|
||||||
krata.v1.common.ZoneTaskSpec task = 2;
|
krata.v1.common.ZoneTaskSpec task = 2;
|
||||||
bytes data = 3;
|
bytes stdin = 3;
|
||||||
|
bool stdin_closed = 4;
|
||||||
}
|
}
|
||||||
|
|
||||||
message ExecInsideZoneReply {
|
message ExecInsideZoneReply {
|
||||||
@ -242,3 +245,10 @@ message SetHostPowerManagementPolicyRequest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
message SetHostPowerManagementPolicyReply {}
|
message SetHostPowerManagementPolicyReply {}
|
||||||
|
|
||||||
|
message UpdateZoneResourcesRequest {
|
||||||
|
string zone_id = 1;
|
||||||
|
krata.v1.common.ZoneResourceSpec resources = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
message UpdateZoneResourcesReply {}
|
||||||
|
@ -16,7 +16,7 @@ clap = { workspace = true }
|
|||||||
env_logger = { workspace = true }
|
env_logger = { workspace = true }
|
||||||
etherparse = { workspace = true }
|
etherparse = { workspace = true }
|
||||||
futures = { workspace = true }
|
futures = { workspace = true }
|
||||||
krata = { path = "../krata", version = "^0.0.16" }
|
krata = { path = "../krata", version = "^0.0.17" }
|
||||||
krata-advmac = { workspace = true }
|
krata-advmac = { workspace = true }
|
||||||
libc = { workspace = true }
|
libc = { workspace = true }
|
||||||
log = { workspace = true }
|
log = { workspace = true }
|
||||||
|
@ -12,20 +12,20 @@ resolver = "2"
|
|||||||
anyhow = { workspace = true }
|
anyhow = { workspace = true }
|
||||||
backhand = { workspace = true }
|
backhand = { workspace = true }
|
||||||
ipnetwork = { workspace = true }
|
ipnetwork = { workspace = true }
|
||||||
krata = { path = "../krata", version = "^0.0.16" }
|
krata = { path = "../krata", version = "^0.0.17" }
|
||||||
krata-advmac = { workspace = true }
|
krata-advmac = { workspace = true }
|
||||||
krata-oci = { path = "../oci", version = "^0.0.16" }
|
krata-oci = { path = "../oci", version = "^0.0.17" }
|
||||||
log = { workspace = true }
|
log = { workspace = true }
|
||||||
serde_json = { workspace = true }
|
serde_json = { workspace = true }
|
||||||
tokio = { workspace = true }
|
tokio = { workspace = true }
|
||||||
uuid = { workspace = true }
|
uuid = { workspace = true }
|
||||||
krata-loopdev = { path = "../loopdev", version = "^0.0.16" }
|
krata-loopdev = { path = "../loopdev", version = "^0.0.17" }
|
||||||
krata-xencall = { path = "../xen/xencall", version = "^0.0.16" }
|
krata-xencall = { path = "../xen/xencall", version = "^0.0.17" }
|
||||||
krata-xenclient = { path = "../xen/xenclient", version = "^0.0.16" }
|
krata-xenclient = { path = "../xen/xenclient", version = "^0.0.17" }
|
||||||
krata-xenevtchn = { path = "../xen/xenevtchn", version = "^0.0.16" }
|
krata-xenevtchn = { path = "../xen/xenevtchn", version = "^0.0.17" }
|
||||||
krata-xengnt = { path = "../xen/xengnt", version = "^0.0.16" }
|
krata-xengnt = { path = "../xen/xengnt", version = "^0.0.17" }
|
||||||
krata-xenplatform = { path = "../xen/xenplatform", version = "^0.0.16" }
|
krata-xenplatform = { path = "../xen/xenplatform", version = "^0.0.17" }
|
||||||
krata-xenstore = { path = "../xen/xenstore", version = "^0.0.16" }
|
krata-xenstore = { path = "../xen/xenstore", version = "^0.0.17" }
|
||||||
walkdir = { workspace = true }
|
walkdir = { workspace = true }
|
||||||
indexmap = { workspace = true }
|
indexmap = { workspace = true }
|
||||||
|
|
||||||
|
@ -30,8 +30,10 @@ pub struct ZoneLaunchRequest {
|
|||||||
pub initrd: Vec<u8>,
|
pub initrd: Vec<u8>,
|
||||||
pub uuid: Option<Uuid>,
|
pub uuid: Option<Uuid>,
|
||||||
pub name: Option<String>,
|
pub name: Option<String>,
|
||||||
pub vcpus: u32,
|
pub target_cpus: u32,
|
||||||
pub mem: u64,
|
pub max_cpus: u32,
|
||||||
|
pub target_memory: u64,
|
||||||
|
pub max_memory: u64,
|
||||||
pub env: HashMap<String, String>,
|
pub env: HashMap<String, String>,
|
||||||
pub run: Option<Vec<String>>,
|
pub run: Option<Vec<String>>,
|
||||||
pub pcis: Vec<PciDevice>,
|
pub pcis: Vec<PciDevice>,
|
||||||
@ -194,8 +196,10 @@ impl ZoneLauncher {
|
|||||||
|
|
||||||
let config = DomainConfig {
|
let config = DomainConfig {
|
||||||
base: BaseDomainConfig {
|
base: BaseDomainConfig {
|
||||||
max_vcpus: request.vcpus,
|
max_vcpus: request.max_cpus,
|
||||||
mem_mb: request.mem,
|
target_vcpus: request.target_cpus,
|
||||||
|
max_mem_mb: request.max_memory,
|
||||||
|
target_mem_mb: request.target_memory,
|
||||||
kernel: request.kernel,
|
kernel: request.kernel,
|
||||||
initrd: request.initrd,
|
initrd: request.initrd,
|
||||||
cmdline,
|
cmdline,
|
||||||
|
@ -1,11 +1,11 @@
|
|||||||
use std::{fs, path::PathBuf, str::FromStr, sync::Arc};
|
|
||||||
|
|
||||||
use anyhow::{anyhow, Result};
|
use anyhow::{anyhow, Result};
|
||||||
use krataloopdev::LoopControl;
|
use krataloopdev::LoopControl;
|
||||||
|
use std::{fs, path::PathBuf, str::FromStr, sync::Arc};
|
||||||
use tokio::sync::Semaphore;
|
use tokio::sync::Semaphore;
|
||||||
use uuid::Uuid;
|
use uuid::Uuid;
|
||||||
|
|
||||||
use xenclient::XenClient;
|
use xenclient::XenClient;
|
||||||
|
use xenplatform::domain::XEN_EXTRA_MEMORY_KB;
|
||||||
use xenstore::{XsdClient, XsdInterface};
|
use xenstore::{XsdClient, XsdInterface};
|
||||||
|
|
||||||
use self::{
|
use self::{
|
||||||
@ -226,6 +226,65 @@ impl Runtime {
|
|||||||
Ok(uuid)
|
Ok(uuid)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub async fn set_memory_resources(
|
||||||
|
&self,
|
||||||
|
domid: u32,
|
||||||
|
target_memory_bytes: u64,
|
||||||
|
max_memory_bytes: u64,
|
||||||
|
) -> Result<()> {
|
||||||
|
let mut max_memory_bytes = max_memory_bytes + (XEN_EXTRA_MEMORY_KB * 1024);
|
||||||
|
if target_memory_bytes > max_memory_bytes {
|
||||||
|
max_memory_bytes = target_memory_bytes + (XEN_EXTRA_MEMORY_KB * 1024);
|
||||||
|
}
|
||||||
|
|
||||||
|
self.context
|
||||||
|
.xen
|
||||||
|
.call
|
||||||
|
.set_max_mem(domid, max_memory_bytes / 1024)
|
||||||
|
.await?;
|
||||||
|
let domain_path = self.context.xen.store.get_domain_path(domid).await?;
|
||||||
|
let tx = self.context.xen.store.transaction().await?;
|
||||||
|
let max_memory_path = format!("{}/memory/static-max", domain_path);
|
||||||
|
tx.write_string(max_memory_path, &(max_memory_bytes / 1024).to_string())
|
||||||
|
.await?;
|
||||||
|
let target_memory_path = format!("{}/memory/target", domain_path);
|
||||||
|
tx.write_string(
|
||||||
|
target_memory_path,
|
||||||
|
&(target_memory_bytes / 1024).to_string(),
|
||||||
|
)
|
||||||
|
.await?;
|
||||||
|
tx.commit().await?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn set_cpu_resources(&self, domid: u32, target_cpus: u32) -> Result<()> {
|
||||||
|
let domain_path = self.context.xen.store.get_domain_path(domid).await?;
|
||||||
|
let cpus = self
|
||||||
|
.context
|
||||||
|
.xen
|
||||||
|
.store
|
||||||
|
.list(&format!("{}/cpu", domain_path))
|
||||||
|
.await?;
|
||||||
|
let tx = self.context.xen.store.transaction().await?;
|
||||||
|
for cpu in cpus {
|
||||||
|
let Some(id) = cpu.parse::<u32>().ok() else {
|
||||||
|
continue;
|
||||||
|
};
|
||||||
|
let available = if id >= target_cpus {
|
||||||
|
"offline"
|
||||||
|
} else {
|
||||||
|
"online"
|
||||||
|
};
|
||||||
|
tx.write_string(
|
||||||
|
format!("{}/cpu/{}/availability", domain_path, id),
|
||||||
|
available,
|
||||||
|
)
|
||||||
|
.await?;
|
||||||
|
}
|
||||||
|
tx.commit().await?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
pub async fn list(&self) -> Result<Vec<ZoneInfo>> {
|
pub async fn list(&self) -> Result<Vec<ZoneInfo>> {
|
||||||
self.context.list().await
|
self.context.list().await
|
||||||
}
|
}
|
||||||
|
@ -13,9 +13,9 @@ async-trait = { workspace = true }
|
|||||||
indexmap = { workspace = true }
|
indexmap = { workspace = true }
|
||||||
libc = { workspace = true }
|
libc = { workspace = true }
|
||||||
log = { workspace = true }
|
log = { workspace = true }
|
||||||
krata-xencall = { path = "../xencall", version = "^0.0.16" }
|
krata-xencall = { path = "../xencall", version = "^0.0.17" }
|
||||||
krata-xenplatform = { path = "../xenplatform", version = "^0.0.16" }
|
krata-xenplatform = { path = "../xenplatform", version = "^0.0.17" }
|
||||||
krata-xenstore = { path = "../xenstore", version = "^0.0.16" }
|
krata-xenstore = { path = "../xenstore", version = "^0.0.17" }
|
||||||
regex = { workspace = true }
|
regex = { workspace = true }
|
||||||
thiserror = { workspace = true }
|
thiserror = { workspace = true }
|
||||||
tokio = { workspace = true }
|
tokio = { workspace = true }
|
||||||
|
@ -27,7 +27,9 @@ async fn main() -> Result<()> {
|
|||||||
base: BaseDomainConfig {
|
base: BaseDomainConfig {
|
||||||
uuid: Uuid::new_v4(),
|
uuid: Uuid::new_v4(),
|
||||||
max_vcpus: 1,
|
max_vcpus: 1,
|
||||||
mem_mb: 512,
|
target_vcpus: 1,
|
||||||
|
max_mem_mb: 512,
|
||||||
|
target_mem_mb: 512,
|
||||||
enable_iommu: true,
|
enable_iommu: true,
|
||||||
kernel: fs::read(&kernel_image_path).await?,
|
kernel: fs::read(&kernel_image_path).await?,
|
||||||
initrd: fs::read(&initrd_path).await?,
|
initrd: fs::read(&initrd_path).await?,
|
||||||
|
@ -156,13 +156,13 @@ impl ClientTransaction {
|
|||||||
self.tx
|
self.tx
|
||||||
.write_string(
|
.write_string(
|
||||||
format!("{}/memory/static-max", self.dom_path).as_str(),
|
format!("{}/memory/static-max", self.dom_path).as_str(),
|
||||||
&(base.mem_mb * 1024).to_string(),
|
&(base.max_mem_mb * 1024).to_string(),
|
||||||
)
|
)
|
||||||
.await?;
|
.await?;
|
||||||
self.tx
|
self.tx
|
||||||
.write_string(
|
.write_string(
|
||||||
format!("{}/memory/target", self.dom_path).as_str(),
|
format!("{}/memory/target", self.dom_path).as_str(),
|
||||||
&(base.mem_mb * 1024).to_string(),
|
&(base.target_mem_mb * 1024).to_string(),
|
||||||
)
|
)
|
||||||
.await?;
|
.await?;
|
||||||
self.tx
|
self.tx
|
||||||
@ -194,7 +194,16 @@ impl ClientTransaction {
|
|||||||
self.tx.mkdir(&path).await?;
|
self.tx.mkdir(&path).await?;
|
||||||
self.tx.set_perms(&path, ro_perm).await?;
|
self.tx.set_perms(&path, ro_perm).await?;
|
||||||
let path = format!("{}/cpu/{}/availability", self.dom_path, i);
|
let path = format!("{}/cpu/{}/availability", self.dom_path, i);
|
||||||
self.tx.write_string(&path, "online").await?;
|
self.tx
|
||||||
|
.write_string(
|
||||||
|
&path,
|
||||||
|
if i < base.target_vcpus {
|
||||||
|
"online"
|
||||||
|
} else {
|
||||||
|
"offline"
|
||||||
|
},
|
||||||
|
)
|
||||||
|
.await?;
|
||||||
self.tx.set_perms(&path, ro_perm).await?;
|
self.tx.set_perms(&path, ro_perm).await?;
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
|
@ -16,7 +16,7 @@ flate2 = { workspace = true }
|
|||||||
indexmap = { workspace = true }
|
indexmap = { workspace = true }
|
||||||
libc = { workspace = true }
|
libc = { workspace = true }
|
||||||
log = { workspace = true }
|
log = { workspace = true }
|
||||||
krata-xencall = { path = "../xencall", version = "^0.0.16" }
|
krata-xencall = { path = "../xencall", version = "^0.0.17" }
|
||||||
memchr = { workspace = true }
|
memchr = { workspace = true }
|
||||||
nix = { workspace = true }
|
nix = { workspace = true }
|
||||||
regex = { workspace = true }
|
regex = { workspace = true }
|
||||||
|
@ -162,11 +162,13 @@ impl<I: BootImageLoader, P: BootSetupPlatform> BootSetup<I, P> {
|
|||||||
pub async fn initialize(
|
pub async fn initialize(
|
||||||
&mut self,
|
&mut self,
|
||||||
initrd: &[u8],
|
initrd: &[u8],
|
||||||
mem_mb: u64,
|
target_mem_mb: u64,
|
||||||
|
max_mem_mb: u64,
|
||||||
max_vcpus: u32,
|
max_vcpus: u32,
|
||||||
cmdline: &str,
|
cmdline: &str,
|
||||||
) -> Result<BootDomain> {
|
) -> Result<BootDomain> {
|
||||||
let total_pages = mem_mb << (20 - self.platform.page_shift());
|
let target_pages = target_mem_mb << (20 - self.platform.page_shift());
|
||||||
|
let total_pages = max_mem_mb << (20 - self.platform.page_shift());
|
||||||
let image_info = self.image_loader.parse(self.platform.hvm()).await?;
|
let image_info = self.image_loader.parse(self.platform.hvm()).await?;
|
||||||
let mut domain = BootDomain {
|
let mut domain = BootDomain {
|
||||||
domid: self.domid,
|
domid: self.domid,
|
||||||
@ -175,7 +177,7 @@ impl<I: BootImageLoader, P: BootSetupPlatform> BootSetup<I, P> {
|
|||||||
virt_pgtab_end: 0,
|
virt_pgtab_end: 0,
|
||||||
pfn_alloc_end: 0,
|
pfn_alloc_end: 0,
|
||||||
total_pages,
|
total_pages,
|
||||||
target_pages: total_pages,
|
target_pages,
|
||||||
page_size: self.platform.page_size(),
|
page_size: self.platform.page_size(),
|
||||||
image_info,
|
image_info,
|
||||||
console_evtchn: 0,
|
console_evtchn: 0,
|
||||||
|
@ -9,6 +9,8 @@ use xencall::XenCall;
|
|||||||
|
|
||||||
use crate::error::Result;
|
use crate::error::Result;
|
||||||
|
|
||||||
|
pub const XEN_EXTRA_MEMORY_KB: u64 = 2048;
|
||||||
|
|
||||||
pub struct BaseDomainManager<P: BootSetupPlatform> {
|
pub struct BaseDomainManager<P: BootSetupPlatform> {
|
||||||
call: XenCall,
|
call: XenCall,
|
||||||
pub platform: Arc<P>,
|
pub platform: Arc<P>,
|
||||||
@ -29,7 +31,7 @@ impl<P: BootSetupPlatform> BaseDomainManager<P> {
|
|||||||
let domid = self.call.create_domain(domain).await?;
|
let domid = self.call.create_domain(domain).await?;
|
||||||
self.call.set_max_vcpus(domid, config.max_vcpus).await?;
|
self.call.set_max_vcpus(domid, config.max_vcpus).await?;
|
||||||
self.call
|
self.call
|
||||||
.set_max_mem(domid, (config.mem_mb * 1024) + 2048)
|
.set_max_mem(domid, (config.max_mem_mb * 1024) + XEN_EXTRA_MEMORY_KB)
|
||||||
.await?;
|
.await?;
|
||||||
let loader = ElfImageLoader::load_file_kernel(&config.kernel)?;
|
let loader = ElfImageLoader::load_file_kernel(&config.kernel)?;
|
||||||
let platform = (*self.platform).clone();
|
let platform = (*self.platform).clone();
|
||||||
@ -37,7 +39,8 @@ impl<P: BootSetupPlatform> BaseDomainManager<P> {
|
|||||||
let mut domain = boot
|
let mut domain = boot
|
||||||
.initialize(
|
.initialize(
|
||||||
&config.initrd,
|
&config.initrd,
|
||||||
config.mem_mb,
|
config.target_mem_mb,
|
||||||
|
config.max_mem_mb,
|
||||||
config.max_vcpus,
|
config.max_vcpus,
|
||||||
&config.cmdline,
|
&config.cmdline,
|
||||||
)
|
)
|
||||||
@ -63,7 +66,9 @@ pub struct BaseDomainConfig {
|
|||||||
pub uuid: Uuid,
|
pub uuid: Uuid,
|
||||||
pub owner_domid: u32,
|
pub owner_domid: u32,
|
||||||
pub max_vcpus: u32,
|
pub max_vcpus: u32,
|
||||||
pub mem_mb: u64,
|
pub target_vcpus: u32,
|
||||||
|
pub max_mem_mb: u64,
|
||||||
|
pub target_mem_mb: u64,
|
||||||
pub kernel: Vec<u8>,
|
pub kernel: Vec<u8>,
|
||||||
pub initrd: Vec<u8>,
|
pub initrd: Vec<u8>,
|
||||||
pub cmdline: String,
|
pub cmdline: String,
|
||||||
|
@ -14,14 +14,15 @@ cgroups-rs = { workspace = true }
|
|||||||
env_logger = { workspace = true }
|
env_logger = { workspace = true }
|
||||||
futures = { workspace = true }
|
futures = { workspace = true }
|
||||||
ipnetwork = { workspace = true }
|
ipnetwork = { workspace = true }
|
||||||
krata = { path = "../krata", version = "^0.0.16" }
|
krata = { path = "../krata", version = "^0.0.17" }
|
||||||
krata-xenstore = { path = "../xen/xenstore", version = "^0.0.16" }
|
krata-xenstore = { path = "../xen/xenstore", version = "^0.0.17" }
|
||||||
libc = { workspace = true }
|
libc = { workspace = true }
|
||||||
log = { workspace = true }
|
log = { workspace = true }
|
||||||
nix = { workspace = true, features = ["ioctl", "process", "fs"] }
|
nix = { workspace = true, features = ["ioctl", "process", "fs"] }
|
||||||
oci-spec = { workspace = true }
|
oci-spec = { workspace = true }
|
||||||
path-absolutize = { workspace = true }
|
path-absolutize = { workspace = true }
|
||||||
platform-info = { workspace = true }
|
platform-info = { workspace = true }
|
||||||
|
pty-process = { workspace = true, features = ["async"] }
|
||||||
rtnetlink = { workspace = true }
|
rtnetlink = { workspace = true }
|
||||||
serde = { workspace = true }
|
serde = { workspace = true }
|
||||||
serde_json = { workspace = true }
|
serde_json = { workspace = true }
|
||||||
|
@ -1,12 +1,6 @@
|
|||||||
use std::{collections::HashMap, process::Stdio};
|
use std::{collections::HashMap, process::Stdio};
|
||||||
|
|
||||||
use anyhow::{anyhow, Result};
|
use anyhow::{anyhow, Result};
|
||||||
use tokio::{
|
|
||||||
io::{AsyncReadExt, AsyncWriteExt},
|
|
||||||
join,
|
|
||||||
process::Command,
|
|
||||||
};
|
|
||||||
|
|
||||||
use krata::idm::{
|
use krata::idm::{
|
||||||
client::IdmClientStreamResponseHandle,
|
client::IdmClientStreamResponseHandle,
|
||||||
internal::{
|
internal::{
|
||||||
@ -15,6 +9,14 @@ use krata::idm::{
|
|||||||
},
|
},
|
||||||
internal::{response::Response as ResponseType, Request, Response},
|
internal::{response::Response as ResponseType, Request, Response},
|
||||||
};
|
};
|
||||||
|
use libc::c_int;
|
||||||
|
use pty_process::{Pty, Size};
|
||||||
|
use tokio::process::Child;
|
||||||
|
use tokio::{
|
||||||
|
io::{AsyncReadExt, AsyncWriteExt},
|
||||||
|
join,
|
||||||
|
process::Command,
|
||||||
|
};
|
||||||
|
|
||||||
use crate::childwait::ChildWait;
|
use crate::childwait::ChildWait;
|
||||||
|
|
||||||
@ -52,7 +54,7 @@ impl ZoneExecTask {
|
|||||||
if !env.contains_key("PATH") {
|
if !env.contains_key("PATH") {
|
||||||
env.insert(
|
env.insert(
|
||||||
"PATH".to_string(),
|
"PATH".to_string(),
|
||||||
"/bin:/usr/bin:/usr/local/bin".to_string(),
|
"/bin:/usr/bin:/usr/local/bin:/sbin:/usr/sbin".to_string(),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -63,112 +65,196 @@ impl ZoneExecTask {
|
|||||||
};
|
};
|
||||||
|
|
||||||
let mut wait_subscription = self.wait.subscribe().await?;
|
let mut wait_subscription = self.wait.subscribe().await?;
|
||||||
let mut child = Command::new(exe)
|
|
||||||
.args(cmd)
|
|
||||||
.envs(env)
|
|
||||||
.current_dir(dir)
|
|
||||||
.stdin(Stdio::piped())
|
|
||||||
.stdout(Stdio::piped())
|
|
||||||
.stderr(Stdio::piped())
|
|
||||||
.kill_on_drop(true)
|
|
||||||
.spawn()
|
|
||||||
.map_err(|error| anyhow!("failed to spawn: {}", error))?;
|
|
||||||
|
|
||||||
let pid = child.id().ok_or_else(|| anyhow!("pid is not provided"))?;
|
let code: c_int;
|
||||||
let mut stdin = child
|
if start.tty {
|
||||||
.stdin
|
let pty = Pty::new().map_err(|error| anyhow!("unable to allocate pty: {}", error))?;
|
||||||
.take()
|
pty.resize(Size::new(24, 80))?;
|
||||||
.ok_or_else(|| anyhow!("stdin was missing"))?;
|
let mut child = ChildDropGuard {
|
||||||
let mut stdout = child
|
inner: pty_process::Command::new(exe)
|
||||||
.stdout
|
.args(cmd)
|
||||||
.take()
|
.envs(env)
|
||||||
.ok_or_else(|| anyhow!("stdout was missing"))?;
|
.current_dir(dir)
|
||||||
let mut stderr = child
|
.spawn(
|
||||||
.stderr
|
&pty.pts()
|
||||||
.take()
|
.map_err(|error| anyhow!("unable to allocate pts: {}", error))?,
|
||||||
.ok_or_else(|| anyhow!("stderr was missing"))?;
|
)
|
||||||
|
.map_err(|error| anyhow!("failed to spawn: {}", error))?,
|
||||||
let stdout_handle = self.handle.clone();
|
kill: true,
|
||||||
let stdout_task = tokio::task::spawn(async move {
|
};
|
||||||
let mut stdout_buffer = vec![0u8; 8 * 1024];
|
let pid = child
|
||||||
loop {
|
.inner
|
||||||
let Ok(size) = stdout.read(&mut stdout_buffer).await else {
|
.id()
|
||||||
break;
|
.ok_or_else(|| anyhow!("pid is not provided"))?;
|
||||||
};
|
let (mut read, mut write) = pty.into_split();
|
||||||
if size > 0 {
|
let pty_read_handle = self.handle.clone();
|
||||||
let response = Response {
|
let pty_read_task = tokio::task::spawn(async move {
|
||||||
response: Some(ResponseType::ExecStream(ExecStreamResponseUpdate {
|
let mut stdout_buffer = vec![0u8; 8 * 1024];
|
||||||
exited: false,
|
loop {
|
||||||
exit_code: 0,
|
let Ok(size) = read.read(&mut stdout_buffer).await else {
|
||||||
error: String::new(),
|
break;
|
||||||
stdout: stdout_buffer[0..size].to_vec(),
|
|
||||||
stderr: vec![],
|
|
||||||
})),
|
|
||||||
};
|
};
|
||||||
let _ = stdout_handle.respond(response).await;
|
if size > 0 {
|
||||||
} else {
|
let response = Response {
|
||||||
break;
|
response: Some(ResponseType::ExecStream(ExecStreamResponseUpdate {
|
||||||
|
exited: false,
|
||||||
|
exit_code: 0,
|
||||||
|
error: String::new(),
|
||||||
|
stdout: stdout_buffer[0..size].to_vec(),
|
||||||
|
stderr: vec![],
|
||||||
|
})),
|
||||||
|
};
|
||||||
|
let _ = pty_read_handle.respond(response).await;
|
||||||
|
} else {
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
});
|
||||||
});
|
|
||||||
|
|
||||||
let stderr_handle = self.handle.clone();
|
let stdin_task = tokio::task::spawn(async move {
|
||||||
let stderr_task = tokio::task::spawn(async move {
|
loop {
|
||||||
let mut stderr_buffer = vec![0u8; 8 * 1024];
|
let Some(request) = receiver.recv().await else {
|
||||||
loop {
|
break;
|
||||||
let Ok(size) = stderr.read(&mut stderr_buffer).await else {
|
|
||||||
break;
|
|
||||||
};
|
|
||||||
if size > 0 {
|
|
||||||
let response = Response {
|
|
||||||
response: Some(ResponseType::ExecStream(ExecStreamResponseUpdate {
|
|
||||||
exited: false,
|
|
||||||
exit_code: 0,
|
|
||||||
error: String::new(),
|
|
||||||
stdout: vec![],
|
|
||||||
stderr: stderr_buffer[0..size].to_vec(),
|
|
||||||
})),
|
|
||||||
};
|
};
|
||||||
let _ = stderr_handle.respond(response).await;
|
|
||||||
} else {
|
let Some(RequestType::ExecStream(update)) = request.request else {
|
||||||
break;
|
continue;
|
||||||
|
};
|
||||||
|
|
||||||
|
let Some(Update::Stdin(update)) = update.update else {
|
||||||
|
continue;
|
||||||
|
};
|
||||||
|
|
||||||
|
if !update.data.is_empty() && write.write_all(&update.data).await.is_err() {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if update.closed {
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
});
|
||||||
});
|
|
||||||
|
|
||||||
let stdin_task = tokio::task::spawn(async move {
|
code = loop {
|
||||||
loop {
|
if let Ok(event) = wait_subscription.recv().await {
|
||||||
let Some(request) = receiver.recv().await else {
|
if event.pid.as_raw() as u32 == pid {
|
||||||
break;
|
break event.status;
|
||||||
};
|
}
|
||||||
|
|
||||||
let Some(RequestType::ExecStream(update)) = request.request else {
|
|
||||||
continue;
|
|
||||||
};
|
|
||||||
|
|
||||||
let Some(Update::Stdin(update)) = update.update else {
|
|
||||||
continue;
|
|
||||||
};
|
|
||||||
|
|
||||||
if stdin.write_all(&update.data).await.is_err() {
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
});
|
|
||||||
|
|
||||||
let data_task = tokio::task::spawn(async move {
|
child.kill = false;
|
||||||
let _ = join!(stdout_task, stderr_task);
|
|
||||||
|
let _ = join!(pty_read_task);
|
||||||
stdin_task.abort();
|
stdin_task.abort();
|
||||||
});
|
} else {
|
||||||
|
let mut child = Command::new(exe)
|
||||||
|
.args(cmd)
|
||||||
|
.envs(env)
|
||||||
|
.current_dir(dir)
|
||||||
|
.stdin(Stdio::piped())
|
||||||
|
.stdout(Stdio::piped())
|
||||||
|
.stderr(Stdio::piped())
|
||||||
|
.kill_on_drop(true)
|
||||||
|
.spawn()
|
||||||
|
.map_err(|error| anyhow!("failed to spawn: {}", error))?;
|
||||||
|
|
||||||
let code = loop {
|
let pid = child.id().ok_or_else(|| anyhow!("pid is not provided"))?;
|
||||||
if let Ok(event) = wait_subscription.recv().await {
|
let mut stdin = child
|
||||||
if event.pid.as_raw() as u32 == pid {
|
.stdin
|
||||||
break event.status;
|
.take()
|
||||||
|
.ok_or_else(|| anyhow!("stdin was missing"))?;
|
||||||
|
let mut stdout = child
|
||||||
|
.stdout
|
||||||
|
.take()
|
||||||
|
.ok_or_else(|| anyhow!("stdout was missing"))?;
|
||||||
|
let mut stderr = child
|
||||||
|
.stderr
|
||||||
|
.take()
|
||||||
|
.ok_or_else(|| anyhow!("stderr was missing"))?;
|
||||||
|
|
||||||
|
let stdout_handle = self.handle.clone();
|
||||||
|
let stdout_task = tokio::task::spawn(async move {
|
||||||
|
let mut stdout_buffer = vec![0u8; 8 * 1024];
|
||||||
|
loop {
|
||||||
|
let Ok(size) = stdout.read(&mut stdout_buffer).await else {
|
||||||
|
break;
|
||||||
|
};
|
||||||
|
if size > 0 {
|
||||||
|
let response = Response {
|
||||||
|
response: Some(ResponseType::ExecStream(ExecStreamResponseUpdate {
|
||||||
|
exited: false,
|
||||||
|
exit_code: 0,
|
||||||
|
error: String::new(),
|
||||||
|
stdout: stdout_buffer[0..size].to_vec(),
|
||||||
|
stderr: vec![],
|
||||||
|
})),
|
||||||
|
};
|
||||||
|
let _ = stdout_handle.respond(response).await;
|
||||||
|
} else {
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
});
|
||||||
};
|
|
||||||
data_task.await?;
|
let stderr_handle = self.handle.clone();
|
||||||
|
let stderr_task = tokio::task::spawn(async move {
|
||||||
|
let mut stderr_buffer = vec![0u8; 8 * 1024];
|
||||||
|
loop {
|
||||||
|
let Ok(size) = stderr.read(&mut stderr_buffer).await else {
|
||||||
|
break;
|
||||||
|
};
|
||||||
|
if size > 0 {
|
||||||
|
let response = Response {
|
||||||
|
response: Some(ResponseType::ExecStream(ExecStreamResponseUpdate {
|
||||||
|
exited: false,
|
||||||
|
exit_code: 0,
|
||||||
|
error: String::new(),
|
||||||
|
stdout: vec![],
|
||||||
|
stderr: stderr_buffer[0..size].to_vec(),
|
||||||
|
})),
|
||||||
|
};
|
||||||
|
let _ = stderr_handle.respond(response).await;
|
||||||
|
} else {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
let stdin_task = tokio::task::spawn(async move {
|
||||||
|
loop {
|
||||||
|
let Some(request) = receiver.recv().await else {
|
||||||
|
break;
|
||||||
|
};
|
||||||
|
|
||||||
|
let Some(RequestType::ExecStream(update)) = request.request else {
|
||||||
|
continue;
|
||||||
|
};
|
||||||
|
|
||||||
|
let Some(Update::Stdin(update)) = update.update else {
|
||||||
|
continue;
|
||||||
|
};
|
||||||
|
|
||||||
|
if stdin.write_all(&update.data).await.is_err() {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
let data_task = tokio::task::spawn(async move {
|
||||||
|
let _ = join!(stdout_task, stderr_task);
|
||||||
|
stdin_task.abort();
|
||||||
|
});
|
||||||
|
|
||||||
|
code = loop {
|
||||||
|
if let Ok(event) = wait_subscription.recv().await {
|
||||||
|
if event.pid.as_raw() as u32 == pid {
|
||||||
|
break event.status;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
data_task.await?;
|
||||||
|
}
|
||||||
let response = Response {
|
let response = Response {
|
||||||
response: Some(ResponseType::ExecStream(ExecStreamResponseUpdate {
|
response: Some(ResponseType::ExecStream(ExecStreamResponseUpdate {
|
||||||
exited: true,
|
exited: true,
|
||||||
@ -183,3 +269,16 @@ impl ZoneExecTask {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct ChildDropGuard {
|
||||||
|
pub inner: Child,
|
||||||
|
pub kill: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Drop for ChildDropGuard {
|
||||||
|
fn drop(&mut self) {
|
||||||
|
if self.kill {
|
||||||
|
drop(self.inner.start_kill());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -2,7 +2,7 @@ use std::{ops::Add, path::Path};
|
|||||||
|
|
||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
use krata::idm::internal::{MetricFormat, MetricNode};
|
use krata::idm::internal::{MetricFormat, MetricNode};
|
||||||
use sysinfo::Process;
|
use sysinfo::{Process, ProcessesToUpdate};
|
||||||
|
|
||||||
pub struct MetricsCollector {}
|
pub struct MetricsCollector {}
|
||||||
|
|
||||||
@ -38,7 +38,7 @@ impl MetricsCollector {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn collect_processes(&self, sysinfo: &mut sysinfo::System) -> Result<MetricNode> {
|
fn collect_processes(&self, sysinfo: &mut sysinfo::System) -> Result<MetricNode> {
|
||||||
sysinfo.refresh_processes();
|
sysinfo.refresh_processes(ProcessesToUpdate::All);
|
||||||
let mut processes = Vec::new();
|
let mut processes = Vec::new();
|
||||||
let mut sysinfo_processes = sysinfo.processes().values().collect::<Vec<_>>();
|
let mut sysinfo_processes = sysinfo.processes().values().collect::<Vec<_>>();
|
||||||
sysinfo_processes.sort_by_key(|x| x.pid());
|
sysinfo_processes.sort_by_key(|x| x.pid());
|
||||||
@ -70,7 +70,11 @@ impl MetricsCollector {
|
|||||||
metrics.push(MetricNode::raw_value("cwd", working_directory));
|
metrics.push(MetricNode::raw_value("cwd", working_directory));
|
||||||
}
|
}
|
||||||
|
|
||||||
let cmdline = process.cmd().to_vec();
|
let cmdline = process
|
||||||
|
.cmd()
|
||||||
|
.iter()
|
||||||
|
.map(|x| x.to_string_lossy().to_string())
|
||||||
|
.collect::<Vec<_>>();
|
||||||
metrics.push(MetricNode::raw_value("cmdline", cmdline));
|
metrics.push(MetricNode::raw_value("cmdline", cmdline));
|
||||||
metrics.push(MetricNode::structural(
|
metrics.push(MetricNode::structural(
|
||||||
"memory",
|
"memory",
|
||||||
|
131
doc/admin-guide/custom-kernels.md
Normal file
131
doc/admin-guide/custom-kernels.md
Normal file
@ -0,0 +1,131 @@
|
|||||||
|
Custom Kernels in krata
|
||||||
|
=======================
|
||||||
|
|
||||||
|
Krata supports using custom kernels instead of the default Edera-provided
|
||||||
|
kernel both on a system-wide and zone-wide basis. Krata also supports using
|
||||||
|
a custom host kernel, as long as it meets certain technical requirements.
|
||||||
|
|
||||||
|
System-wide default kernel for zones
|
||||||
|
------------------------------------
|
||||||
|
|
||||||
|
The standard system-wide default kernel for zones is stored in
|
||||||
|
`/var/lib/krata/zone/kernel` which is the kernel image that should be
|
||||||
|
booted for the zone, and `/var/lib/krata/zone/addons.squashfs`,
|
||||||
|
which contains a set of kernel modules that should be mounted in the
|
||||||
|
zone.
|
||||||
|
|
||||||
|
Zone-wide alternative kernels via OCI
|
||||||
|
-------------------------------------
|
||||||
|
|
||||||
|
Krata also supports fetching alternative kernel images for use in zones
|
||||||
|
via OCI repositories. These kernel images are distributed like any other
|
||||||
|
OCI image, but are not intended to be directly executed by an OCI runtime.
|
||||||
|
|
||||||
|
To select an alternative kernel, you can supply the `-k` option to the
|
||||||
|
`kratactl zone launch` command that specifies an OCI tag to pull the
|
||||||
|
alternative kernel image from.
|
||||||
|
|
||||||
|
OCI-based kernel image contents
|
||||||
|
-------------------------------
|
||||||
|
|
||||||
|
OCI-based kernel images contain the following files:
|
||||||
|
|
||||||
|
* `/kernel/image`: The kernel image itself.
|
||||||
|
|
||||||
|
* `/kernel/addons.squashfs`: A squashfs file containing the kernel
|
||||||
|
modules for a given kernel image.
|
||||||
|
|
||||||
|
* `/kernel/metadata`: A file containing the following metadata fields
|
||||||
|
in `KEY=VALUE` format:
|
||||||
|
- `KERNEL_ARCH`: The kernel architecture (`x86_64` or `aarch64`)
|
||||||
|
- `KERNEL_VERSION`: The kernel version
|
||||||
|
- `KERNEL_FLAVOR`: The kernel flavor (examples: `standard`, `dom0` or `openpax`)
|
||||||
|
- `KERNEL_CONFIG`: The digest for the relevant configuration file stored in the OCI
|
||||||
|
repository
|
||||||
|
- `KERNEL_TAGS`: The OCI tags this kernel image was originally built for
|
||||||
|
(example: `latest`)
|
||||||
|
|
||||||
|
Minimum requirements for a zone-wide/system-wide kernel
|
||||||
|
-------------------------------------------------------
|
||||||
|
|
||||||
|
The following configuration options must be set:
|
||||||
|
|
||||||
|
```
|
||||||
|
CONFIG_XEN=y
|
||||||
|
CONFIG_XEN_PV=y
|
||||||
|
CONFIG_XEN_512GB=y
|
||||||
|
CONFIG_XEN_PV_SMP=y
|
||||||
|
CONFIG_XEN_PVHVM=y
|
||||||
|
CONFIG_XEN_PVHVM_SMP=y
|
||||||
|
CONFIG_XEN_PVHVM_GUEST=y
|
||||||
|
CONFIG_XEN_SAVE_RESTORE=y
|
||||||
|
CONFIG_XEN_PVH=y
|
||||||
|
CONFIG_XEN_PV_MSR_SAFE=y
|
||||||
|
CONFIG_PCI_XEN=y
|
||||||
|
CONFIG_NET_9P_XEN=y
|
||||||
|
CONFIG_XEN_PCIDEV_FRONTEND=y
|
||||||
|
CONFIG_XEN_BLKDEV_FRONTEND=y
|
||||||
|
CONFIG_XEN_NETDEV_FRONTEND=y
|
||||||
|
CONFIG_INPUT_XEN_KBDDEV_FRONTEND=y
|
||||||
|
CONFIG_HVC_XEN=y
|
||||||
|
CONFIG_HVC_XEN_FRONTEND=y
|
||||||
|
CONFIG_XEN_FBDEV_FRONTEND=m
|
||||||
|
CONFIG_XEN_BALLOON=y
|
||||||
|
CONFIG_XEN_BALLOON_MEMORY_HOTPLUG=y
|
||||||
|
CONFIG_XEN_MEMORY_HOTPLUG_LIMIT=512
|
||||||
|
CONFIG_XEN_SCRUB_PAGES_DEFAULT=y
|
||||||
|
CONFIG_XEN_DEV_EVTCHN=y
|
||||||
|
CONFIG_XEN_BACKEND=y
|
||||||
|
CONFIG_XENFS=y
|
||||||
|
CONFIG_XEN_COMPAT_XENFS=y
|
||||||
|
CONFIG_XEN_SYS_HYPERVISOR=y
|
||||||
|
CONFIG_XEN_XENBUS_FRONTEND=y
|
||||||
|
CONFIG_SWIOTLB_XEN=y
|
||||||
|
CONFIG_XEN_HAVE_PVMMU=y
|
||||||
|
CONFIG_XEN_EFI=y
|
||||||
|
CONFIG_XEN_AUTO_XLATE=y
|
||||||
|
CONFIG_XEN_ACPI=y
|
||||||
|
CONFIG_XEN_HAVE_VPMU=y
|
||||||
|
CONFIG_XEN_GRANT_DMA_OPS=y
|
||||||
|
CONFIG_XEN_VIRTIO=y
|
||||||
|
```
|
||||||
|
|
||||||
|
It is possible to copy these options into a `.config` file and then use
|
||||||
|
`make olddefconfig` to build the rest of the kernel configuration, which
|
||||||
|
you can then use to build a kernel as desired.
|
||||||
|
|
||||||
|
The [kernels][edera-kernels] repository provides some example configurations
|
||||||
|
and can generate a Dockerfile which will build a kernel image.
|
||||||
|
|
||||||
|
[edera-kernels]: https://github.com/edera-dev/kernels
|
||||||
|
|
||||||
|
Minimum requirements for a host kernel
|
||||||
|
--------------------------------------
|
||||||
|
|
||||||
|
The configuration options above are also required for a host kernel.
|
||||||
|
In addition, the following options are also required:
|
||||||
|
|
||||||
|
```
|
||||||
|
CONFIG_XEN_PV_DOM0=y
|
||||||
|
CONFIG_XEN_DOM0=y
|
||||||
|
CONFIG_PCI_XEN=y
|
||||||
|
CONFIG_XEN_PCIDEV_BACKEND=y
|
||||||
|
CONFIG_XEN_BLKDEV_BACKEND=y
|
||||||
|
CONFIG_XEN_NETDEV_BACKEND=y
|
||||||
|
CONFIG_XEN_SCSI_BACKEND=y
|
||||||
|
CONFIG_XEN_PVCALLS_BACKEND=y
|
||||||
|
CONFIG_TCG_XEN=m
|
||||||
|
CONFIG_XEN_WDT=y
|
||||||
|
CONFIG_XEN_DEV_EVTCHN=y
|
||||||
|
CONFIG_XEN_GNTDEV=y
|
||||||
|
CONFIG_XEN_GRANT_DEV_ALLOC=y
|
||||||
|
CONFIG_XEN_GRANT_DMA_ALLOC=y
|
||||||
|
CONFIG_SWIOTLB_XEN=y
|
||||||
|
CONFIG_XEN_PRIVCMD=y
|
||||||
|
CONFIG_XEN_ACPI_PROCESSOR=y
|
||||||
|
CONFIG_XEN_MCE_LOG=y
|
||||||
|
```
|
||||||
|
|
||||||
|
Build and install the kernel as you normally would for your system.
|
||||||
|
Assuming GRUB is the bootloader, it will automatically detect the new
|
||||||
|
host kernel when you run `grub-mkconfig` or `grub2-mkconfig`.
|
Reference in New Issue
Block a user