connected daemon to the brain (#2)
Instead of grabbing commands from files, the daemon now connects to the brain and receives commands via gRPC. Reviewed-on: SNP/daemon#2
This commit is contained in:
		
							parent
							
								
									3ba140a830
								
							
						
					
					
						commit
						3c6074f735
					
				
							
								
								
									
										699
									
								
								Cargo.lock
									
									
									
										generated
									
									
									
								
							
							
								
								
								
								
								
									
									
								
							
						
						
									
										699
									
								
								Cargo.lock
									
									
									
										generated
									
									
									
								
							| @ -17,12 +17,103 @@ version = "2.0.0" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "512761e0bb2578dd7380c6baaa0f4ce03e84f95e960231d1dec8bf4d7d6e2627" | ||||
| 
 | ||||
| [[package]] | ||||
| name = "aho-corasick" | ||||
| version = "1.1.3" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916" | ||||
| dependencies = [ | ||||
|  "memchr", | ||||
| ] | ||||
| 
 | ||||
| [[package]] | ||||
| name = "anstream" | ||||
| version = "0.6.18" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "8acc5369981196006228e28809f761875c0327210a891e941f4c683b3a99529b" | ||||
| dependencies = [ | ||||
|  "anstyle", | ||||
|  "anstyle-parse", | ||||
|  "anstyle-query", | ||||
|  "anstyle-wincon", | ||||
|  "colorchoice", | ||||
|  "is_terminal_polyfill", | ||||
|  "utf8parse", | ||||
| ] | ||||
| 
 | ||||
| [[package]] | ||||
| name = "anstyle" | ||||
| version = "1.0.10" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "55cc3b69f167a1ef2e161439aa98aed94e6028e5f9a59be9a6ffb47aef1651f9" | ||||
| 
 | ||||
| [[package]] | ||||
| name = "anstyle-parse" | ||||
| version = "0.2.6" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "3b2d16507662817a6a20a9ea92df6652ee4f94f914589377d69f3b21bc5798a9" | ||||
| dependencies = [ | ||||
|  "utf8parse", | ||||
| ] | ||||
| 
 | ||||
| [[package]] | ||||
| name = "anstyle-query" | ||||
| version = "1.1.2" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "79947af37f4177cfead1110013d678905c37501914fba0efea834c3fe9a8d60c" | ||||
| dependencies = [ | ||||
|  "windows-sys 0.59.0", | ||||
| ] | ||||
| 
 | ||||
| [[package]] | ||||
| name = "anstyle-wincon" | ||||
| version = "3.0.6" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "2109dbce0e72be3ec00bed26e6a7479ca384ad226efdd66db8fa2e3a38c83125" | ||||
| dependencies = [ | ||||
|  "anstyle", | ||||
|  "windows-sys 0.59.0", | ||||
| ] | ||||
| 
 | ||||
| [[package]] | ||||
| name = "anyhow" | ||||
| version = "1.0.94" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "c1fd03a028ef38ba2276dce7e33fcd6369c158a1bca17946c4b1b701891c1ff7" | ||||
| 
 | ||||
| [[package]] | ||||
| name = "async-stream" | ||||
| version = "0.3.6" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "0b5a71a6f37880a80d1d7f19efd781e4b5de42c88f0722cc13bcb6cc2cfe8476" | ||||
| dependencies = [ | ||||
|  "async-stream-impl", | ||||
|  "futures-core", | ||||
|  "pin-project-lite", | ||||
| ] | ||||
| 
 | ||||
| [[package]] | ||||
| name = "async-stream-impl" | ||||
| version = "0.3.6" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "c7c24de15d275a1ecfd47a380fb4d5ec9bfe0933f309ed5e705b775596a3574d" | ||||
| dependencies = [ | ||||
|  "proc-macro2", | ||||
|  "quote", | ||||
|  "syn", | ||||
| ] | ||||
| 
 | ||||
| [[package]] | ||||
| name = "async-trait" | ||||
| version = "0.1.83" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "721cae7de5c34fbb2acd27e21e6d2cf7b886dce0c27388d46c4e6c47ea4318dd" | ||||
| dependencies = [ | ||||
|  "proc-macro2", | ||||
|  "quote", | ||||
|  "syn", | ||||
| ] | ||||
| 
 | ||||
| [[package]] | ||||
| name = "atomic-waker" | ||||
| version = "1.1.2" | ||||
| @ -35,6 +126,53 @@ version = "1.4.0" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26" | ||||
| 
 | ||||
| [[package]] | ||||
| name = "axum" | ||||
| version = "0.7.9" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "edca88bc138befd0323b20752846e6587272d3b03b0343c8ea28a6f819e6e71f" | ||||
| dependencies = [ | ||||
|  "async-trait", | ||||
|  "axum-core", | ||||
|  "bytes", | ||||
|  "futures-util", | ||||
|  "http", | ||||
|  "http-body", | ||||
|  "http-body-util", | ||||
|  "itoa", | ||||
|  "matchit", | ||||
|  "memchr", | ||||
|  "mime", | ||||
|  "percent-encoding", | ||||
|  "pin-project-lite", | ||||
|  "rustversion", | ||||
|  "serde", | ||||
|  "sync_wrapper", | ||||
|  "tower 0.5.2", | ||||
|  "tower-layer", | ||||
|  "tower-service", | ||||
| ] | ||||
| 
 | ||||
| [[package]] | ||||
| name = "axum-core" | ||||
| version = "0.4.5" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "09f2bd6146b97ae3359fa0cc6d6b376d9539582c7b4220f041a33ec24c226199" | ||||
| dependencies = [ | ||||
|  "async-trait", | ||||
|  "bytes", | ||||
|  "futures-util", | ||||
|  "http", | ||||
|  "http-body", | ||||
|  "http-body-util", | ||||
|  "mime", | ||||
|  "pin-project-lite", | ||||
|  "rustversion", | ||||
|  "sync_wrapper", | ||||
|  "tower-layer", | ||||
|  "tower-service", | ||||
| ] | ||||
| 
 | ||||
| [[package]] | ||||
| name = "backtrace" | ||||
| version = "0.3.74" | ||||
| @ -56,6 +194,12 @@ version = "0.22.1" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" | ||||
| 
 | ||||
| [[package]] | ||||
| name = "base64ct" | ||||
| version = "1.6.0" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "8c3c1a368f70d6cf7302d78f8f7093da241fb8e8807c05cc9e51a125895a6d5b" | ||||
| 
 | ||||
| [[package]] | ||||
| name = "bitflags" | ||||
| version = "2.6.0" | ||||
| @ -91,9 +235,9 @@ checksum = "325918d6fe32f23b19878fe4b34794ae41fc19ddbe53b10571a4874d44ffd39b" | ||||
| 
 | ||||
| [[package]] | ||||
| name = "cc" | ||||
| version = "1.2.3" | ||||
| version = "1.2.6" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "27f657647bcff5394bf56c7317665bbf790a137a50eaaa5c6bfbb9e27a518f2d" | ||||
| checksum = "8d6dbb628b8f8555f86d0323c2eb39e3ec81901f4b83e091db8a6a76d316a333" | ||||
| dependencies = [ | ||||
|  "shlex", | ||||
| ] | ||||
| @ -105,13 +249,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" | ||||
| 
 | ||||
| [[package]] | ||||
| name = "cidr" | ||||
| version = "0.3.0" | ||||
| name = "colorchoice" | ||||
| version = "1.0.3" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "bfc95a0c21d5409adc146dbbb152b5c65aaea32bc2d2f57cf12f850bffdd7ab8" | ||||
| dependencies = [ | ||||
|  "serde", | ||||
| ] | ||||
| checksum = "5b63caa9aa9397e2d9480a9b13673856c78d8ac123288526c37d7839f2a86990" | ||||
| 
 | ||||
| [[package]] | ||||
| name = "const-oid" | ||||
| version = "0.9.6" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "c2459377285ad874054d797f3ccebf984978aa39129f6eafde5cdc8315b612f8" | ||||
| 
 | ||||
| [[package]] | ||||
| name = "core-foundation" | ||||
| @ -148,17 +295,65 @@ dependencies = [ | ||||
|  "typenum", | ||||
| ] | ||||
| 
 | ||||
| [[package]] | ||||
| name = "curve25519-dalek" | ||||
| version = "4.1.3" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "97fb8b7c4503de7d6ae7b42ab72a5a59857b4c937ec27a3d4539dba95b5ab2be" | ||||
| dependencies = [ | ||||
|  "cfg-if", | ||||
|  "cpufeatures", | ||||
|  "curve25519-dalek-derive", | ||||
|  "digest", | ||||
|  "fiat-crypto", | ||||
|  "rustc_version", | ||||
|  "subtle", | ||||
|  "zeroize", | ||||
| ] | ||||
| 
 | ||||
| [[package]] | ||||
| name = "curve25519-dalek-derive" | ||||
| version = "0.1.1" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "f46882e17999c6cc590af592290432be3bce0428cb0d5f8b6715e4dc7b383eb3" | ||||
| dependencies = [ | ||||
|  "proc-macro2", | ||||
|  "quote", | ||||
|  "syn", | ||||
| ] | ||||
| 
 | ||||
| [[package]] | ||||
| name = "der" | ||||
| version = "0.7.9" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "f55bf8e7b65898637379c1b74eb1551107c8294ed26d855ceb9fd1a09cfc9bc0" | ||||
| dependencies = [ | ||||
|  "const-oid", | ||||
|  "pem-rfc7468", | ||||
|  "zeroize", | ||||
| ] | ||||
| 
 | ||||
| [[package]] | ||||
| name = "detee-snp-daemon" | ||||
| version = "0.1.0" | ||||
| dependencies = [ | ||||
|  "anyhow", | ||||
|  "cidr", | ||||
|  "ed25519-dalek", | ||||
|  "env_logger", | ||||
|  "lazy_static", | ||||
|  "log", | ||||
|  "prost", | ||||
|  "prost-types", | ||||
|  "rand", | ||||
|  "rand_core", | ||||
|  "reqwest", | ||||
|  "serde", | ||||
|  "serde_yaml", | ||||
|  "sha2", | ||||
|  "tokio", | ||||
|  "tokio-stream", | ||||
|  "tonic", | ||||
|  "tonic-build", | ||||
| ] | ||||
| 
 | ||||
| [[package]] | ||||
| @ -182,6 +377,37 @@ dependencies = [ | ||||
|  "syn", | ||||
| ] | ||||
| 
 | ||||
| [[package]] | ||||
| name = "ed25519" | ||||
| version = "2.2.3" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "115531babc129696a58c64a4fef0a8bf9e9698629fb97e9e40767d235cfbcd53" | ||||
| dependencies = [ | ||||
|  "pkcs8", | ||||
|  "signature", | ||||
| ] | ||||
| 
 | ||||
| [[package]] | ||||
| name = "ed25519-dalek" | ||||
| version = "2.1.1" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "4a3daa8e81a3963a60642bcc1f90a670680bd4a77535faa384e9d1c79d620871" | ||||
| dependencies = [ | ||||
|  "curve25519-dalek", | ||||
|  "ed25519", | ||||
|  "rand_core", | ||||
|  "serde", | ||||
|  "sha2", | ||||
|  "subtle", | ||||
|  "zeroize", | ||||
| ] | ||||
| 
 | ||||
| [[package]] | ||||
| name = "either" | ||||
| version = "1.13.0" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "60b1af1c220855b6ceac025d3f6ecdd2b7c4894bfe9cd9bda4fbb4bc7c0d4cf0" | ||||
| 
 | ||||
| [[package]] | ||||
| name = "encoding_rs" | ||||
| version = "0.8.35" | ||||
| @ -191,6 +417,29 @@ dependencies = [ | ||||
|  "cfg-if", | ||||
| ] | ||||
| 
 | ||||
| [[package]] | ||||
| name = "env_filter" | ||||
| version = "0.1.3" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "186e05a59d4c50738528153b83b0b0194d3a29507dfec16eccd4b342903397d0" | ||||
| dependencies = [ | ||||
|  "log", | ||||
|  "regex", | ||||
| ] | ||||
| 
 | ||||
| [[package]] | ||||
| name = "env_logger" | ||||
| version = "0.11.6" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "dcaee3d8e3cfc3fd92428d477bc97fc29ec8716d180c0d74c643bb26166660e0" | ||||
| dependencies = [ | ||||
|  "anstream", | ||||
|  "anstyle", | ||||
|  "env_filter", | ||||
|  "humantime", | ||||
|  "log", | ||||
| ] | ||||
| 
 | ||||
| [[package]] | ||||
| name = "equivalent" | ||||
| version = "1.0.1" | ||||
| @ -213,6 +462,18 @@ version = "2.3.0" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "37909eebbb50d72f9059c3b6d82c0463f2ff062c9e95845c43a6c9c0355411be" | ||||
| 
 | ||||
| [[package]] | ||||
| name = "fiat-crypto" | ||||
| version = "0.2.9" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "28dea519a9695b9977216879a3ebfddf92f1c08c05d984f8996aecd6ecdc811d" | ||||
| 
 | ||||
| [[package]] | ||||
| name = "fixedbitset" | ||||
| version = "0.4.2" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "0ce7134b9999ecaf8bcd65542e436736ef32ddca1b3e06094cb6ec5755203b80" | ||||
| 
 | ||||
| [[package]] | ||||
| name = "fnv" | ||||
| version = "1.0.7" | ||||
| @ -332,19 +593,31 @@ dependencies = [ | ||||
|  "futures-core", | ||||
|  "futures-sink", | ||||
|  "http", | ||||
|  "indexmap", | ||||
|  "indexmap 2.7.0", | ||||
|  "slab", | ||||
|  "tokio", | ||||
|  "tokio-util", | ||||
|  "tracing", | ||||
| ] | ||||
| 
 | ||||
| [[package]] | ||||
| name = "hashbrown" | ||||
| version = "0.12.3" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" | ||||
| 
 | ||||
| [[package]] | ||||
| name = "hashbrown" | ||||
| version = "0.15.2" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "bf151400ff0baff5465007dd2f3e717f3fe502074ca563069ce3a6629d07b289" | ||||
| 
 | ||||
| [[package]] | ||||
| name = "heck" | ||||
| version = "0.5.0" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" | ||||
| 
 | ||||
| [[package]] | ||||
| name = "http" | ||||
| version = "1.2.0" | ||||
| @ -385,6 +658,18 @@ version = "1.9.5" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "7d71d3574edd2771538b901e6549113b4006ece66150fb69c0fb6d9a2adae946" | ||||
| 
 | ||||
| [[package]] | ||||
| name = "httpdate" | ||||
| version = "1.0.3" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9" | ||||
| 
 | ||||
| [[package]] | ||||
| name = "humantime" | ||||
| version = "2.1.0" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4" | ||||
| 
 | ||||
| [[package]] | ||||
| name = "hyper" | ||||
| version = "1.5.1" | ||||
| @ -398,6 +683,7 @@ dependencies = [ | ||||
|  "http", | ||||
|  "http-body", | ||||
|  "httparse", | ||||
|  "httpdate", | ||||
|  "itoa", | ||||
|  "pin-project-lite", | ||||
|  "smallvec", | ||||
| @ -407,9 +693,9 @@ dependencies = [ | ||||
| 
 | ||||
| [[package]] | ||||
| name = "hyper-rustls" | ||||
| version = "0.27.3" | ||||
| version = "0.27.5" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "08afdbb5c31130e3034af566421053ab03787c640246a446327f550d11bcb333" | ||||
| checksum = "2d191583f3da1305256f22463b9bb0471acad48a4e534a5218b9963e9c1f59b2" | ||||
| dependencies = [ | ||||
|  "futures-util", | ||||
|  "http", | ||||
| @ -422,6 +708,19 @@ dependencies = [ | ||||
|  "tower-service", | ||||
| ] | ||||
| 
 | ||||
| [[package]] | ||||
| name = "hyper-timeout" | ||||
| version = "0.5.2" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "2b90d566bffbce6a75bd8b09a05aa8c2cb1fabb6cb348f8840c9e4c90a0d83b0" | ||||
| dependencies = [ | ||||
|  "hyper", | ||||
|  "hyper-util", | ||||
|  "pin-project-lite", | ||||
|  "tokio", | ||||
|  "tower-service", | ||||
| ] | ||||
| 
 | ||||
| [[package]] | ||||
| name = "hyper-tls" | ||||
| version = "0.6.0" | ||||
| @ -596,6 +895,16 @@ dependencies = [ | ||||
|  "icu_properties", | ||||
| ] | ||||
| 
 | ||||
| [[package]] | ||||
| name = "indexmap" | ||||
| version = "1.9.3" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99" | ||||
| dependencies = [ | ||||
|  "autocfg", | ||||
|  "hashbrown 0.12.3", | ||||
| ] | ||||
| 
 | ||||
| [[package]] | ||||
| name = "indexmap" | ||||
| version = "2.7.0" | ||||
| @ -603,7 +912,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "62f822373a4fe84d4bb149bf54e584a7f4abec90e072ed49cda0edea5b95471f" | ||||
| dependencies = [ | ||||
|  "equivalent", | ||||
|  "hashbrown", | ||||
|  "hashbrown 0.15.2", | ||||
| ] | ||||
| 
 | ||||
| [[package]] | ||||
| @ -612,6 +921,21 @@ version = "2.10.1" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "ddc24109865250148c2e0f3d25d4f0f479571723792d3802153c60922a4fb708" | ||||
| 
 | ||||
| [[package]] | ||||
| name = "is_terminal_polyfill" | ||||
| version = "1.70.1" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "7943c866cc5cd64cbc25b2e01621d07fa8eb2a1a23160ee81ce38704e97b8ecf" | ||||
| 
 | ||||
| [[package]] | ||||
| name = "itertools" | ||||
| version = "0.13.0" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "413ee7dfc52ee1a4949ceeb7dbc8a33f2d6c088194d9f922fb8318faf1f01186" | ||||
| dependencies = [ | ||||
|  "either", | ||||
| ] | ||||
| 
 | ||||
| [[package]] | ||||
| name = "itoa" | ||||
| version = "1.0.14" | ||||
| @ -628,6 +952,12 @@ dependencies = [ | ||||
|  "wasm-bindgen", | ||||
| ] | ||||
| 
 | ||||
| [[package]] | ||||
| name = "lazy_static" | ||||
| version = "1.5.0" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" | ||||
| 
 | ||||
| [[package]] | ||||
| name = "libc" | ||||
| version = "0.2.167" | ||||
| @ -652,6 +982,12 @@ version = "0.4.22" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24" | ||||
| 
 | ||||
| [[package]] | ||||
| name = "matchit" | ||||
| version = "0.7.3" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "0e7465ac9959cc2b1404e8e2367b43684a6d13790fe23056cc8c6c5a6b7bcb94" | ||||
| 
 | ||||
| [[package]] | ||||
| name = "memchr" | ||||
| version = "2.7.4" | ||||
| @ -684,6 +1020,12 @@ dependencies = [ | ||||
|  "windows-sys 0.52.0", | ||||
| ] | ||||
| 
 | ||||
| [[package]] | ||||
| name = "multimap" | ||||
| version = "0.10.0" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "defc4c55412d89136f966bbb339008b474350e5e6e78d2714439c386b3137a03" | ||||
| 
 | ||||
| [[package]] | ||||
| name = "native-tls" | ||||
| version = "0.2.12" | ||||
| @ -760,12 +1102,51 @@ dependencies = [ | ||||
|  "vcpkg", | ||||
| ] | ||||
| 
 | ||||
| [[package]] | ||||
| name = "pem-rfc7468" | ||||
| version = "0.7.0" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "88b39c9bfcfc231068454382784bb460aae594343fb030d46e9f50a645418412" | ||||
| dependencies = [ | ||||
|  "base64ct", | ||||
| ] | ||||
| 
 | ||||
| [[package]] | ||||
| name = "percent-encoding" | ||||
| version = "2.3.1" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" | ||||
| 
 | ||||
| [[package]] | ||||
| name = "petgraph" | ||||
| version = "0.6.5" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "b4c5cc86750666a3ed20bdaf5ca2a0344f9c67674cae0515bec2da16fbaa47db" | ||||
| dependencies = [ | ||||
|  "fixedbitset", | ||||
|  "indexmap 2.7.0", | ||||
| ] | ||||
| 
 | ||||
| [[package]] | ||||
| name = "pin-project" | ||||
| version = "1.1.7" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "be57f64e946e500c8ee36ef6331845d40a93055567ec57e8fae13efd33759b95" | ||||
| dependencies = [ | ||||
|  "pin-project-internal", | ||||
| ] | ||||
| 
 | ||||
| [[package]] | ||||
| name = "pin-project-internal" | ||||
| version = "1.1.7" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "3c0f5fad0874fc7abcd4d750e76917eaebbecaa2c20bde22e1dbeeba8beb758c" | ||||
| dependencies = [ | ||||
|  "proc-macro2", | ||||
|  "quote", | ||||
|  "syn", | ||||
| ] | ||||
| 
 | ||||
| [[package]] | ||||
| name = "pin-project-lite" | ||||
| version = "0.2.15" | ||||
| @ -778,6 +1159,16 @@ version = "0.1.0" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" | ||||
| 
 | ||||
| [[package]] | ||||
| name = "pkcs8" | ||||
| version = "0.10.2" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "f950b2377845cebe5cf8b5165cb3cc1a5e0fa5cfa3e1f7f55707d8fd82e0a7b7" | ||||
| dependencies = [ | ||||
|  "der", | ||||
|  "spki", | ||||
| ] | ||||
| 
 | ||||
| [[package]] | ||||
| name = "pkg-config" | ||||
| version = "0.3.31" | ||||
| @ -793,6 +1184,16 @@ dependencies = [ | ||||
|  "zerocopy", | ||||
| ] | ||||
| 
 | ||||
| [[package]] | ||||
| name = "prettyplease" | ||||
| version = "0.2.25" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "64d1ec885c64d0457d564db4ec299b2dae3f9c02808b8ad9c3a089c591b18033" | ||||
| dependencies = [ | ||||
|  "proc-macro2", | ||||
|  "syn", | ||||
| ] | ||||
| 
 | ||||
| [[package]] | ||||
| name = "proc-macro2" | ||||
| version = "1.0.92" | ||||
| @ -802,6 +1203,58 @@ dependencies = [ | ||||
|  "unicode-ident", | ||||
| ] | ||||
| 
 | ||||
| [[package]] | ||||
| name = "prost" | ||||
| version = "0.13.4" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "2c0fef6c4230e4ccf618a35c59d7ede15dea37de8427500f50aff708806e42ec" | ||||
| dependencies = [ | ||||
|  "bytes", | ||||
|  "prost-derive", | ||||
| ] | ||||
| 
 | ||||
| [[package]] | ||||
| name = "prost-build" | ||||
| version = "0.13.4" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "d0f3e5beed80eb580c68e2c600937ac2c4eedabdfd5ef1e5b7ea4f3fba84497b" | ||||
| dependencies = [ | ||||
|  "heck", | ||||
|  "itertools", | ||||
|  "log", | ||||
|  "multimap", | ||||
|  "once_cell", | ||||
|  "petgraph", | ||||
|  "prettyplease", | ||||
|  "prost", | ||||
|  "prost-types", | ||||
|  "regex", | ||||
|  "syn", | ||||
|  "tempfile", | ||||
| ] | ||||
| 
 | ||||
| [[package]] | ||||
| name = "prost-derive" | ||||
| version = "0.13.4" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "157c5a9d7ea5c2ed2d9fb8f495b64759f7816c7eaea54ba3978f0d63000162e3" | ||||
| dependencies = [ | ||||
|  "anyhow", | ||||
|  "itertools", | ||||
|  "proc-macro2", | ||||
|  "quote", | ||||
|  "syn", | ||||
| ] | ||||
| 
 | ||||
| [[package]] | ||||
| name = "prost-types" | ||||
| version = "0.13.4" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "cc2f1e56baa61e93533aebc21af4d2134b70f66275e0fcdf3cbe43d77ff7e8fc" | ||||
| dependencies = [ | ||||
|  "prost", | ||||
| ] | ||||
| 
 | ||||
| [[package]] | ||||
| name = "quote" | ||||
| version = "1.0.37" | ||||
| @ -842,10 +1295,39 @@ dependencies = [ | ||||
| ] | ||||
| 
 | ||||
| [[package]] | ||||
| name = "reqwest" | ||||
| version = "0.12.9" | ||||
| name = "regex" | ||||
| version = "1.11.1" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "a77c62af46e79de0a562e1a9849205ffcb7fc1238876e9bd743357570e04046f" | ||||
| checksum = "b544ef1b4eac5dc2db33ea63606ae9ffcfac26c1416a2806ae0bf5f56b201191" | ||||
| dependencies = [ | ||||
|  "aho-corasick", | ||||
|  "memchr", | ||||
|  "regex-automata", | ||||
|  "regex-syntax", | ||||
| ] | ||||
| 
 | ||||
| [[package]] | ||||
| name = "regex-automata" | ||||
| version = "0.4.9" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "809e8dc61f6de73b46c85f4c96486310fe304c434cfa43669d7b40f711150908" | ||||
| dependencies = [ | ||||
|  "aho-corasick", | ||||
|  "memchr", | ||||
|  "regex-syntax", | ||||
| ] | ||||
| 
 | ||||
| [[package]] | ||||
| name = "regex-syntax" | ||||
| version = "0.8.5" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c" | ||||
| 
 | ||||
| [[package]] | ||||
| name = "reqwest" | ||||
| version = "0.12.11" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "7fe060fe50f524be480214aba758c71f99f90ee8c83c5a36b5e9e1d568eb4eb3" | ||||
| dependencies = [ | ||||
|  "base64", | ||||
|  "bytes", | ||||
| @ -877,6 +1359,7 @@ dependencies = [ | ||||
|  "system-configuration", | ||||
|  "tokio", | ||||
|  "tokio-native-tls", | ||||
|  "tower 0.5.2", | ||||
|  "tower-service", | ||||
|  "url", | ||||
|  "wasm-bindgen", | ||||
| @ -906,6 +1389,15 @@ version = "0.1.24" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f" | ||||
| 
 | ||||
| [[package]] | ||||
| name = "rustc_version" | ||||
| version = "0.4.1" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "cfcb3a22ef46e85b45de6ee7e79d063319ebb6594faafcf1c225ea92ab6e9b92" | ||||
| dependencies = [ | ||||
|  "semver", | ||||
| ] | ||||
| 
 | ||||
| [[package]] | ||||
| name = "rustix" | ||||
| version = "0.38.42" | ||||
| @ -921,9 +1413,9 @@ dependencies = [ | ||||
| 
 | ||||
| [[package]] | ||||
| name = "rustls" | ||||
| version = "0.23.19" | ||||
| version = "0.23.20" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "934b404430bb06b3fae2cba809eb45a1ab1aecd64491213d7c3301b88393f8d1" | ||||
| checksum = "5065c3f250cbd332cd894be57c40fa52387247659b14a2d6041d121547903b1b" | ||||
| dependencies = [ | ||||
|  "once_cell", | ||||
|  "rustls-pki-types", | ||||
| @ -943,9 +1435,9 @@ dependencies = [ | ||||
| 
 | ||||
| [[package]] | ||||
| name = "rustls-pki-types" | ||||
| version = "1.10.0" | ||||
| version = "1.10.1" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "16f1201b3c9a7ee8039bcadc17b7e605e2945b27eee7631788c1bd2b0643674b" | ||||
| checksum = "d2bf47e6ff922db3825eb750c4e2ff784c6ff8fb9e13046ef6a1d1c5401b0b37" | ||||
| 
 | ||||
| [[package]] | ||||
| name = "rustls-webpki" | ||||
| @ -958,6 +1450,12 @@ dependencies = [ | ||||
|  "untrusted", | ||||
| ] | ||||
| 
 | ||||
| [[package]] | ||||
| name = "rustversion" | ||||
| version = "1.0.18" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "0e819f2bc632f285be6d7cd36e25940d45b2391dd6d9b939e79de557f7014248" | ||||
| 
 | ||||
| [[package]] | ||||
| name = "ryu" | ||||
| version = "1.0.18" | ||||
| @ -988,14 +1486,20 @@ dependencies = [ | ||||
| 
 | ||||
| [[package]] | ||||
| name = "security-framework-sys" | ||||
| version = "2.12.1" | ||||
| version = "2.13.0" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "fa39c7303dc58b5543c94d22c1766b0d31f2ee58306363ea622b10bbc075eaa2" | ||||
| checksum = "1863fd3768cd83c56a7f60faa4dc0d403f1b6df0a38c3c25f44b7894e45370d5" | ||||
| dependencies = [ | ||||
|  "core-foundation-sys", | ||||
|  "libc", | ||||
| ] | ||||
| 
 | ||||
| [[package]] | ||||
| name = "semver" | ||||
| version = "1.0.24" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "3cb6eb87a131f756572d7fb904f6e7b68633f09cca868c5df1c4b8d1a694bbba" | ||||
| 
 | ||||
| [[package]] | ||||
| name = "serde" | ||||
| version = "1.0.215" | ||||
| @ -1018,9 +1522,9 @@ dependencies = [ | ||||
| 
 | ||||
| [[package]] | ||||
| name = "serde_json" | ||||
| version = "1.0.133" | ||||
| version = "1.0.134" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "c7fceb2473b9166b2294ef05efcb65a3db80803f0b03ef86a5fc88a2b85ee377" | ||||
| checksum = "d00f4175c42ee48b15416f6193a959ba3a0d67fc699a0db9ad12df9f83991c7d" | ||||
| dependencies = [ | ||||
|  "itoa", | ||||
|  "memchr", | ||||
| @ -1046,7 +1550,7 @@ version = "0.9.34+deprecated" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "6a8b1a1a2ebf674015cc02edccce75287f1a0130d394307b36743c2f5d504b47" | ||||
| dependencies = [ | ||||
|  "indexmap", | ||||
|  "indexmap 2.7.0", | ||||
|  "itoa", | ||||
|  "ryu", | ||||
|  "serde", | ||||
| @ -1070,6 +1574,15 @@ version = "1.3.0" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" | ||||
| 
 | ||||
| [[package]] | ||||
| name = "signature" | ||||
| version = "2.2.0" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "77549399552de45a898a580c1b41d445bf730df867cc44e6c0233bbc4b8329de" | ||||
| dependencies = [ | ||||
|  "rand_core", | ||||
| ] | ||||
| 
 | ||||
| [[package]] | ||||
| name = "slab" | ||||
| version = "0.4.9" | ||||
| @ -1101,6 +1614,16 @@ version = "0.9.8" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67" | ||||
| 
 | ||||
| [[package]] | ||||
| name = "spki" | ||||
| version = "0.7.3" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "d91ed6c858b01f942cd56b37a94b3e0a1798290327d1236e4d9cf4eaca44d29d" | ||||
| dependencies = [ | ||||
|  "base64ct", | ||||
|  "der", | ||||
| ] | ||||
| 
 | ||||
| [[package]] | ||||
| name = "stable_deref_trait" | ||||
| version = "1.2.0" | ||||
| @ -1200,9 +1723,21 @@ dependencies = [ | ||||
|  "mio", | ||||
|  "pin-project-lite", | ||||
|  "socket2", | ||||
|  "tokio-macros", | ||||
|  "windows-sys 0.52.0", | ||||
| ] | ||||
| 
 | ||||
| [[package]] | ||||
| name = "tokio-macros" | ||||
| version = "2.4.0" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "693d596312e88961bc67d7f1f97af8a70227d9f90c31bba5806eec004978d752" | ||||
| dependencies = [ | ||||
|  "proc-macro2", | ||||
|  "quote", | ||||
|  "syn", | ||||
| ] | ||||
| 
 | ||||
| [[package]] | ||||
| name = "tokio-native-tls" | ||||
| version = "0.3.1" | ||||
| @ -1223,6 +1758,17 @@ dependencies = [ | ||||
|  "tokio", | ||||
| ] | ||||
| 
 | ||||
| [[package]] | ||||
| name = "tokio-stream" | ||||
| version = "0.1.17" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "eca58d7bba4a75707817a2c44174253f9236b2d5fbd055602e9d5c07c139a047" | ||||
| dependencies = [ | ||||
|  "futures-core", | ||||
|  "pin-project-lite", | ||||
|  "tokio", | ||||
| ] | ||||
| 
 | ||||
| [[package]] | ||||
| name = "tokio-util" | ||||
| version = "0.7.13" | ||||
| @ -1236,6 +1782,91 @@ dependencies = [ | ||||
|  "tokio", | ||||
| ] | ||||
| 
 | ||||
| [[package]] | ||||
| name = "tonic" | ||||
| version = "0.12.3" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "877c5b330756d856ffcc4553ab34a5684481ade925ecc54bcd1bf02b1d0d4d52" | ||||
| dependencies = [ | ||||
|  "async-stream", | ||||
|  "async-trait", | ||||
|  "axum", | ||||
|  "base64", | ||||
|  "bytes", | ||||
|  "h2", | ||||
|  "http", | ||||
|  "http-body", | ||||
|  "http-body-util", | ||||
|  "hyper", | ||||
|  "hyper-timeout", | ||||
|  "hyper-util", | ||||
|  "percent-encoding", | ||||
|  "pin-project", | ||||
|  "prost", | ||||
|  "socket2", | ||||
|  "tokio", | ||||
|  "tokio-stream", | ||||
|  "tower 0.4.13", | ||||
|  "tower-layer", | ||||
|  "tower-service", | ||||
|  "tracing", | ||||
| ] | ||||
| 
 | ||||
| [[package]] | ||||
| name = "tonic-build" | ||||
| version = "0.12.3" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "9557ce109ea773b399c9b9e5dca39294110b74f1f342cb347a80d1fce8c26a11" | ||||
| dependencies = [ | ||||
|  "prettyplease", | ||||
|  "proc-macro2", | ||||
|  "prost-build", | ||||
|  "prost-types", | ||||
|  "quote", | ||||
|  "syn", | ||||
| ] | ||||
| 
 | ||||
| [[package]] | ||||
| name = "tower" | ||||
| version = "0.4.13" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "b8fa9be0de6cf49e536ce1851f987bd21a43b771b09473c3549a6c853db37c1c" | ||||
| dependencies = [ | ||||
|  "futures-core", | ||||
|  "futures-util", | ||||
|  "indexmap 1.9.3", | ||||
|  "pin-project", | ||||
|  "pin-project-lite", | ||||
|  "rand", | ||||
|  "slab", | ||||
|  "tokio", | ||||
|  "tokio-util", | ||||
|  "tower-layer", | ||||
|  "tower-service", | ||||
|  "tracing", | ||||
| ] | ||||
| 
 | ||||
| [[package]] | ||||
| name = "tower" | ||||
| version = "0.5.2" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "d039ad9159c98b70ecfd540b2573b97f7f52c3e8d9f8ad57a24b916a536975f9" | ||||
| dependencies = [ | ||||
|  "futures-core", | ||||
|  "futures-util", | ||||
|  "pin-project-lite", | ||||
|  "sync_wrapper", | ||||
|  "tokio", | ||||
|  "tower-layer", | ||||
|  "tower-service", | ||||
| ] | ||||
| 
 | ||||
| [[package]] | ||||
| name = "tower-layer" | ||||
| version = "0.3.3" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "121c2a6cda46980bb0fcd1647ffaf6cd3fc79a013de288782836f6df9c48780e" | ||||
| 
 | ||||
| [[package]] | ||||
| name = "tower-service" | ||||
| version = "0.3.3" | ||||
| @ -1249,9 +1880,21 @@ source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "784e0ac535deb450455cbfa28a6f0df145ea1bb7ae51b821cf5e7927fdcfbdd0" | ||||
| dependencies = [ | ||||
|  "pin-project-lite", | ||||
|  "tracing-attributes", | ||||
|  "tracing-core", | ||||
| ] | ||||
| 
 | ||||
| [[package]] | ||||
| name = "tracing-attributes" | ||||
| version = "0.1.28" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "395ae124c09f9e6918a2310af6038fba074bcf474ac352496d5910dd59a2226d" | ||||
| dependencies = [ | ||||
|  "proc-macro2", | ||||
|  "quote", | ||||
|  "syn", | ||||
| ] | ||||
| 
 | ||||
| [[package]] | ||||
| name = "tracing-core" | ||||
| version = "0.1.33" | ||||
| @ -1314,6 +1957,12 @@ version = "1.0.4" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "b6c140620e7ffbb22c2dee59cafe6084a59b5ffc27a8859a5f0d494b5d52b6be" | ||||
| 
 | ||||
| [[package]] | ||||
| name = "utf8parse" | ||||
| version = "0.2.2" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" | ||||
| 
 | ||||
| [[package]] | ||||
| name = "vcpkg" | ||||
| version = "0.2.15" | ||||
|  | ||||
							
								
								
									
										16
									
								
								Cargo.toml
									
									
									
									
									
								
							
							
								
								
								
								
								
									
									
								
							
						
						
									
										16
									
								
								Cargo.toml
									
									
									
									
									
								
							| @ -4,10 +4,22 @@ version = "0.1.0" | ||||
| edition = "2021" | ||||
| 
 | ||||
| [dependencies] | ||||
| ed25519-dalek = { version = "2.1.1", default-features = false, features = ["std", "alloc", "rand_core", "pem"] } | ||||
| rand_core = { version = "0.6.4", features = ["alloc", "getrandom", "std"] } | ||||
| anyhow = "1.0.94" | ||||
| cidr = { version = "0.3.0", features = ["serde"] } | ||||
| rand = "0.8.5" | ||||
| env_logger = "0.11.6" | ||||
| log = "0.4.22" | ||||
| reqwest = { version = "0.12.9", features = ["blocking"] } | ||||
| serde = { version = "1.0.215", features = ["derive"] } | ||||
| serde_yaml = "0.9.34" | ||||
| sha2 = "0.10.8" | ||||
| lazy_static = "1.5.0" | ||||
| prost = "0.13.4" | ||||
| prost-types = "0.13.4" | ||||
| rand = "0.8.5" | ||||
| tokio = { version = "1.42.0", features = ["macros", "rt-multi-thread"] } | ||||
| tokio-stream = "0.1.17" | ||||
| tonic = "0.12" | ||||
| 
 | ||||
| [build-dependencies] | ||||
| tonic-build = "0.12" | ||||
|  | ||||
							
								
								
									
										145
									
								
								brain.proto
									
									
									
									
									
										Normal file
									
								
							
							
								
								
								
								
								
									
									
								
							
						
						
									
										145
									
								
								brain.proto
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,145 @@ | ||||
| syntax = "proto3"; | ||||
| package brain; | ||||
| 
 | ||||
| message Empty { | ||||
| } | ||||
| 
 | ||||
| message NodePubkey { | ||||
|   string node_pubkey = 1; | ||||
| } | ||||
| 
 | ||||
| message RegisterNodeReq {  | ||||
|   string node_pubkey = 1; | ||||
|   string owner_pubkey = 2; | ||||
| } | ||||
| 
 | ||||
| message NodeResourceReq { | ||||
|   string node_pubkey = 1; | ||||
|   uint32 avail_ports = 2; | ||||
|   uint32 avail_ipv4 = 3; | ||||
|   uint32 avail_ipv6 = 4; | ||||
|   uint32 avail_vcpus = 5; | ||||
|   uint32 avail_memory_mb = 6; | ||||
|   uint32 avail_storage_gb = 7; | ||||
|   uint32 max_ports_per_vm = 8; | ||||
| } | ||||
| 
 | ||||
| message NewVMReq { | ||||
|   string uuid = 1; // UUID is empty when CLI sends request; brain sets UUID | ||||
|   string hostname = 2; | ||||
|   string admin_pubkey = 3; | ||||
|   string node_pubkey = 4; | ||||
|   repeated uint32 extra_ports = 5; | ||||
|   bool public_ipv4 = 6; | ||||
|   bool public_ipv6 = 7; | ||||
|   uint32 disk_size_gb = 8; | ||||
|   uint32 vcpus = 9; | ||||
|   uint32 memory_mb = 10; | ||||
|   string kernel_url = 11; | ||||
|   string kernel_sha = 12; | ||||
|   string dtrfs_url = 13; | ||||
|   string dtrfs_sha = 14; | ||||
| } | ||||
| 
 | ||||
| message UpdateVMReq { | ||||
|   string uuid = 1; | ||||
|   uint32 disk_size_gb = 3; | ||||
|   uint32 vcpus = 4; | ||||
|   uint32 memory_mb = 5; | ||||
|   string kernel_url = 6; | ||||
|   string kernel_sha = 7; | ||||
|   string dtrfs_url = 8; | ||||
|   string dtrfs_sha = 9; | ||||
| } | ||||
| 
 | ||||
| message UpdateVMResp { | ||||
|   string uuid = 1; | ||||
|   string error = 3; | ||||
| } | ||||
| 
 | ||||
| message VMContract { | ||||
|   string uuid = 1; | ||||
|   string hostname = 2; | ||||
|   string admin_pubkey = 3; | ||||
|   string node_pubkey = 4; | ||||
|   repeated uint32 exposed_ports = 5; | ||||
|   string public_ipv4 = 6; | ||||
|   string public_ipv6 = 7; | ||||
|   uint32 disk_size_gb = 8; | ||||
|   uint32 vcpus = 9; | ||||
|   uint32 memory_mb = 10; | ||||
|   string kernel_sha = 11; | ||||
|   string dtrfs_sha = 12; | ||||
|   string created_at = 13; | ||||
|   string updated_at = 14; | ||||
| } | ||||
| 
 | ||||
| message ListVMContractsReq { | ||||
|   string admin_pubkey = 1; | ||||
|   string node_pubkey = 2; | ||||
|   string uuid = 3; | ||||
| } | ||||
| 
 | ||||
| message NewVmRespIP { | ||||
|   uint32 nic_index = 1; | ||||
|   string address = 2; | ||||
|   string mask = 3; | ||||
|   string gateway = 4; | ||||
| } | ||||
| 
 | ||||
| message NewVMResp { | ||||
|   string uuid = 1; | ||||
|   repeated uint32 exposed_ports = 2; | ||||
|   string ovmf_hash = 5; | ||||
|   // This is needed to allow the CLI to build the kernel params from known data. | ||||
|   // The CLI will use the kernel params to get the measurement. | ||||
|   repeated NewVmRespIP ips = 6; | ||||
|   string error = 7; | ||||
| } | ||||
| 
 | ||||
| message DeleteVMReq { | ||||
|   string uuid = 1; | ||||
| } | ||||
| 
 | ||||
| service BrainDaemonService { | ||||
|   rpc RegisterNode (RegisterNodeReq) returns (Empty); | ||||
|   rpc SendNodeResources (stream NodeResourceReq) returns (Empty); | ||||
|   rpc GetNewVMReqs (NodePubkey) returns (stream NewVMReq); | ||||
|   rpc SendNewVMResp (stream NewVMResp) returns (Empty); | ||||
|   rpc GetDeleteVMReq (NodePubkey) returns (stream DeleteVMReq); | ||||
|   rpc ListVMContracts (ListVMContractsReq) returns (stream VMContract); | ||||
|   rpc GetUpdateVMReq (NodePubkey) returns (stream UpdateVMReq); | ||||
|   rpc SendUpdateVMResp (stream UpdateVMResp) returns (Empty); | ||||
| } | ||||
| 
 | ||||
| message NodeFilters { | ||||
|   uint32 free_ports = 1; | ||||
|   bool offers_ipv4 = 2; | ||||
|   bool offers_ipv6 = 3; | ||||
|   uint32 vcpus = 4; | ||||
|   uint32 memory_mb = 5; | ||||
|   uint32 storage_gb = 6; | ||||
|   string country = 7; | ||||
|   string region = 8; | ||||
|   string city = 9; | ||||
|   string ip = 10; | ||||
| } | ||||
| 
 | ||||
| message NodeListResp { | ||||
|   string node_pubkey = 1; | ||||
|   string country = 2; | ||||
|   string region = 3; | ||||
|   string city = 4; | ||||
|   string ip = 5; // required for latency test | ||||
|   uint32 server_rating = 6; | ||||
|   uint32 provider_rating = 7; | ||||
| } | ||||
| 
 | ||||
| service BrainCliService { | ||||
|   rpc CreateVMContract (NewVMReq) returns (NewVMResp); | ||||
|   rpc ListVMContracts (ListVMContractsReq) returns (stream VMContract); | ||||
|   rpc ListNodes (NodeFilters) returns (stream NodeListResp); | ||||
|   rpc GetOneNode (NodeFilters) returns (NodeListResp); | ||||
|   rpc DeleteVM (DeleteVMReq) returns (Empty); | ||||
|   rpc UpdateVM (UpdateVMReq) returns (UpdateVMResp); | ||||
| } | ||||
							
								
								
									
										6
									
								
								build.rs
									
									
									
									
									
										Normal file
									
								
							
							
								
								
								
								
								
									
									
								
							
						
						
									
										6
									
								
								build.rs
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,6 @@ | ||||
| fn main() { | ||||
|     tonic_build::configure() | ||||
|         .build_server(true) | ||||
|         .compile_protos(&["brain.proto"], &["proto"]) | ||||
|         .unwrap_or_else(|e| panic!("Failed to compile protos {:?}", e)); | ||||
| } | ||||
| @ -1,25 +1,24 @@ | ||||
| brain_url: "http://164.92.249.180:31337" | ||||
| max_cores_per_vm: 4 | ||||
| max_vcpu_reservation: 8 | ||||
| max_mem_reservation_mb: 25000 | ||||
| network_interfaces: | ||||
|   - driver: "MACVTAP" | ||||
|     device: "eno8303" | ||||
|     ipv4: | ||||
|       - subnet: "173.234.136.152/29" | ||||
|     ipv4_ranges: | ||||
|       - first_ip: "173.234.136.154" | ||||
|         last_ip: "173.234.136.155" | ||||
|         netmask: "27" | ||||
|         gateway: "173.234.136.158" | ||||
|         reserved_addrs: | ||||
|           - "173.234.136.153" | ||||
|           - "173.234.136.156" | ||||
|           - "173.234.136.157" | ||||
|           - "173.234.136.158" | ||||
|       - subnet: "173.234.137.16/31" | ||||
|       - first_ip: "173.234.137.17" | ||||
|         last_ip: "173.234.137.17" | ||||
|         netmask: "27" | ||||
|         gateway: "173.234.137.30" | ||||
|         reserved_addrs: | ||||
|           - "173.234.137.16" | ||||
|     ipv6: | ||||
|       - subnet: "2a0d:3003:b666:a00c:2::/112" | ||||
|     ipv6_ranges: | ||||
|       - first_ip: "2a0d:3003:b666:a00c:0002:0000:0000:0011" | ||||
|         last_ip: "2a0d:3003:b666:a00c:0002:0000:0000:fffc" | ||||
|         netmask: "64" | ||||
|         gateway: "2a0d:3003:b666:a00c::1" | ||||
|         reserved_addrs: [] | ||||
| volumes: | ||||
|   - path: "/opt/detee_vms/" | ||||
|     max_reservation_gb: 200 | ||||
|  | ||||
							
								
								
									
										3
									
								
								rustfmt.toml
									
									
									
									
									
										Normal file
									
								
							
							
								
								
								
								
								
									
									
								
							
						
						
									
										3
									
								
								rustfmt.toml
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,3 @@ | ||||
| reorder_impl_items = true | ||||
| use_small_heuristics = "Max" | ||||
| imports_granularity = "Crate" | ||||
| @ -1,4 +1,5 @@ | ||||
| #!/bin/bash | ||||
| OVMF_PATH="/var/lib/detee/boot/0346619257269b9a61ee003e197d521b8e2283483070d163a34940d6a1d40d76"; | ||||
| 
 | ||||
| [[ -z "$VM_UUID" ]] && { | ||||
|   echo "Environment variable VM_UUID is not set." | ||||
| @ -65,7 +66,7 @@ qemu-system-x86_64 $qemu_device_params \ | ||||
|     -machine q35,confidential-guest-support=sev0,memory-backend=ram1 \ | ||||
|     -smp $VCPUS,maxcpus=$VCPUS \ | ||||
|     -m $MEMORY,slots=5,maxmem=$MAX_MEMORY \ | ||||
|     -no-reboot -bios /usr/share/edk2/ovmf/OVMF.amdsev.fd \ | ||||
|     -no-reboot -bios "$OVMF_PATH" \ | ||||
|     -drive file=${DISK},if=none,id=disk0,format=qcow2 \ | ||||
|     -device virtio-blk-pci,drive=disk0 \ | ||||
|     -object memory-backend-memfd,id=ram1,size=$MEMORY,share=true,prealloc=false \ | ||||
|  | ||||
							
								
								
									
										114
									
								
								src/config.rs
									
									
									
									
									
								
							
							
								
								
								
								
								
									
									
								
							
						
						
									
										114
									
								
								src/config.rs
									
									
									
									
									
								
							| @ -1,9 +1,10 @@ | ||||
| #![allow(dead_code)] | ||||
| use cidr::{Ipv4Cidr, Ipv6Cidr}; | ||||
| use anyhow::Result; | ||||
| use serde::Deserialize; | ||||
| use std::collections::HashSet; | ||||
| use std::net::{Ipv4Addr, Ipv6Addr}; | ||||
| use std::ops::Range; | ||||
| use std::{ | ||||
|     net::{Ipv4Addr, Ipv6Addr}, | ||||
|     ops::Range, | ||||
| }; | ||||
| 
 | ||||
| #[derive(Deserialize, Debug, Clone)] | ||||
| pub struct Volume { | ||||
| @ -13,24 +14,26 @@ pub struct Volume { | ||||
| 
 | ||||
| #[derive(Deserialize, Debug)] | ||||
| pub struct IPv4Range { | ||||
|     pub subnet: Ipv4Cidr, | ||||
|     pub first_ip: Ipv4Addr, | ||||
|     pub last_ip: Ipv4Addr, | ||||
|     pub netmask: String, | ||||
|     pub gateway: Ipv4Addr, | ||||
|     pub reserved_addrs: HashSet<Ipv4Addr>, | ||||
| } | ||||
| 
 | ||||
| #[derive(Deserialize, Debug)] | ||||
| pub struct IPv6Range { | ||||
|     pub subnet: Ipv6Cidr, | ||||
|     pub first_ip: Ipv6Addr, | ||||
|     pub last_ip: Ipv6Addr, | ||||
|     pub netmask: String, | ||||
|     pub gateway: Ipv6Addr, | ||||
|     pub reserved_addrs: HashSet<Ipv6Addr>, | ||||
| } | ||||
| 
 | ||||
| #[derive(Deserialize, Debug)] | ||||
| pub struct Interface { | ||||
|     pub driver: InterfaceType, | ||||
|     pub device: String, | ||||
|     pub ipv4: Vec<IPv4Range>, | ||||
|     pub ipv6: Vec<IPv6Range>, | ||||
|     pub ipv4_ranges: Vec<IPv4Range>, | ||||
|     pub ipv6_ranges: Vec<IPv6Range>, | ||||
| } | ||||
| 
 | ||||
| #[derive(Deserialize, Debug)] | ||||
| @ -42,6 +45,7 @@ pub enum InterfaceType { | ||||
| 
 | ||||
| #[derive(Deserialize, Debug)] | ||||
| pub struct Config { | ||||
|     pub brain_url: String, | ||||
|     pub max_cores_per_vm: usize, | ||||
|     pub max_vcpu_reservation: usize, | ||||
|     pub max_mem_reservation_mb: usize, | ||||
| @ -60,10 +64,7 @@ mod range_format { | ||||
|     where | ||||
|         S: Serializer, | ||||
|     { | ||||
|         let range_repr = RangeRepr { | ||||
|             start: range.start, | ||||
|             end: range.end, | ||||
|         }; | ||||
|         let range_repr = RangeRepr { start: range.start, end: range.end }; | ||||
|         range_repr.serialize(serializer) | ||||
|     } | ||||
| 
 | ||||
| @ -83,10 +84,93 @@ mod range_format { | ||||
| } | ||||
| 
 | ||||
| impl Config { | ||||
|     pub fn load_from_disk(path: &str) -> Result<Self, Box<dyn std::error::Error>> { | ||||
|     pub fn load_from_disk(path: &str) -> Result<Self> { | ||||
|         let content = std::fs::read_to_string(path)?; | ||||
|         let config: Config = serde_yaml::from_str(&content)?; | ||||
|         for nic in &config.network_interfaces { | ||||
|             for range in &nic.ipv4_ranges { | ||||
|                 let ipv4_netmask = range.netmask.parse::<u8>()?; | ||||
|                 if ipv4_netmask > 32 { | ||||
|                     return Err(anyhow::anyhow!( | ||||
|                         "IPv4 netmask must be in short format: a number from 1 to 32" | ||||
|                     )); | ||||
|                 } | ||||
|                 if range.first_ip.to_bits() > range.last_ip.to_bits() { | ||||
|                     return Err(anyhow::anyhow!( | ||||
|                         "For range {range:?} first ip is bigger than last ip." | ||||
|                     )); | ||||
|                 } | ||||
|                 let expected_netmask = std::cmp::min( | ||||
|                     calc_ipv4_netmask(range.first_ip, range.gateway), | ||||
|                     calc_ipv4_netmask(range.last_ip, range.gateway), | ||||
|                 ); | ||||
|                 if expected_netmask < ipv4_netmask as u32 { | ||||
|                     return Err(anyhow::anyhow!( | ||||
|                         "Your netmask is too small to include the IPs and also the gateway: {range:?}" | ||||
|                     )); | ||||
|                 } | ||||
|             } | ||||
|             for range in &nic.ipv6_ranges { | ||||
|                 let ipv6_netmask = range.netmask.parse::<u8>()?; | ||||
|                 if ipv6_netmask > 128 { | ||||
|                     return Err(anyhow::anyhow!( | ||||
|                         "IPv6 netmask must be in short format: a number from 1 to 128" | ||||
|                     )); | ||||
|                 } | ||||
|                 if range.first_ip.to_bits() > range.last_ip.to_bits() { | ||||
|                     return Err(anyhow::anyhow!( | ||||
|                         "For range {range:?} first ip is bigger than last ip." | ||||
|                     )); | ||||
|                 } | ||||
|                 let expected_netmask = std::cmp::min( | ||||
|                     calc_ipv6_netmask(range.first_ip, range.gateway), | ||||
|                     calc_ipv6_netmask(range.last_ip, range.gateway), | ||||
|                 ); | ||||
|                 if expected_netmask < ipv6_netmask as u128 { | ||||
|                     return Err(anyhow::anyhow!( | ||||
|                         "Your netmask is too small to include the IPs and also the gateway: {range:?}" | ||||
|                     )); | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|         Ok(config) | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| fn calc_ipv4_netmask(ip: Ipv4Addr, gateway: Ipv4Addr) -> u32 { | ||||
|     // Convert the IPs to u32 for easier bit manipulation
 | ||||
|     let ip_u32 = u32::from(ip); | ||||
|     let gateway_u32 = u32::from(gateway); | ||||
| 
 | ||||
|     // Find the smallest common prefix
 | ||||
|     let mut prefix_len = 0; | ||||
|     for i in 1..=32 { | ||||
|         if (ip_u32 >> (32 - i)) == (gateway_u32 >> (32 - i)) { | ||||
|             prefix_len = i; | ||||
|         } else { | ||||
|             break; | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     // Return the mask as a string
 | ||||
|     prefix_len | ||||
| } | ||||
| 
 | ||||
| fn calc_ipv6_netmask(ip: Ipv6Addr, gateway: Ipv6Addr) -> u128 { | ||||
|     // Convert the IPs to u128 for easier bit manipulation
 | ||||
|     let ip_u128 = u128::from(ip); | ||||
|     let gateway_u128 = u128::from(gateway); | ||||
| 
 | ||||
|     // Find the smallest common prefix
 | ||||
|     let mut prefix_len = 0; | ||||
|     for i in 1..=128 { | ||||
|         if (ip_u128 >> (128 - i)) == (gateway_u128 >> (128 - i)) { | ||||
|             prefix_len = i; | ||||
|         } else { | ||||
|             break; | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     // Return the mask as a string
 | ||||
|     prefix_len | ||||
| } | ||||
|  | ||||
| @ -2,9 +2,13 @@ | ||||
| 
 | ||||
| pub(crate) const DEFAULT_OVMF: &str = "/usr/share/edk2/ovmf/OVMF.amdsev.fd"; | ||||
| pub(crate) const VM_BOOT_DIR: &str = "/var/lib/detee/boot/"; | ||||
| pub(crate) const USED_RESOURCES: &str = "/etc/detee/daemon/used_resources.yaml"; 
 | ||||
| pub(crate) const VM_CONFIG_DIR: &str = "/etc/detee/daemon/vms/"; 
 | ||||
| pub(crate) const USED_RESOURCES: &str = "/etc/detee/daemon/used_resources.yaml"; | ||||
| pub(crate) const VM_CONFIG_DIR: &str = "/etc/detee/daemon/vms/"; | ||||
| pub(crate) const SECRET_KEY_PATH: &str = "/etc/detee/daemon/node_secret_key.pem"; | ||||
| pub(crate) const DAEMON_CONFIG_PATH: &str = "/etc/detee/daemon/config.yaml"; | ||||
| pub(crate) const START_VM_SCRIPT: &str = "/usr/local/bin/detee/start_qemu_vm.sh"; | ||||
| // TODO: research if other CPU types provide better performance
 | ||||
| pub(crate) const QEMU_VM_CPU_TYPE: &str = "EPYC-v4"; | ||||
| // If you modify this, also modify scripts/start_qemu_vm.sh
 | ||||
| pub(crate) const OVMF_HASH: &str = "0346619257269b9a61ee003e197d521b8e2283483070d163a34940d6a1d40d76"; | ||||
| pub(crate) const OVMF_URL: &str = "https://drive.google.com/uc?export=download&id=1V-vLkaiLaGmFSjrN84Z6nELQOxKNAoSJ"; | ||||
|  | ||||
							
								
								
									
										226
									
								
								src/grpc.rs
									
									
									
									
									
										Normal file
									
								
							
							
								
								
								
								
								
									
									
								
							
						
						
									
										226
									
								
								src/grpc.rs
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,226 @@ | ||||
| #![allow(dead_code)] | ||||
| pub mod brain { | ||||
|     tonic::include_proto!("brain"); | ||||
| } | ||||
| 
 | ||||
| use anyhow::Result; | ||||
| use brain::{ | ||||
|     brain_daemon_service_client::BrainDaemonServiceClient, DeleteVmReq, ListVmContractsReq, | ||||
|     NewVmReq, NewVmResp, NodePubkey, NodeResourceReq, RegisterNodeReq, UpdateVmReq, UpdateVmResp, | ||||
|     VmContract, | ||||
| }; | ||||
| use lazy_static::lazy_static; | ||||
| use log::{debug, error, info, warn}; | ||||
| use std::{fs::File, io::Write}; | ||||
| use tokio::{ | ||||
|     sync::mpsc::{Receiver, Sender}, | ||||
|     task::JoinSet, | ||||
| }; | ||||
| use tokio_stream::{wrappers::ReceiverStream, StreamExt}; | ||||
| use tonic::transport::Channel; | ||||
| 
 | ||||
| lazy_static! { | ||||
|     static ref PUBLIC_KEY: String = get_public_key(); | ||||
| } | ||||
| 
 | ||||
| fn create_secret_key() -> Result<ed25519_dalek::SigningKey> { | ||||
|     use ed25519_dalek::pkcs8::{spki::der::pem::LineEnding, EncodePrivateKey}; | ||||
|     let key_path = crate::constants::SECRET_KEY_PATH; | ||||
|     info!("Creating new secret key at {}", key_path); | ||||
|     let sk = ed25519_dalek::SigningKey::generate(&mut rand_core::OsRng); | ||||
|     let sk_pem = sk.to_pkcs8_pem(LineEnding::default()).unwrap(); | ||||
|     let mut file = File::create(key_path)?; | ||||
|     file.write_all(sk_pem.as_bytes())?; | ||||
|     Ok(sk) | ||||
| } | ||||
| 
 | ||||
| fn load_secret_key() -> Result<ed25519_dalek::SigningKey> { | ||||
|     use ed25519_dalek::pkcs8::DecodePrivateKey; | ||||
|     let secret_key_pem = match std::fs::read_to_string(crate::constants::SECRET_KEY_PATH) { | ||||
|         Ok(secret_key_pem) => secret_key_pem, | ||||
|         Err(e) => { | ||||
|             warn!("Could not load secret key due to error: {e:?}"); | ||||
|             return Ok(create_secret_key()?); | ||||
|         } | ||||
|     }; | ||||
|     Ok(ed25519_dalek::SigningKey::from_pkcs8_pem(&secret_key_pem)?) | ||||
| } | ||||
| 
 | ||||
| pub fn get_public_key() -> String { | ||||
|     use ed25519_dalek::pkcs8::{spki::der::pem::LineEnding, EncodePublicKey}; | ||||
|     let pubkey = load_secret_key() | ||||
|         .unwrap() | ||||
|         .verifying_key() | ||||
|         .to_public_key_pem(LineEnding::default()) | ||||
|         .unwrap() | ||||
|         .lines() | ||||
|         .nth(1) | ||||
|         .unwrap() | ||||
|         .to_string(); | ||||
|     log::info!("Loaded the following public key: {pubkey}"); | ||||
|     pubkey | ||||
| } | ||||
| 
 | ||||
| pub async fn list_contracts(brain_url: String) -> Result<Vec<VmContract>> { | ||||
|     let mut client = BrainDaemonServiceClient::connect(brain_url).await?; | ||||
|     let mut contracts = Vec::new(); | ||||
|     let mut grpc_stream = client | ||||
|         .list_vm_contracts(ListVmContractsReq { | ||||
|             node_pubkey: PUBLIC_KEY.to_string(), | ||||
|             ..Default::default() | ||||
|         }) | ||||
|         .await? | ||||
|         .into_inner(); | ||||
|     while let Some(stream_update) = grpc_stream.next().await { | ||||
|         match stream_update { | ||||
|             Ok(node) => { | ||||
|                 debug!("Received contract from brain: {node:?}"); | ||||
|                 contracts.push(node); | ||||
|             } | ||||
|             Err(e) => { | ||||
|                 warn!("Received error instead of contracts: {e:?}"); | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|     info!("Brain terminated list_contracts stream."); | ||||
|     Ok(contracts) | ||||
| } | ||||
| 
 | ||||
| async fn listen_for_new_vm_reqs( | ||||
|     mut client: BrainDaemonServiceClient<Channel>, | ||||
|     tx: Sender<NewVmReq>, | ||||
| ) -> Result<()> { | ||||
|     debug!("starting listen_for_new_vm_reqs"); | ||||
|     let node_pubkey = PUBLIC_KEY.clone(); | ||||
|     let mut grpc_stream = client.get_new_vm_reqs(NodePubkey { node_pubkey }).await?.into_inner(); | ||||
|     while let Some(stream_update) = grpc_stream.next().await { | ||||
|         match stream_update { | ||||
|             Ok(req) => { | ||||
|                 info!("Received new vm request: {req:?}"); | ||||
|                 let _ = tx.send(req).await; | ||||
|             } | ||||
|             Err(e) => { | ||||
|                 warn!("Brain disconnected from listen_for_new_vm_reqs: {e}"); | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|     debug!("listen_for_new_vm_reqs is about to exit"); | ||||
|     Ok(()) | ||||
| } | ||||
| 
 | ||||
| async fn send_newvm_resp( | ||||
|     mut client: BrainDaemonServiceClient<Channel>, | ||||
|     rx: Receiver<NewVmResp>, | ||||
| ) -> Result<()> { | ||||
|     debug!("starting send_newvm_resp stream"); | ||||
|     let rx_stream = ReceiverStream::new(rx); | ||||
|     client.send_new_vm_resp(rx_stream).await?; | ||||
|     debug!("send_newvm_resp is about to exit"); | ||||
|     Ok(()) | ||||
| } | ||||
| 
 | ||||
| async fn send_node_resources( | ||||
|     mut client: BrainDaemonServiceClient<Channel>, | ||||
|     rx: Receiver<NodeResourceReq>, | ||||
| ) -> Result<()> { | ||||
|     debug!("starting send_newvm_resp stream"); | ||||
|     let rx_stream = ReceiverStream::new(rx).map(|mut node_resources| { | ||||
|         node_resources.node_pubkey = get_public_key(); | ||||
|         node_resources | ||||
|     }); | ||||
|     client.send_node_resources(rx_stream).await?; | ||||
|     debug!("send_newvm_resp is about to exit"); | ||||
|     Ok(()) | ||||
| } | ||||
| 
 | ||||
| async fn register_node(mut client: BrainDaemonServiceClient<Channel>) { | ||||
|     debug!("Starting node registration..."); | ||||
|     let req = RegisterNodeReq { | ||||
|         node_pubkey: PUBLIC_KEY.clone(), | ||||
|         owner_pubkey: "IamTheOwnerOf".to_string() + &PUBLIC_KEY, | ||||
|     }; | ||||
|     match client.register_node(req).await { | ||||
|         Ok(_) => { | ||||
|             info!("Registered as 10.0.10.1 from Bruma/Cyrodiil with ID {}", PUBLIC_KEY.clone()) | ||||
|         } | ||||
|         Err(e) => error!("Could not register node data: {e:?}"), | ||||
|     }; | ||||
| } | ||||
| 
 | ||||
| async fn listen_for_deleted_vms( | ||||
|     mut client: BrainDaemonServiceClient<Channel>, | ||||
|     tx: Sender<DeleteVmReq>, | ||||
| ) -> Result<()> { | ||||
|     debug!("starting listen_for_new_vm_reqs"); | ||||
|     let node_pubkey = PUBLIC_KEY.clone(); | ||||
|     let mut grpc_stream = client.get_delete_vm_req(NodePubkey { node_pubkey }).await?.into_inner(); | ||||
|     while let Some(stream_update) = grpc_stream.next().await { | ||||
|         match stream_update { | ||||
|             Ok(req) => { | ||||
|                 info!("Received delete vm request: {req:?}"); | ||||
|                 let _ = tx.send(req).await; | ||||
|             } | ||||
|             Err(e) => { | ||||
|                 warn!("Brain disconnected from listen_for_deleted_vms: {e}"); | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|     debug!("listen_for_new_vm_reqs is about to exit"); | ||||
|     Ok(()) | ||||
| } | ||||
| 
 | ||||
| async fn listen_for_update_vm_reqs( | ||||
|     mut client: BrainDaemonServiceClient<Channel>, | ||||
|     tx: Sender<UpdateVmReq>, | ||||
| ) -> Result<()> { | ||||
|     debug!("starting listen_for_update_vm_reqs"); | ||||
|     let node_pubkey = PUBLIC_KEY.clone(); | ||||
|     let mut grpc_stream = client.get_update_vm_req(NodePubkey { node_pubkey }).await?.into_inner(); | ||||
|     while let Some(stream_update) = grpc_stream.next().await { | ||||
|         match stream_update { | ||||
|             Ok(req) => { | ||||
|                 info!("Received update vm request: {req:?}"); | ||||
|                 let _ = tx.send(req).await; | ||||
|             } | ||||
|             Err(e) => { | ||||
|                 warn!("Brain disconnected from listen_for_update_vm_reqs: {e}"); | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|     debug!("listen_for_update_vm_reqs is about to exit"); | ||||
|     Ok(()) | ||||
| } | ||||
| 
 | ||||
| async fn send_updatevm_resp( | ||||
|     mut client: BrainDaemonServiceClient<Channel>, | ||||
|     rx: Receiver<UpdateVmResp>, | ||||
| ) -> Result<()> { | ||||
|     debug!("starting send_updatevm_resp stream"); | ||||
|     let rx_stream = ReceiverStream::new(rx); | ||||
|     client.send_update_vm_resp(rx_stream).await?; | ||||
|     debug!("send_updatevm_resp is about to exit"); | ||||
|     Ok(()) | ||||
| } | ||||
| 
 | ||||
| pub struct ConnectionData { | ||||
|     pub brain_url: String, | ||||
|     pub newvm_tx: Sender<NewVmReq>, | ||||
|     pub confirm_vm_rx: Receiver<NewVmResp>, | ||||
|     pub delete_vm_tx: Sender<DeleteVmReq>, | ||||
|     pub resources_rx: Receiver<NodeResourceReq>, | ||||
| } | ||||
| 
 | ||||
| pub async fn connect_and_run(cd: ConnectionData) -> Result<()> { | ||||
|     let client = BrainDaemonServiceClient::connect(cd.brain_url).await?; | ||||
|     let mut streaming_tasks = JoinSet::new(); | ||||
| 
 | ||||
|     register_node(client.clone()).await; | ||||
|     streaming_tasks.spawn(listen_for_new_vm_reqs(client.clone(), cd.newvm_tx)); | ||||
|     streaming_tasks.spawn(send_newvm_resp(client.clone(), cd.confirm_vm_rx)); | ||||
|     streaming_tasks.spawn(listen_for_deleted_vms(client.clone(), cd.delete_vm_tx)); | ||||
|     streaming_tasks.spawn(send_node_resources(client.clone(), cd.resources_rx)); | ||||
| 
 | ||||
|     let task_output = streaming_tasks.join_next().await; | ||||
|     warn!("One stream exited: {task_output:?}"); | ||||
|     Ok(()) | ||||
| } | ||||
							
								
								
									
										284
									
								
								src/main.rs
									
									
									
									
									
								
							
							
								
								
								
								
								
									
									
								
							
						
						
									
										284
									
								
								src/main.rs
									
									
									
									
									
								
							| @ -1,62 +1,234 @@ | ||||
| #[allow(dead_code)] | ||||
| mod config; | ||||
| mod constants; | ||||
| mod grpc; | ||||
| mod state; | ||||
| mod tcontract; | ||||
| 
 | ||||
| use crate::config::Config; | ||||
| use crate::state::NewVMRequest; | ||||
| use crate::state::UpdateVMReq; | ||||
| use std::fs::read_dir; | ||||
| use crate::{config::Config, grpc::brain}; | ||||
| use anyhow::Result; | ||||
| use log::{debug, info, warn}; | ||||
| use tokio::{ | ||||
|     sync::mpsc::{Receiver, Sender}, | ||||
|     time::{sleep, Duration}, | ||||
| }; | ||||
| 
 | ||||
| fn main() -> Result<(), Box<dyn std::error::Error>> { | ||||
|     let config = Config::load_from_disk(crate::constants::DAEMON_CONFIG_PATH)?; | ||||
|     let mut res = match state::Resources::load_from_disk() { | ||||
|         Ok(res) => res, | ||||
|         Err(e) => { | ||||
|             println!("Could not load resources from disk: {e:?}"); | ||||
|             println!("Creating new resource calculator."); | ||||
|             state::Resources::new(&config.volumes) | ||||
|         } | ||||
|     }; | ||||
| 
 | ||||
|     for entry in read_dir("/etc/detee/daemon/newvmreq/")? { | ||||
|         let entry = entry?; | ||||
|         let path = entry.path(); | ||||
|         if path.is_file() { | ||||
|             let new_vm_req = NewVMRequest::from_file(path.to_str().unwrap())?; | ||||
|             let vm = state::VM::new(new_vm_req, &config, &mut res).unwrap(); | ||||
|             vm.start()?; | ||||
|             println!("started vm {}", vm.uuid); | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     for entry in read_dir("/etc/detee/daemon/deletevm/")? { | ||||
|         let entry = entry?; | ||||
|         let path = entry.path(); | ||||
|         if path.is_file() { | ||||
|             let vm_id = path.file_name().unwrap().to_str().unwrap(); | ||||
|             let content = std::fs::read_to_string( | ||||
|                 crate::constants::VM_CONFIG_DIR.to_string() + vm_id + ".yaml", | ||||
|             )?; | ||||
|             let vm: crate::state::VM = serde_yaml::from_str(&content)?; | ||||
|             vm.delete(&mut res)?; | ||||
|             println!("deleted vm {}", vm.uuid); | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     for entry in read_dir("/etc/detee/daemon/updatedvmreq/")? { | ||||
|         let entry = entry?; | ||||
|         let path = entry.path(); | ||||
|         if path.is_file() { | ||||
|             let update_vm_req = UpdateVMReq::from_file(path.to_str().unwrap())?; | ||||
|             let content = std::fs::read_to_string( | ||||
|                 crate::constants::VM_CONFIG_DIR.to_string() + &update_vm_req.uuid + ".yaml", | ||||
|             )?; | ||||
|             let mut vm: crate::state::VM = serde_yaml::from_str(&content)?; | ||||
|             vm.update(update_vm_req, &config, &mut res).unwrap(); | ||||
|             println!("updated vm {}", vm.uuid); | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     Ok(()) | ||||
| #[allow(dead_code)] | ||||
| struct VMHandler { | ||||
|     new_vm_req_chan: Receiver<brain::NewVmReq>, | ||||
|     new_vm_resp_chan: Sender<brain::NewVmResp>, | ||||
|     delete_vm_chan: Receiver<brain::DeleteVmReq>, | ||||
|     resources_chan: Sender<brain::NodeResourceReq>, | ||||
|     config: Config, | ||||
|     res: state::Resources, | ||||
| } | ||||
| 
 | ||||
| #[allow(dead_code)] | ||||
| impl VMHandler { | ||||
|     fn new( | ||||
|         new_vm_req_chan: Receiver<brain::NewVmReq>, | ||||
|         new_vm_resp_chan: Sender<brain::NewVmResp>, | ||||
|         delete_vm_chan: Receiver<brain::DeleteVmReq>, | ||||
|         resources_chan: Sender<brain::NodeResourceReq>, | ||||
|     ) -> Self { | ||||
|         let config = match Config::load_from_disk(crate::constants::DAEMON_CONFIG_PATH) { | ||||
|             Ok(config) => config, | ||||
|             Err(e) => panic!("Could not load config: {e:?}"), | ||||
|         }; | ||||
|         let res = match state::Resources::load_from_disk() { | ||||
|             Ok(res) => res, | ||||
|             Err(e) => { | ||||
|                 warn!("Could not load resources from disk: {e:?}"); | ||||
|                 info!("Creating new resource calculator."); | ||||
|                 state::Resources::new(&config.volumes) | ||||
|             } | ||||
|         }; | ||||
|         Self { new_vm_req_chan, new_vm_resp_chan, delete_vm_chan, resources_chan, config, res } | ||||
|     } | ||||
| 
 | ||||
|     fn get_available_ips(&self) -> (u32, u32) { | ||||
|         let mut avail_ipv4 = 0; | ||||
|         let mut avail_ipv6 = 0; | ||||
|         for nic in self.config.network_interfaces.iter() { | ||||
|             for range in nic.ipv4_ranges.iter() { | ||||
|                 avail_ipv4 += (range.last_ip.to_bits() + 1) - range.first_ip.to_bits(); | ||||
|             } | ||||
|             for range in nic.ipv6_ranges.iter() { | ||||
|                 avail_ipv6 += (range.last_ip.to_bits() + 1) - range.first_ip.to_bits(); | ||||
|             } | ||||
|         } | ||||
|         ( | ||||
|             avail_ipv4.saturating_sub(self.res.reserved_ipv4.len() as u32), | ||||
|             avail_ipv6.saturating_sub(self.res.reserved_ipv6.len() as u128) as u32, | ||||
|         ) | ||||
|     } | ||||
| 
 | ||||
|     async fn send_node_resources(&mut self) { | ||||
|         let (avail_ipv4, avail_ipv6) = self.get_available_ips(); | ||||
|         let mut avail_storage_gb = 0; | ||||
|         for volume in self.config.volumes.iter() { | ||||
|             avail_storage_gb += volume.max_reservation_gb; | ||||
|             if let Some(reservation) = self.res.reserved_storage.get(&volume.path) { | ||||
|                 avail_storage_gb -= reservation; | ||||
|             } | ||||
|         } | ||||
|         let avail_storage_gb = avail_storage_gb as u32; | ||||
|         let res = brain::NodeResourceReq { | ||||
|             node_pubkey: String::new(), | ||||
|             avail_ports: (self.config.public_port_range.len() - self.res.reserved_ports.len()) | ||||
|                 as u32, | ||||
|             avail_ipv4, | ||||
|             avail_ipv6, | ||||
|             avail_vcpus: (self.config.max_vcpu_reservation - self.res.reserved_vcpus) as u32, | ||||
|             avail_memory_mb: (self.config.max_mem_reservation_mb - self.res.reserved_memory) as u32, | ||||
|             avail_storage_gb, | ||||
|             max_ports_per_vm: self.config.max_ports_per_vm as u32, | ||||
|         }; | ||||
|         debug!("sending node resources on brain: {res:?}"); | ||||
|         let _ = self.resources_chan.send(res).await; | ||||
|     } | ||||
| 
 | ||||
|     async fn handle_new_vm_req(&mut self, new_vm_req: brain::NewVmReq) { | ||||
|         debug!("Processing new vm request: {new_vm_req:?}"); | ||||
|         let uuid = new_vm_req.uuid.clone(); | ||||
|         match state::VM::new(new_vm_req.into(), &self.config, &mut self.res) { | ||||
|             Ok(vm) => match vm.start() { | ||||
|                 Ok(_) => { | ||||
|                     info!("Succesfully started VM {uuid}"); | ||||
|                     let _ = self.new_vm_resp_chan.send(vm.into()).await; | ||||
|                     self.send_node_resources().await; | ||||
|                 } | ||||
|                 Err(e) => { | ||||
|                     log::error!("Could not start VM {uuid}: {e:?}"); | ||||
|                     let _ = self | ||||
|                         .new_vm_resp_chan | ||||
|                         .send(brain::NewVmResp { | ||||
|                             uuid, | ||||
|                             error: "This node has an internal error. Choose another node." | ||||
|                                 .to_string(), | ||||
|                             ..Default::default() | ||||
|                         }) | ||||
|                         .await; | ||||
|                 } | ||||
|             }, | ||||
|             Err(e) => match e { | ||||
|                 crate::state::VMCreationErrors::VMAlreadyExists(vm) => { | ||||
|                     log::info!( | ||||
|                         "Got NewVmReq for VM {}, that already exist. Will send NewVmResp.", | ||||
|                         vm.uuid | ||||
|                     ); | ||||
|                     let _ = self.new_vm_resp_chan.send(vm.into()).await; | ||||
|                 } | ||||
|                 _ => { | ||||
|                     warn!("Refusing to service vm {uuid} due to error: {e:?}"); | ||||
|                     let _ = self | ||||
|                         .new_vm_resp_chan | ||||
|                         .send(brain::NewVmResp { | ||||
|                             uuid, | ||||
|                             error: format!("{e:?}"), | ||||
|                             ..Default::default() | ||||
|                         }) | ||||
|                         .await; | ||||
|                 } | ||||
|             }, | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     fn handle_delete_vm(&mut self, delete_vm_req: brain::DeleteVmReq) -> Result<()> { | ||||
|         let vm_id = delete_vm_req.uuid; | ||||
|         let content = | ||||
|             std::fs::read_to_string(constants::VM_CONFIG_DIR.to_string() + &vm_id + ".yaml")?; | ||||
|         let vm: state::VM = serde_yaml::from_str(&content)?; | ||||
|         vm.delete(&mut self.res)?; | ||||
|         Ok(()) | ||||
|     } | ||||
| 
 | ||||
|     async fn run(mut self) { | ||||
|         self.send_node_resources().await; | ||||
|         loop { | ||||
|             tokio::select! { | ||||
|                 Some(new_vm_req) = self.new_vm_req_chan.recv() => { | ||||
|                     self.handle_new_vm_req(new_vm_req).await; | ||||
|                 } | ||||
|                 Some(delete_vm_req) = self.delete_vm_chan.recv() => { | ||||
|                     let uuid = delete_vm_req.uuid.clone(); | ||||
|                     if let Err(e) = self.handle_delete_vm(delete_vm_req) { | ||||
|                         log::error!("Could not delete vm {uuid}: {e:?}"); | ||||
|                     } else { | ||||
|                         self.send_node_resources().await; | ||||
|                     } | ||||
|                 } | ||||
|                 else => { | ||||
|                     log::error!("All data channels closed."); | ||||
|                     return; | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     fn clear_deleted_contracts(&mut self, contracts: Vec<brain::VmContract>) { | ||||
|         for uuid in self.res.existing_vms.clone() { | ||||
|             if contracts.iter().find(|c| c.uuid == uuid).is_none() { | ||||
|                 info!("VM {uuid} exists locally but not found in brain. Deleting..."); | ||||
|                 let content = match std::fs::read_to_string( | ||||
|                     crate::constants::VM_CONFIG_DIR.to_string() + &uuid + ".yaml", | ||||
|                 ) { | ||||
|                     Ok(content) => content, | ||||
|                     Err(e) => { | ||||
|                         log::error!("Could not find VM config for {uuid}. Cannot delete VM: {e:?}"); | ||||
|                         continue; | ||||
|                     } | ||||
|                 }; | ||||
|                 let vm: crate::state::VM = match serde_yaml::from_str(&content) { | ||||
|                     Ok(vm) => vm, | ||||
|                     Err(e) => { | ||||
|                         log::error!("VM config corrupted for {uuid}. Cannot delete VM: {e:?}"); | ||||
|                         continue; | ||||
|                     } | ||||
|                 }; | ||||
|                 match vm.delete(&mut self.res) { | ||||
|                     Ok(()) => info!("Successfully deleted VM {uuid}"), | ||||
|                     Err(e) => log::error!("Deletion failed for VM {uuid}: {e:?}"), | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| #[tokio::main] | ||||
| async fn main() { | ||||
|     env_logger::builder().filter_level(log::LevelFilter::Debug).init(); | ||||
| 
 | ||||
|     loop { | ||||
|         let (newvm_tx, newvm_rx) = tokio::sync::mpsc::channel(6); | ||||
|         let (confirm_vm_tx, confirm_vm_rx) = tokio::sync::mpsc::channel(6); | ||||
|         let (delete_vm_tx, delete_vm_rx) = tokio::sync::mpsc::channel(6); | ||||
|         let (resources_tx, resources_rx) = tokio::sync::mpsc::channel(6); | ||||
| 
 | ||||
|         let mut vm_handler = VMHandler::new(newvm_rx, confirm_vm_tx, delete_vm_rx, resources_tx); | ||||
|         let brain_url = vm_handler.config.brain_url.clone(); | ||||
| 
 | ||||
|         info!("Trying to get VM Contracts from Brain to see if some Contracts got removed..."); | ||||
|         match grpc::list_contracts(brain_url.clone()).await { | ||||
|             Ok(contracts) => vm_handler.clear_deleted_contracts(contracts), | ||||
|             Err(e) => log::error!("Could not get contracts from brain: {e:?}"), | ||||
|         }; | ||||
| 
 | ||||
|         tokio::spawn(async move { | ||||
|             vm_handler.run().await; | ||||
|         }); | ||||
| 
 | ||||
|         info!("Connecting to brain..."); | ||||
|         if let Err(e) = grpc::connect_and_run(grpc::ConnectionData { | ||||
|             brain_url, | ||||
|             newvm_tx, | ||||
|             confirm_vm_rx, | ||||
|             delete_vm_tx, | ||||
|             resources_rx, | ||||
|         }) | ||||
|         .await | ||||
|         { | ||||
|             log::error!("The connection broke: {e}"); | ||||
|         } | ||||
|         sleep(Duration::from_secs(3)).await; | ||||
|     } | ||||
| } | ||||
|  | ||||
							
								
								
									
										355
									
								
								src/state.rs
									
									
									
									
									
								
							
							
								
								
								
								
								
									
									
								
							
						
						
									
										355
									
								
								src/state.rs
									
									
									
									
									
								
							| @ -1,32 +1,28 @@ | ||||
| #![allow(dead_code)] | ||||
| use crate::config::Config; | ||||
| use crate::constants::*; | ||||
| use anyhow::anyhow; | ||||
| use anyhow::Result; | ||||
| use serde::Deserialize; | ||||
| use serde::Serialize; | ||||
| use crate::{config::Config, constants::*, grpc::brain}; | ||||
| use anyhow::{anyhow, Result}; | ||||
| use serde::{Deserialize, Serialize}; | ||||
| use sha2::{Digest, Sha256}; | ||||
| use std::collections::HashMap; | ||||
| use std::collections::HashSet; | ||||
| use std::fs; | ||||
| use std::fs::remove_file; | ||||
| use std::fs::File; | ||||
| use std::io::Read; | ||||
| use std::io::Write; | ||||
| use std::net::{Ipv4Addr, Ipv6Addr}; | ||||
| use std::path::Path; | ||||
| use std::process::Command; | ||||
| use std::{ | ||||
|     collections::{HashMap, HashSet}, | ||||
|     fs, | ||||
|     fs::{remove_file, File}, | ||||
|     io::{Read, Write}, | ||||
|     path::Path, | ||||
|     process::Command, | ||||
| }; | ||||
| 
 | ||||
| #[derive(Serialize, Deserialize, Debug)] | ||||
| pub struct Resources { | ||||
|     existing_vms: HashSet<String>, | ||||
|     pub existing_vms: HashSet<String>, | ||||
|     // QEMU does not support MHz limiation
 | ||||
|     reserved_vcpus: usize, | ||||
|     reserved_memory: usize, | ||||
|     reserved_ports: HashSet<u16>, | ||||
|     reserved_storage: HashMap<String, usize>, | ||||
|     reserved_ips: HashSet<String>, | ||||
|     reserved_if_names: HashSet<String>, | ||||
|     pub reserved_vcpus: usize, | ||||
|     pub reserved_memory: usize, | ||||
|     pub reserved_ports: HashSet<u16>, | ||||
|     pub reserved_storage: HashMap<String, usize>, | ||||
|     pub reserved_ipv4: HashSet<String>, | ||||
|     pub reserved_ipv6: HashSet<String>, | ||||
|     pub reserved_if_names: HashSet<String>, | ||||
|     // sha256sum -> absolute path
 | ||||
|     boot_files: HashSet<String>, | ||||
| } | ||||
| @ -60,7 +56,8 @@ impl Resources { | ||||
|             reserved_memory: 0, | ||||
|             reserved_ports: HashSet::new(), | ||||
|             reserved_storage: HashMap::new(), | ||||
|             reserved_ips: HashSet::new(), | ||||
|             reserved_ipv4: HashSet::new(), | ||||
|             reserved_ipv6: HashSet::new(), | ||||
|             reserved_if_names: HashSet::new(), | ||||
|             boot_files: HashSet::new(), | ||||
|         }; | ||||
| @ -111,11 +108,8 @@ impl Resources { | ||||
|     fn available_if_name(&mut self) -> String { | ||||
|         use rand::{distributions::Alphanumeric, Rng}; | ||||
|         loop { | ||||
|             let mut interface_name: String = rand::thread_rng() | ||||
|                 .sample_iter(&Alphanumeric) | ||||
|                 .take(9) | ||||
|                 .map(char::from) | ||||
|                 .collect(); | ||||
|             let mut interface_name: String = | ||||
|                 rand::thread_rng().sample_iter(&Alphanumeric).take(9).map(char::from).collect(); | ||||
|             interface_name = "detee".to_string() + &interface_name; | ||||
|             if !self.reserved_if_names.contains(&interface_name) { | ||||
|                 return interface_name; | ||||
| @ -123,13 +117,15 @@ impl Resources { | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     fn available_ipv4(&mut self, config: &Config) -> Option<VMNIC> { | ||||
|         for nic in config.network_interfaces.iter() { | ||||
|             for range in nic.ipv4.iter() { | ||||
|                 for ip in range.subnet.iter().skip(1) { | ||||
|                     if !range.reserved_addrs.contains(&ip.address()) | ||||
|                         && !self.reserved_ips.contains(&ip.address().to_string()) | ||||
|                         && ip.address() != range.gateway | ||||
|     fn available_ipv4(&mut self, nics: &Vec<crate::config::Interface>) -> Option<VMNIC> { | ||||
|         for nic in nics.iter() { | ||||
|             for range in nic.ipv4_ranges.iter() { | ||||
|                 let first_ip = range.first_ip.to_bits(); | ||||
|                 let last_ip = range.last_ip.to_bits(); | ||||
|                 for ip in first_ip..last_ip + 1 { | ||||
|                     let ip_addr = std::net::Ipv4Addr::from_bits(ip); | ||||
|                     if !self.reserved_ipv4.contains(&ip_addr.to_string()) | ||||
|                         && ip_addr != range.gateway | ||||
|                     { | ||||
|                         let if_config = match nic.driver { | ||||
|                             crate::config::InterfaceType::MACVTAP => InterfaceConfig::MACVTAP { | ||||
| @ -140,14 +136,14 @@ impl Resources { | ||||
|                                 name: self.available_if_name(), | ||||
|                                 device: nic.device.clone(), | ||||
|                             }, | ||||
|                             crate::config::InterfaceType::Bridge => InterfaceConfig::Bridge { | ||||
|                                 device: nic.device.clone(), | ||||
|                             }, | ||||
|                             crate::config::InterfaceType::Bridge => { | ||||
|                                 InterfaceConfig::Bridge { device: nic.device.clone() } | ||||
|                             } | ||||
|                         }; | ||||
|                         let mut ips = Vec::new(); | ||||
|                         ips.push(IPConfig { | ||||
|                             address: ip.address().to_string(), | ||||
|                             mask: calc_ipv4_netmask(ip.address(), range.gateway), | ||||
|                             address: ip_addr.to_string(), | ||||
|                             mask: range.netmask.clone(), | ||||
|                             gateway: range.gateway.to_string(), | ||||
|                         }); | ||||
|                         return Some(VMNIC { if_config, ips }); | ||||
| @ -158,13 +154,15 @@ impl Resources { | ||||
|         None | ||||
|     } | ||||
| 
 | ||||
|     fn available_ipv6(&mut self, config: &Config) -> Option<VMNIC> { | ||||
|         for nic in config.network_interfaces.iter() { | ||||
|             for range in nic.ipv6.iter() { | ||||
|                 for ip in range.subnet.iter().skip(1) { | ||||
|                     if !range.reserved_addrs.contains(&ip.address()) | ||||
|                         && !self.reserved_ips.contains(&ip.address().to_string()) | ||||
|                         && ip.address() != range.gateway | ||||
|     fn available_ipv6(&mut self, nics: &Vec<crate::config::Interface>) -> Option<VMNIC> { | ||||
|         for nic in nics.iter() { | ||||
|             for range in nic.ipv6_ranges.iter() { | ||||
|                 let first_ip = range.first_ip.to_bits(); | ||||
|                 let last_ip = range.last_ip.to_bits(); | ||||
|                 for ip in first_ip..last_ip + 1 { | ||||
|                     let ip_addr = std::net::Ipv6Addr::from_bits(ip); | ||||
|                     if !self.reserved_ipv6.contains(&ip_addr.to_string()) | ||||
|                         && ip_addr != range.gateway | ||||
|                     { | ||||
|                         let if_config = match nic.driver { | ||||
|                             crate::config::InterfaceType::MACVTAP => InterfaceConfig::MACVTAP { | ||||
| @ -175,14 +173,14 @@ impl Resources { | ||||
|                                 name: self.available_if_name(), | ||||
|                                 device: nic.device.clone(), | ||||
|                             }, | ||||
|                             crate::config::InterfaceType::Bridge => InterfaceConfig::Bridge { | ||||
|                                 device: nic.device.clone(), | ||||
|                             }, | ||||
|                             crate::config::InterfaceType::Bridge => { | ||||
|                                 InterfaceConfig::Bridge { device: nic.device.clone() } | ||||
|                             } | ||||
|                         }; | ||||
|                         let mut ips = Vec::new(); | ||||
|                         ips.push(IPConfig { | ||||
|                             address: ip.address().to_string(), | ||||
|                             mask: calc_ipv6_netmask(ip.address(), range.gateway), | ||||
|                             address: ip_addr.to_string(), | ||||
|                             mask: range.netmask.clone(), | ||||
|                             gateway: range.gateway.to_string(), | ||||
|                         }); | ||||
|                         return Some(VMNIC { if_config, ips }); | ||||
| @ -213,7 +211,7 @@ impl Resources { | ||||
|         Ok(()) | ||||
|     } | ||||
| 
 | ||||
|     fn download_boot_file(&mut self, url: String, sha: String) -> Result<()> { | ||||
|     fn find_or_download_file(&mut self, url: String, sha: String) -> Result<()> { | ||||
|         if !self.boot_files.contains(&sha) { | ||||
|             download_and_check_sha(&url, &sha)?; | ||||
|         } | ||||
| @ -230,7 +228,14 @@ impl Resources { | ||||
|                 self.reserved_if_names.insert(vtap); | ||||
|             } | ||||
|             for ip in nic.ips.iter() { | ||||
|                 self.reserved_ips.insert(ip.address.clone()); | ||||
|                 if let Ok(ip_address) = ip.address.parse::<std::net::IpAddr>() { | ||||
|                     if ip_address.is_ipv4() { | ||||
|                         self.reserved_ipv4.insert(ip.address.clone()); | ||||
|                     } | ||||
|                     if ip_address.is_ipv6() { | ||||
|                         self.reserved_ipv6.insert(ip.address.clone()); | ||||
|                     } | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|         for (host_port, _) in vm.fw_ports.iter() { | ||||
| @ -253,15 +258,20 @@ impl Resources { | ||||
|                 self.reserved_if_names.remove(&vtap); | ||||
|             } | ||||
|             for ip in nic.ips.iter() { | ||||
|                 self.reserved_ips.remove(&ip.address.clone()); | ||||
|                 if let Ok(ip_address) = ip.address.parse::<std::net::IpAddr>() { | ||||
|                     if ip_address.is_ipv4() { | ||||
|                         self.reserved_ipv4.remove(&ip.address); | ||||
|                     } | ||||
|                     if ip_address.is_ipv6() { | ||||
|                         self.reserved_ipv6.remove(&ip.address); | ||||
|                     } | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|         for (host_port, _) in vm.fw_ports.iter() { | ||||
|             self.reserved_ports.remove(host_port); | ||||
|         } | ||||
|         self.reserved_storage | ||||
|             .entry(vm.storage_dir.clone()) | ||||
|             .and_modify(|gb| *gb -= vm.disk_size_gb); | ||||
|         self.reserved_storage.entry(vm.storage_dir.clone()).and_modify(|gb| *gb -= vm.disk_size_gb); | ||||
|         let _ = self.save_to_disk(); | ||||
|     } | ||||
| } | ||||
| @ -333,12 +343,6 @@ pub struct VMNIC { | ||||
|     ips: Vec<IPConfig>, | ||||
| } | ||||
| 
 | ||||
| impl VMNIC { | ||||
|     fn new() -> VMNIC { | ||||
|         todo!("implement this here to improve code elegance of resource reservation"); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| #[derive(Serialize, Deserialize, Debug)] | ||||
| pub struct VM { | ||||
|     pub uuid: String, | ||||
| @ -356,6 +360,35 @@ pub struct VM { | ||||
|     storage_dir: String, | ||||
| } | ||||
| 
 | ||||
| impl Into<brain::NewVmResp> for VM { | ||||
|     fn into(self) -> brain::NewVmResp { | ||||
|         let mut nic_index: u32 = 0; | ||||
|         let mut ips: Vec<brain::NewVmRespIp> = Vec::new(); | ||||
|         if self.fw_ports.len() > 0 { | ||||
|             nic_index += 1; | ||||
|         } | ||||
|         // TODO: when brain supports multiple IPs per VM, fix this
 | ||||
|         for nic in self.nics { | ||||
|             for ip in nic.ips { | ||||
|                 ips.push(brain::NewVmRespIp { | ||||
|                     nic_index, | ||||
|                     address: ip.address, | ||||
|                     mask: ip.mask, | ||||
|                     gateway: ip.gateway, | ||||
|                 }); | ||||
|             } | ||||
|             nic_index += 1; | ||||
|         } | ||||
|         brain::NewVmResp { | ||||
|             uuid: self.uuid, | ||||
|             exposed_ports: self.fw_ports.iter().map(|(p, _)| *p as u32).collect(), | ||||
|             ips, | ||||
|             ovmf_hash: crate::constants::OVMF_HASH.to_string(), | ||||
|             error: "".to_string(), | ||||
|         } | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| #[derive(Deserialize, Debug)] | ||||
| pub struct NewVMRequest { | ||||
|     uuid: String, | ||||
| @ -373,11 +406,23 @@ pub struct NewVMRequest { | ||||
|     dtrfs_sha: String, | ||||
| } | ||||
| 
 | ||||
| impl NewVMRequest { | ||||
|     pub fn from_file(path: &str) -> Result<Self, Box<dyn std::error::Error>> { | ||||
|         let content = std::fs::read_to_string(path)?; | ||||
|         let request: NewVMRequest = serde_yaml::from_str(&content)?; | ||||
|         Ok(request) | ||||
| impl From<brain::NewVmReq> for NewVMRequest { | ||||
|     fn from(req: brain::NewVmReq) -> Self { | ||||
|         Self { | ||||
|             uuid: req.uuid, | ||||
|             hostname: req.hostname, | ||||
|             admin_key: req.admin_pubkey, | ||||
|             extra_ports: req.extra_ports.iter().map(|&port| port as u16).collect(), | ||||
|             public_ipv4: req.public_ipv4, | ||||
|             public_ipv6: req.public_ipv6, | ||||
|             disk_size_gb: req.disk_size_gb as usize, | ||||
|             vcpus: req.vcpus as usize, | ||||
|             memory_mb: req.memory_mb as usize, | ||||
|             kernel_url: req.kernel_url, | ||||
|             kernel_sha: req.kernel_sha, | ||||
|             dtrfs_url: req.dtrfs_url, | ||||
|             dtrfs_sha: req.dtrfs_sha, | ||||
|         } | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| @ -394,17 +439,9 @@ pub struct UpdateVMReq { | ||||
|     dtrfs_sha: String, | ||||
| } | ||||
| 
 | ||||
| impl UpdateVMReq { | ||||
|     pub fn from_file(path: &str) -> Result<Self, Box<dyn std::error::Error>> { | ||||
|         let content = std::fs::read_to_string(path)?; | ||||
|         let request: UpdateVMReq = serde_yaml::from_str(&content)?; | ||||
|         Ok(request) | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| #[derive(Debug)] | ||||
| pub enum VMCreationErrors { | ||||
|     VMAlreadyExists, | ||||
|     VMAlreadyExists(VM), | ||||
|     NATandIPv4Conflict, | ||||
|     TooManyCores, | ||||
|     NotEnoughPorts, | ||||
| @ -426,7 +463,11 @@ impl VM { | ||||
|         res: &mut Resources, | ||||
|     ) -> Result<Self, VMCreationErrors> { | ||||
|         if res.existing_vms.contains(&req.uuid) { | ||||
|             return Err(VMCreationErrors::VMAlreadyExists); | ||||
|             let content = std::fs::read_to_string(VM_CONFIG_DIR.to_string() + &req.uuid + ".yaml") | ||||
|                 .map_err(|e| VMCreationErrors::ServerDiskError(e.to_string()))?; | ||||
|             let vm: crate::state::VM = serde_yaml::from_str(&content) | ||||
|                 .map_err(|e| VMCreationErrors::ServerDiskError(e.to_string()))?; | ||||
|             return Err(VMCreationErrors::VMAlreadyExists(vm)); | ||||
|         } | ||||
|         if req.extra_ports.len() > 0 && req.public_ipv4 { | ||||
|             return Err(VMCreationErrors::NATandIPv4Conflict); | ||||
| @ -444,12 +485,20 @@ impl VM { | ||||
|             return Err(VMCreationErrors::DiskTooSmall); | ||||
|         } | ||||
| 
 | ||||
|         if let Err(kernel_err) = res.download_boot_file(req.kernel_url, req.kernel_sha.clone()) { | ||||
|         if let Err(ovmf_err) = res.find_or_download_file( | ||||
|             crate::constants::OVMF_URL.to_string(), | ||||
|             crate::constants::OVMF_HASH.to_string(), | ||||
|         ) { | ||||
|             return Err(VMCreationErrors::BootFileError(format!( | ||||
|                 "Could not get OVMF: {ovmf_err:?}" | ||||
|             ))); | ||||
|         }; | ||||
|         if let Err(kernel_err) = res.find_or_download_file(req.kernel_url, req.kernel_sha.clone()) { | ||||
|             return Err(VMCreationErrors::BootFileError(format!( | ||||
|                 "Could not get kernel: {kernel_err:?}" | ||||
|             ))); | ||||
|         }; | ||||
|         if let Err(dtrfs_err) = res.download_boot_file(req.dtrfs_url, req.dtrfs_sha.clone()) { | ||||
|         if let Err(dtrfs_err) = res.find_or_download_file(req.dtrfs_url, req.dtrfs_sha.clone()) { | ||||
|             return Err(VMCreationErrors::BootFileError(format!( | ||||
|                 "Could not get dtrfs: {dtrfs_err:?}" | ||||
|             ))); | ||||
| @ -457,13 +506,13 @@ impl VM { | ||||
| 
 | ||||
|         let mut vm_nics = Vec::new(); | ||||
|         if req.public_ipv4 { | ||||
|             match res.available_ipv4(config) { | ||||
|             match res.available_ipv4(&config.network_interfaces) { | ||||
|                 Some(vmnic) => vm_nics.push(vmnic), | ||||
|                 None => return Err(VMCreationErrors::IPv4NotAvailable), | ||||
|             } | ||||
|         } | ||||
|         if req.public_ipv6 { | ||||
|             match res.available_ipv6(config) { | ||||
|             match res.available_ipv6(&config.network_interfaces) { | ||||
|                 Some(mut vmnic) => { | ||||
|                     if let Some(mut existing_vmnic) = vm_nics.pop() { | ||||
|                         if vmnic.if_config.device_name() == existing_vmnic.if_config.device_name() { | ||||
| @ -478,7 +527,7 @@ impl VM { | ||||
|                     } | ||||
|                 } | ||||
|                 None => { | ||||
|                     return Err(VMCreationErrors::IPv4NotAvailable); | ||||
|                     return Err(VMCreationErrors::IPv6NotAvailable); | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
| @ -532,18 +581,12 @@ impl VM { | ||||
|             return Err(VMCreationErrors::TooManyCores); | ||||
|         } | ||||
|         if config.max_vcpu_reservation | ||||
|             < res | ||||
|                 .reserved_vcpus | ||||
|                 .saturating_sub(self.vcpus) | ||||
|                 .saturating_add(req.vcpus) | ||||
|             < res.reserved_vcpus.saturating_sub(self.vcpus).saturating_add(req.vcpus) | ||||
|         { | ||||
|             return Err(VMCreationErrors::NotEnoughCPU); | ||||
|         } | ||||
|         if config.max_mem_reservation_mb | ||||
|             < res | ||||
|                 .reserved_memory | ||||
|                 .saturating_sub(self.memory_mb) | ||||
|                 .saturating_add(req.memory_mb) | ||||
|             < res.reserved_memory.saturating_sub(self.memory_mb).saturating_add(req.memory_mb) | ||||
|         { | ||||
|             return Err(VMCreationErrors::NotEnoughMemory); | ||||
|         } | ||||
| @ -558,12 +601,14 @@ impl VM { | ||||
|                 )); | ||||
|             } | ||||
| 
 | ||||
|             if let Err(kern_err) = res.download_boot_file(req.kernel_url, req.kernel_sha.clone()) { | ||||
|             if let Err(kern_err) = res.find_or_download_file(req.kernel_url, req.kernel_sha.clone()) | ||||
|             { | ||||
|                 return Err(VMCreationErrors::BootFileError(format!( | ||||
|                     "Could not get kernel: {kern_err:?}" | ||||
|                 ))); | ||||
|             }; | ||||
|             if let Err(dtrfs_err) = res.download_boot_file(req.dtrfs_url, req.dtrfs_sha.clone()) { | ||||
|             if let Err(dtrfs_err) = res.find_or_download_file(req.dtrfs_url, req.dtrfs_sha.clone()) | ||||
|             { | ||||
|                 return Err(VMCreationErrors::BootFileError(format!( | ||||
|                     "Could not get dtrfs: {dtrfs_err:?}" | ||||
|                 ))); | ||||
| @ -578,12 +623,10 @@ impl VM { | ||||
|         res.reserved_memory = res.reserved_memory.saturating_sub(self.memory_mb); | ||||
|         res.reserved_vcpus = res.reserved_vcpus.saturating_add(req.vcpus); | ||||
|         res.reserved_vcpus = res.reserved_vcpus.saturating_sub(self.vcpus); | ||||
|         res.reserved_storage | ||||
|             .entry(self.storage_dir.clone()) | ||||
|             .and_modify(|gb| { | ||||
|                 *gb = gb.saturating_add(req.disk_size_gb); | ||||
|                 *gb = gb.saturating_sub(self.disk_size_gb); | ||||
|             }); | ||||
|         res.reserved_storage.entry(self.storage_dir.clone()).and_modify(|gb| { | ||||
|             *gb = gb.saturating_add(req.disk_size_gb); | ||||
|             *gb = gb.saturating_sub(self.disk_size_gb); | ||||
|         }); | ||||
|         let _ = res.save_to_disk(); | ||||
| 
 | ||||
|         self.memory_mb = req.memory_mb; | ||||
| @ -645,28 +688,25 @@ impl VM { | ||||
|         dir + &self.uuid + ".qcow2" | ||||
|     } | ||||
| 
 | ||||
|     // If you change this here, you also have to change it in the CLI.
 | ||||
|     // The kernel params must match on both daemon and CLI to build the measurement.
 | ||||
|     pub fn kernel_params(&self) -> String { | ||||
|         let mut ip_string = String::new(); | ||||
|         let mut i = 0; | ||||
|         if self.fw_ports.len() > 0 { | ||||
|             ip_string += &format!( | ||||
|                 "detee_net_eth{}={}_{}_{} ", | ||||
|                 i, "10.0.2.15", "24", "10.0.2.2" | ||||
|             ); | ||||
|             ip_string += &format!("detee_net_eth{}={}_{}_{} ", i, "10.0.2.15", "24", "10.0.2.2"); | ||||
|             i += 1; | ||||
|         } | ||||
|         for nic in self.nics.iter() { | ||||
|             for ip in nic.ips.iter() { | ||||
|                 ip_string += &format!( | ||||
|                     "detee_net_eth{}={}_{}_{} ", | ||||
|                     i, ip.address, ip.mask, ip.gateway | ||||
|                 ); | ||||
|                 ip_string += | ||||
|                     &format!("detee_net_eth{}={}_{}_{} ", i, ip.address, ip.mask, ip.gateway); | ||||
|             } | ||||
|             i += 1; | ||||
|         } | ||||
|         let admin_key = format!("detee_admin={}", self.admin_key); | ||||
|         let admin_key = format!("detee_admin={} ", self.admin_key); | ||||
|         let hostname = format!("detee_name={}", self.hostname); | ||||
|         format!("{} {} {}", ip_string, admin_key, hostname) | ||||
|         format!("{}{}{}", ip_string, admin_key, hostname) | ||||
|     } | ||||
| 
 | ||||
|     fn write_config(&self) -> Result<()> { | ||||
| @ -686,11 +726,7 @@ impl VM { | ||||
|         let mut i = 0; | ||||
|         for nic in self.nics.iter() { | ||||
|             let mut interface = String::new(); | ||||
|             interface += &format!( | ||||
|                 r#"export NETWORK_INTERFACE_{}="{}"#, | ||||
|                 i, | ||||
|                 nic.if_config.if_type() | ||||
|             ); | ||||
|             interface += &format!(r#"export NETWORK_INTERFACE_{}="{}"#, i, nic.if_config.if_type()); | ||||
|             // device is currently ignored in case of NAT cause we assume QEMU userspace NAT
 | ||||
|             if let Some(vtap_name) = nic.if_config.vtap_name() { | ||||
|                 interface += &format!("_{}_{}", nic.if_config.device_name(), vtap_name); | ||||
| @ -711,15 +747,9 @@ impl VM { | ||||
|             vars += "export NETWORK_INTERFACE_0000=NAT\n"; | ||||
|         } | ||||
| 
 | ||||
|         vars += &format!( | ||||
|             r#"export KERNEL="{}""#, | ||||
|             VM_BOOT_DIR.to_string() + &self.kernel_sha | ||||
|         ); | ||||
|         vars += &format!(r#"export KERNEL="{}""#, VM_BOOT_DIR.to_string() + &self.kernel_sha); | ||||
|         vars += "\n"; | ||||
|         vars += &format!( | ||||
|             r#"export INITRD="{}""#, | ||||
|             VM_BOOT_DIR.to_string() + &self.dtrfs_sha | ||||
|         ); | ||||
|         vars += &format!(r#"export INITRD="{}""#, VM_BOOT_DIR.to_string() + &self.dtrfs_sha); | ||||
|         vars += "\n"; | ||||
|         vars += &format!(r#"export PARAMS="{}""#, self.kernel_params()); | ||||
|         vars += "\n"; | ||||
| @ -747,11 +777,7 @@ impl VM { | ||||
|     fn delete_vtap_interfaces(&self) -> Result<()> { | ||||
|         for nic in self.nics.iter() { | ||||
|             if let Some(name) = nic.if_config.vtap_name() { | ||||
|                 let result = Command::new("ip") | ||||
|                     .arg("link") | ||||
|                     .arg("del") | ||||
|                     .arg(&name) | ||||
|                     .output()?; | ||||
|                 let result = Command::new("ip").arg("link").arg("del").arg(&name).output()?; | ||||
|                 if !result.status.success() { | ||||
|                     return Err(anyhow!( | ||||
|                         "Could not delete vtap interface {:?}:\n{:?}\n{:?}", | ||||
| @ -794,10 +820,7 @@ impl VM { | ||||
| 
 | ||||
|     fn create_disk(&self) -> Result<()> { | ||||
|         if std::path::Path::new(&self.disk_path()).exists() { | ||||
|             return Err(anyhow!( | ||||
|                 "Could not create {}. The file already exists.", | ||||
|                 self.disk_path() | ||||
|             )); | ||||
|             return Err(anyhow!("Could not create {}. The file already exists.", self.disk_path())); | ||||
|         } | ||||
| 
 | ||||
|         let result = Command::new("qemu-img") | ||||
| @ -844,10 +867,8 @@ impl VM { | ||||
| } | ||||
| 
 | ||||
| fn systemctl_start_and_enable(vm_uuid: &str) -> Result<()> { | ||||
|     let result = Command::new("systemctl") | ||||
|         .arg("start") | ||||
|         .arg(vm_uuid.to_string() + ".service") | ||||
|         .output()?; | ||||
|     let result = | ||||
|         Command::new("systemctl").arg("start").arg(vm_uuid.to_string() + ".service").output()?; | ||||
|     if !result.status.success() { | ||||
|         return Err(anyhow!( | ||||
|             "Could not reload systemctl daemon:\n{:?}\n{:?}", | ||||
| @ -857,10 +878,8 @@ fn systemctl_start_and_enable(vm_uuid: &str) -> Result<()> { | ||||
|                 .unwrap_or("Could not grab stderr from creation script.".to_string()), | ||||
|         )); | ||||
|     } | ||||
|     let result = Command::new("systemctl") | ||||
|         .arg("enable") | ||||
|         .arg(vm_uuid.to_string() + ".service") | ||||
|         .output()?; | ||||
|     let result = | ||||
|         Command::new("systemctl").arg("enable").arg(vm_uuid.to_string() + ".service").output()?; | ||||
|     if !result.status.success() { | ||||
|         return Err(anyhow!( | ||||
|             "Could not reload systemctl daemon:\n{:?}\n{:?}", | ||||
| @ -874,10 +893,8 @@ fn systemctl_start_and_enable(vm_uuid: &str) -> Result<()> { | ||||
| } | ||||
| 
 | ||||
| fn systemctl_stop_and_disable(vm_uuid: &str) -> Result<()> { | ||||
|     let result = Command::new("systemctl") | ||||
|         .arg("stop") | ||||
|         .arg(vm_uuid.to_string() + ".service") | ||||
|         .output()?; | ||||
|     let result = | ||||
|         Command::new("systemctl").arg("stop").arg(vm_uuid.to_string() + ".service").output()?; | ||||
|     if !result.status.success() { | ||||
|         return Err(anyhow!( | ||||
|             "Could not reload systemctl daemon:\n{:?}\n{:?}", | ||||
| @ -887,10 +904,8 @@ fn systemctl_stop_and_disable(vm_uuid: &str) -> Result<()> { | ||||
|                 .unwrap_or("Could not grab stderr from creation script.".to_string()), | ||||
|         )); | ||||
|     } | ||||
|     let result = Command::new("systemctl") | ||||
|         .arg("disable") | ||||
|         .arg(vm_uuid.to_string() + ".service") | ||||
|         .output()?; | ||||
|     let result = | ||||
|         Command::new("systemctl").arg("disable").arg(vm_uuid.to_string() + ".service").output()?; | ||||
|     if !result.status.success() { | ||||
|         return Err(anyhow!( | ||||
|             "Could not reload systemctl daemon:\n{:?}\n{:?}", | ||||
| @ -919,9 +934,7 @@ fn systemctl_reload() -> Result<()> { | ||||
| 
 | ||||
| fn download_and_check_sha(url: &str, sha: &str) -> Result<()> { | ||||
|     use reqwest::blocking::get; | ||||
|     use std::fs::File; | ||||
|     use std::io::copy; | ||||
|     use std::path::Path; | ||||
|     use std::{fs::File, io::copy, path::Path}; | ||||
|     let save_path = VM_BOOT_DIR.to_string() + sha; | ||||
|     let response = get(url)?; | ||||
|     if !response.status().is_success() { | ||||
| @ -958,41 +971,3 @@ fn compute_sha256<P: AsRef<Path>>(path: P) -> Result<String> { | ||||
|     let result = hasher.finalize(); | ||||
|     Ok(format!("{:x}", result)) | ||||
| } | ||||
| 
 | ||||
| fn calc_ipv4_netmask(ip: Ipv4Addr, gateway: Ipv4Addr) -> String { | ||||
|     // Convert the IPs to u32 for easier bit manipulation
 | ||||
|     let ip_u32 = u32::from(ip); | ||||
|     let gateway_u32 = u32::from(gateway); | ||||
| 
 | ||||
|     // Find the smallest common prefix
 | ||||
|     let mut prefix_len = 0; | ||||
|     for i in 1..=32 { | ||||
|         if (ip_u32 >> (32 - i)) == (gateway_u32 >> (32 - i)) { | ||||
|             prefix_len = i; | ||||
|         } else { | ||||
|             break; | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     // Return the mask as a string
 | ||||
|     prefix_len.to_string() | ||||
| } | ||||
| 
 | ||||
| fn calc_ipv6_netmask(ip: Ipv6Addr, gateway: Ipv6Addr) -> String { | ||||
|     // Convert the IPs to u128 for easier bit manipulation
 | ||||
|     let ip_u128 = u128::from(ip); | ||||
|     let gateway_u128 = u128::from(gateway); | ||||
| 
 | ||||
|     // Find the smallest common prefix
 | ||||
|     let mut prefix_len = 0; | ||||
|     for i in 1..=128 { | ||||
|         if (ip_u128 >> (128 - i)) == (gateway_u128 >> (128 - i)) { | ||||
|             prefix_len = i; | ||||
|         } else { | ||||
|             break; | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     // Return the mask as a string
 | ||||
|     prefix_len.to_string() | ||||
| } | ||||
|  | ||||
| @ -1,25 +0,0 @@ | ||||
| #![allow(dead_code)] | ||||
| // this is defined in the engine but we will mock it here for now
 | ||||
| 
 | ||||
| pub struct FinalizedTContract { | ||||
|     pub owner: String, | ||||
|     pub user: String, | ||||
|     pub alloc: ResourceAllocation, | ||||
|     pub kernel_uri: String, | ||||
|     pub kernel_sha: String, | ||||
|     pub dtrfs_uri: String, | ||||
|     pub dtrfs_sha: String, | ||||
| } | ||||
| 
 | ||||
| #[derive(Default)] | ||||
| pub struct ResourceAllocation { | ||||
|     pub vcpus: usize, | ||||
|     pub memory: usize, | ||||
|     pub storage: usize, | ||||
|     pub extra_ports: Vec<u16>, | ||||
|     // storage tier: not part of MVP
 | ||||
|     // pub storage_tier: usize,
 | ||||
|     pub public_ipv4: Option<String>, | ||||
|     pub public_ipv6: Option<String>, | ||||
| } | ||||
| 
 | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user