Demonstrating core cloud concepts, starting with CaaS. Not for production use.

Design from the last stream, plus groundwork for the pods

+1 -1
README.md
··· 1 - Meow2 1 + Meow
+1
control-plane/job-board/.gitignore
··· 1 + target
+931
control-plane/job-board/Cargo.lock
··· 1 + # This file is automatically @generated by Cargo. 2 + # It is not intended for manual editing. 3 + version = 4 4 + 5 + [[package]] 6 + name = "bitflags" 7 + version = "2.9.4" 8 + source = "registry+https://github.com/rust-lang/crates.io-index" 9 + checksum = "2261d10cca569e4643e526d8dc2e62e433cc8aba21ab764233731f8d369bf394" 10 + 11 + [[package]] 12 + name = "block-buffer" 13 + version = "0.10.4" 14 + source = "registry+https://github.com/rust-lang/crates.io-index" 15 + checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71" 16 + dependencies = [ 17 + "generic-array", 18 + ] 19 + 20 + [[package]] 21 + name = "bumpalo" 22 + version = "3.19.0" 23 + source = "registry+https://github.com/rust-lang/crates.io-index" 24 + checksum = "46c5e41b57b8bba42a04676d81cb89e9ee8e859a1a66f80a5a72e1cb76b34d43" 25 + 26 + [[package]] 27 + name = "byteorder" 28 + version = "1.5.0" 29 + source = "registry+https://github.com/rust-lang/crates.io-index" 30 + checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" 31 + 32 + [[package]] 33 + name = "bytes" 34 + version = "1.10.1" 35 + source = "registry+https://github.com/rust-lang/crates.io-index" 36 + checksum = "d71b6127be86fdcfddb610f7182ac57211d4b18a3e9c82eb2d17662f2227ad6a" 37 + 38 + [[package]] 39 + name = "cfg-if" 40 + version = "1.0.4" 41 + source = "registry+https://github.com/rust-lang/crates.io-index" 42 + checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801" 43 + 44 + [[package]] 45 + name = "cpufeatures" 46 + version = "0.2.17" 47 + source = "registry+https://github.com/rust-lang/crates.io-index" 48 + checksum = "59ed5838eebb26a2bb2e58f6d5b5316989ae9d08bab10e0e6d103e656d1b0280" 49 + dependencies = [ 50 + "libc", 51 + ] 52 + 53 + [[package]] 54 + name = "crypto-common" 55 + version = "0.1.6" 56 + source = "registry+https://github.com/rust-lang/crates.io-index" 57 + checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" 58 + dependencies = [ 59 + "generic-array", 60 + "typenum", 61 + ] 62 + 63 + [[package]] 64 + name = "data-encoding" 65 + version = "2.9.0" 66 + source = "registry+https://github.com/rust-lang/crates.io-index" 67 + checksum = "2a2330da5de22e8a3cb63252ce2abb30116bf5265e89c0e01bc17015ce30a476" 68 + 69 + [[package]] 70 + name = "digest" 71 + version = "0.10.7" 72 + source = "registry+https://github.com/rust-lang/crates.io-index" 73 + checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" 74 + dependencies = [ 75 + "block-buffer", 76 + "crypto-common", 77 + ] 78 + 79 + [[package]] 80 + name = "fnv" 81 + version = "1.0.7" 82 + source = "registry+https://github.com/rust-lang/crates.io-index" 83 + checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" 84 + 85 + [[package]] 86 + name = "futures-core" 87 + version = "0.3.31" 88 + source = "registry+https://github.com/rust-lang/crates.io-index" 89 + checksum = "05f29059c0c2090612e8d742178b0580d2dc940c837851ad723096f87af6663e" 90 + 91 + [[package]] 92 + name = "futures-sink" 93 + version = "0.3.31" 94 + source = "registry+https://github.com/rust-lang/crates.io-index" 95 + checksum = "e575fab7d1e0dcb8d0c7bcf9a63ee213816ab51902e6d244a95819acacf1d4f7" 96 + 97 + [[package]] 98 + name = "futures-task" 99 + version = "0.3.31" 100 + source = "registry+https://github.com/rust-lang/crates.io-index" 101 + checksum = "f90f7dce0722e95104fcb095585910c0977252f286e354b5e3bd38902cd99988" 102 + 103 + [[package]] 104 + name = "futures-util" 105 + version = "0.3.31" 106 + source = "registry+https://github.com/rust-lang/crates.io-index" 107 + checksum = "9fa08315bb612088cc391249efdc3bc77536f16c91f6cf495e6fbe85b20a4a81" 108 + dependencies = [ 109 + "futures-core", 110 + "futures-sink", 111 + "futures-task", 112 + "pin-project-lite", 113 + "pin-utils", 114 + "slab", 115 + ] 116 + 117 + [[package]] 118 + name = "generic-array" 119 + version = "0.14.9" 120 + source = "registry+https://github.com/rust-lang/crates.io-index" 121 + checksum = "4bb6743198531e02858aeaea5398fcc883e71851fcbcb5a2f773e2fb6cb1edf2" 122 + dependencies = [ 123 + "typenum", 124 + "version_check", 125 + ] 126 + 127 + [[package]] 128 + name = "getrandom" 129 + version = "0.2.16" 130 + source = "registry+https://github.com/rust-lang/crates.io-index" 131 + checksum = "335ff9f135e4384c8150d6f27c6daed433577f86b4750418338c01a1a2528592" 132 + dependencies = [ 133 + "cfg-if", 134 + "libc", 135 + "wasi", 136 + ] 137 + 138 + [[package]] 139 + name = "getrandom" 140 + version = "0.3.4" 141 + source = "registry+https://github.com/rust-lang/crates.io-index" 142 + checksum = "899def5c37c4fd7b2664648c28120ecec138e4d395b459e5ca34f9cce2dd77fd" 143 + dependencies = [ 144 + "cfg-if", 145 + "libc", 146 + "r-efi", 147 + "wasip2", 148 + ] 149 + 150 + [[package]] 151 + name = "http" 152 + version = "1.3.1" 153 + source = "registry+https://github.com/rust-lang/crates.io-index" 154 + checksum = "f4a85d31aea989eead29a3aaf9e1115a180df8282431156e533de47660892565" 155 + dependencies = [ 156 + "bytes", 157 + "fnv", 158 + "itoa", 159 + ] 160 + 161 + [[package]] 162 + name = "httparse" 163 + version = "1.10.1" 164 + source = "registry+https://github.com/rust-lang/crates.io-index" 165 + checksum = "6dbf3de79e51f3d586ab4cb9d5c3e2c14aa28ed23d180cf89b4df0454a69cc87" 166 + 167 + [[package]] 168 + name = "itoa" 169 + version = "1.0.15" 170 + source = "registry+https://github.com/rust-lang/crates.io-index" 171 + checksum = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c" 172 + 173 + [[package]] 174 + name = "job-board-orchestrator" 175 + version = "0.1.0" 176 + dependencies = [ 177 + "futures-util", 178 + "serde", 179 + "serde_json", 180 + "tokio", 181 + "tokio-tungstenite", 182 + "tracing", 183 + "tracing-subscriber", 184 + "uuid", 185 + ] 186 + 187 + [[package]] 188 + name = "js-sys" 189 + version = "0.3.81" 190 + source = "registry+https://github.com/rust-lang/crates.io-index" 191 + checksum = "ec48937a97411dcb524a265206ccd4c90bb711fca92b2792c407f268825b9305" 192 + dependencies = [ 193 + "once_cell", 194 + "wasm-bindgen", 195 + ] 196 + 197 + [[package]] 198 + name = "lazy_static" 199 + version = "1.5.0" 200 + source = "registry+https://github.com/rust-lang/crates.io-index" 201 + checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" 202 + 203 + [[package]] 204 + name = "libc" 205 + version = "0.2.177" 206 + source = "registry+https://github.com/rust-lang/crates.io-index" 207 + checksum = "2874a2af47a2325c2001a6e6fad9b16a53b802102b528163885171cf92b15976" 208 + 209 + [[package]] 210 + name = "lock_api" 211 + version = "0.4.14" 212 + source = "registry+https://github.com/rust-lang/crates.io-index" 213 + checksum = "224399e74b87b5f3557511d98dff8b14089b3dadafcab6bb93eab67d3aace965" 214 + dependencies = [ 215 + "scopeguard", 216 + ] 217 + 218 + [[package]] 219 + name = "log" 220 + version = "0.4.28" 221 + source = "registry+https://github.com/rust-lang/crates.io-index" 222 + checksum = "34080505efa8e45a4b816c349525ebe327ceaa8559756f0356cba97ef3bf7432" 223 + 224 + [[package]] 225 + name = "memchr" 226 + version = "2.7.6" 227 + source = "registry+https://github.com/rust-lang/crates.io-index" 228 + checksum = "f52b00d39961fc5b2736ea853c9cc86238e165017a493d1d5c8eac6bdc4cc273" 229 + 230 + [[package]] 231 + name = "mio" 232 + version = "1.0.4" 233 + source = "registry+https://github.com/rust-lang/crates.io-index" 234 + checksum = "78bed444cc8a2160f01cbcf811ef18cac863ad68ae8ca62092e8db51d51c761c" 235 + dependencies = [ 236 + "libc", 237 + "wasi", 238 + "windows-sys 0.59.0", 239 + ] 240 + 241 + [[package]] 242 + name = "nu-ansi-term" 243 + version = "0.50.3" 244 + source = "registry+https://github.com/rust-lang/crates.io-index" 245 + checksum = "7957b9740744892f114936ab4a57b3f487491bbeafaf8083688b16841a4240e5" 246 + dependencies = [ 247 + "windows-sys 0.61.2", 248 + ] 249 + 250 + [[package]] 251 + name = "once_cell" 252 + version = "1.21.3" 253 + source = "registry+https://github.com/rust-lang/crates.io-index" 254 + checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d" 255 + 256 + [[package]] 257 + name = "parking_lot" 258 + version = "0.12.5" 259 + source = "registry+https://github.com/rust-lang/crates.io-index" 260 + checksum = "93857453250e3077bd71ff98b6a65ea6621a19bb0f559a85248955ac12c45a1a" 261 + dependencies = [ 262 + "lock_api", 263 + "parking_lot_core", 264 + ] 265 + 266 + [[package]] 267 + name = "parking_lot_core" 268 + version = "0.9.12" 269 + source = "registry+https://github.com/rust-lang/crates.io-index" 270 + checksum = "2621685985a2ebf1c516881c026032ac7deafcda1a2c9b7850dc81e3dfcb64c1" 271 + dependencies = [ 272 + "cfg-if", 273 + "libc", 274 + "redox_syscall", 275 + "smallvec", 276 + "windows-link", 277 + ] 278 + 279 + [[package]] 280 + name = "pin-project-lite" 281 + version = "0.2.16" 282 + source = "registry+https://github.com/rust-lang/crates.io-index" 283 + checksum = "3b3cff922bd51709b605d9ead9aa71031d81447142d828eb4a6eba76fe619f9b" 284 + 285 + [[package]] 286 + name = "pin-utils" 287 + version = "0.1.0" 288 + source = "registry+https://github.com/rust-lang/crates.io-index" 289 + checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" 290 + 291 + [[package]] 292 + name = "ppv-lite86" 293 + version = "0.2.21" 294 + source = "registry+https://github.com/rust-lang/crates.io-index" 295 + checksum = "85eae3c4ed2f50dcfe72643da4befc30deadb458a9b590d720cde2f2b1e97da9" 296 + dependencies = [ 297 + "zerocopy", 298 + ] 299 + 300 + [[package]] 301 + name = "proc-macro2" 302 + version = "1.0.101" 303 + source = "registry+https://github.com/rust-lang/crates.io-index" 304 + checksum = "89ae43fd86e4158d6db51ad8e2b80f313af9cc74f5c0e03ccb87de09998732de" 305 + dependencies = [ 306 + "unicode-ident", 307 + ] 308 + 309 + [[package]] 310 + name = "quote" 311 + version = "1.0.41" 312 + source = "registry+https://github.com/rust-lang/crates.io-index" 313 + checksum = "ce25767e7b499d1b604768e7cde645d14cc8584231ea6b295e9c9eb22c02e1d1" 314 + dependencies = [ 315 + "proc-macro2", 316 + ] 317 + 318 + [[package]] 319 + name = "r-efi" 320 + version = "5.3.0" 321 + source = "registry+https://github.com/rust-lang/crates.io-index" 322 + checksum = "69cdb34c158ceb288df11e18b4bd39de994f6657d83847bdffdbd7f346754b0f" 323 + 324 + [[package]] 325 + name = "rand" 326 + version = "0.8.5" 327 + source = "registry+https://github.com/rust-lang/crates.io-index" 328 + checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" 329 + dependencies = [ 330 + "libc", 331 + "rand_chacha", 332 + "rand_core", 333 + ] 334 + 335 + [[package]] 336 + name = "rand_chacha" 337 + version = "0.3.1" 338 + source = "registry+https://github.com/rust-lang/crates.io-index" 339 + checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" 340 + dependencies = [ 341 + "ppv-lite86", 342 + "rand_core", 343 + ] 344 + 345 + [[package]] 346 + name = "rand_core" 347 + version = "0.6.4" 348 + source = "registry+https://github.com/rust-lang/crates.io-index" 349 + checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" 350 + dependencies = [ 351 + "getrandom 0.2.16", 352 + ] 353 + 354 + [[package]] 355 + name = "redox_syscall" 356 + version = "0.5.18" 357 + source = "registry+https://github.com/rust-lang/crates.io-index" 358 + checksum = "ed2bf2547551a7053d6fdfafda3f938979645c44812fbfcda098faae3f1a362d" 359 + dependencies = [ 360 + "bitflags", 361 + ] 362 + 363 + [[package]] 364 + name = "rustversion" 365 + version = "1.0.22" 366 + source = "registry+https://github.com/rust-lang/crates.io-index" 367 + checksum = "b39cdef0fa800fc44525c84ccb54a029961a8215f9619753635a9c0d2538d46d" 368 + 369 + [[package]] 370 + name = "ryu" 371 + version = "1.0.20" 372 + source = "registry+https://github.com/rust-lang/crates.io-index" 373 + checksum = "28d3b2b1366ec20994f1fd18c3c594f05c5dd4bc44d8bb0c1c632c8d6829481f" 374 + 375 + [[package]] 376 + name = "scopeguard" 377 + version = "1.2.0" 378 + source = "registry+https://github.com/rust-lang/crates.io-index" 379 + checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" 380 + 381 + [[package]] 382 + name = "serde" 383 + version = "1.0.228" 384 + source = "registry+https://github.com/rust-lang/crates.io-index" 385 + checksum = "9a8e94ea7f378bd32cbbd37198a4a91436180c5bb472411e48b5ec2e2124ae9e" 386 + dependencies = [ 387 + "serde_core", 388 + "serde_derive", 389 + ] 390 + 391 + [[package]] 392 + name = "serde_core" 393 + version = "1.0.228" 394 + source = "registry+https://github.com/rust-lang/crates.io-index" 395 + checksum = "41d385c7d4ca58e59fc732af25c3983b67ac852c1a25000afe1175de458b67ad" 396 + dependencies = [ 397 + "serde_derive", 398 + ] 399 + 400 + [[package]] 401 + name = "serde_derive" 402 + version = "1.0.228" 403 + source = "registry+https://github.com/rust-lang/crates.io-index" 404 + checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79" 405 + dependencies = [ 406 + "proc-macro2", 407 + "quote", 408 + "syn", 409 + ] 410 + 411 + [[package]] 412 + name = "serde_json" 413 + version = "1.0.145" 414 + source = "registry+https://github.com/rust-lang/crates.io-index" 415 + checksum = "402a6f66d8c709116cf22f558eab210f5a50187f702eb4d7e5ef38d9a7f1c79c" 416 + dependencies = [ 417 + "itoa", 418 + "memchr", 419 + "ryu", 420 + "serde", 421 + "serde_core", 422 + ] 423 + 424 + [[package]] 425 + name = "sha1" 426 + version = "0.10.6" 427 + source = "registry+https://github.com/rust-lang/crates.io-index" 428 + checksum = "e3bf829a2d51ab4a5ddf1352d8470c140cadc8301b2ae1789db023f01cedd6ba" 429 + dependencies = [ 430 + "cfg-if", 431 + "cpufeatures", 432 + "digest", 433 + ] 434 + 435 + [[package]] 436 + name = "sharded-slab" 437 + version = "0.1.7" 438 + source = "registry+https://github.com/rust-lang/crates.io-index" 439 + checksum = "f40ca3c46823713e0d4209592e8d6e826aa57e928f09752619fc696c499637f6" 440 + dependencies = [ 441 + "lazy_static", 442 + ] 443 + 444 + [[package]] 445 + name = "signal-hook-registry" 446 + version = "1.4.6" 447 + source = "registry+https://github.com/rust-lang/crates.io-index" 448 + checksum = "b2a4719bff48cee6b39d12c020eeb490953ad2443b7055bd0b21fca26bd8c28b" 449 + dependencies = [ 450 + "libc", 451 + ] 452 + 453 + [[package]] 454 + name = "slab" 455 + version = "0.4.11" 456 + source = "registry+https://github.com/rust-lang/crates.io-index" 457 + checksum = "7a2ae44ef20feb57a68b23d846850f861394c2e02dc425a50098ae8c90267589" 458 + 459 + [[package]] 460 + name = "smallvec" 461 + version = "1.15.1" 462 + source = "registry+https://github.com/rust-lang/crates.io-index" 463 + checksum = "67b1b7a3b5fe4f1376887184045fcf45c69e92af734b7aaddc05fb777b6fbd03" 464 + 465 + [[package]] 466 + name = "socket2" 467 + version = "0.6.1" 468 + source = "registry+https://github.com/rust-lang/crates.io-index" 469 + checksum = "17129e116933cf371d018bb80ae557e889637989d8638274fb25622827b03881" 470 + dependencies = [ 471 + "libc", 472 + "windows-sys 0.60.2", 473 + ] 474 + 475 + [[package]] 476 + name = "syn" 477 + version = "2.0.106" 478 + source = "registry+https://github.com/rust-lang/crates.io-index" 479 + checksum = "ede7c438028d4436d71104916910f5bb611972c5cfd7f89b8300a8186e6fada6" 480 + dependencies = [ 481 + "proc-macro2", 482 + "quote", 483 + "unicode-ident", 484 + ] 485 + 486 + [[package]] 487 + name = "thiserror" 488 + version = "1.0.69" 489 + source = "registry+https://github.com/rust-lang/crates.io-index" 490 + checksum = "b6aaf5339b578ea85b50e080feb250a3e8ae8cfcdff9a461c9ec2904bc923f52" 491 + dependencies = [ 492 + "thiserror-impl", 493 + ] 494 + 495 + [[package]] 496 + name = "thiserror-impl" 497 + version = "1.0.69" 498 + source = "registry+https://github.com/rust-lang/crates.io-index" 499 + checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" 500 + dependencies = [ 501 + "proc-macro2", 502 + "quote", 503 + "syn", 504 + ] 505 + 506 + [[package]] 507 + name = "thread_local" 508 + version = "1.1.9" 509 + source = "registry+https://github.com/rust-lang/crates.io-index" 510 + checksum = "f60246a4944f24f6e018aa17cdeffb7818b76356965d03b07d6a9886e8962185" 511 + dependencies = [ 512 + "cfg-if", 513 + ] 514 + 515 + [[package]] 516 + name = "tokio" 517 + version = "1.48.0" 518 + source = "registry+https://github.com/rust-lang/crates.io-index" 519 + checksum = "ff360e02eab121e0bc37a2d3b4d4dc622e6eda3a8e5253d5435ecf5bd4c68408" 520 + dependencies = [ 521 + "bytes", 522 + "libc", 523 + "mio", 524 + "parking_lot", 525 + "pin-project-lite", 526 + "signal-hook-registry", 527 + "socket2", 528 + "tokio-macros", 529 + "windows-sys 0.61.2", 530 + ] 531 + 532 + [[package]] 533 + name = "tokio-macros" 534 + version = "2.6.0" 535 + source = "registry+https://github.com/rust-lang/crates.io-index" 536 + checksum = "af407857209536a95c8e56f8231ef2c2e2aff839b22e07a1ffcbc617e9db9fa5" 537 + dependencies = [ 538 + "proc-macro2", 539 + "quote", 540 + "syn", 541 + ] 542 + 543 + [[package]] 544 + name = "tokio-tungstenite" 545 + version = "0.23.1" 546 + source = "registry+https://github.com/rust-lang/crates.io-index" 547 + checksum = "c6989540ced10490aaf14e6bad2e3d33728a2813310a0c71d1574304c49631cd" 548 + dependencies = [ 549 + "futures-util", 550 + "log", 551 + "tokio", 552 + "tungstenite", 553 + ] 554 + 555 + [[package]] 556 + name = "tracing" 557 + version = "0.1.41" 558 + source = "registry+https://github.com/rust-lang/crates.io-index" 559 + checksum = "784e0ac535deb450455cbfa28a6f0df145ea1bb7ae51b821cf5e7927fdcfbdd0" 560 + dependencies = [ 561 + "pin-project-lite", 562 + "tracing-attributes", 563 + "tracing-core", 564 + ] 565 + 566 + [[package]] 567 + name = "tracing-attributes" 568 + version = "0.1.30" 569 + source = "registry+https://github.com/rust-lang/crates.io-index" 570 + checksum = "81383ab64e72a7a8b8e13130c49e3dab29def6d0c7d76a03087b3cf71c5c6903" 571 + dependencies = [ 572 + "proc-macro2", 573 + "quote", 574 + "syn", 575 + ] 576 + 577 + [[package]] 578 + name = "tracing-core" 579 + version = "0.1.34" 580 + source = "registry+https://github.com/rust-lang/crates.io-index" 581 + checksum = "b9d12581f227e93f094d3af2ae690a574abb8a2b9b7a96e7cfe9647b2b617678" 582 + dependencies = [ 583 + "once_cell", 584 + "valuable", 585 + ] 586 + 587 + [[package]] 588 + name = "tracing-log" 589 + version = "0.2.0" 590 + source = "registry+https://github.com/rust-lang/crates.io-index" 591 + checksum = "ee855f1f400bd0e5c02d150ae5de3840039a3f54b025156404e34c23c03f47c3" 592 + dependencies = [ 593 + "log", 594 + "once_cell", 595 + "tracing-core", 596 + ] 597 + 598 + [[package]] 599 + name = "tracing-subscriber" 600 + version = "0.3.20" 601 + source = "registry+https://github.com/rust-lang/crates.io-index" 602 + checksum = "2054a14f5307d601f88daf0553e1cbf472acc4f2c51afab632431cdcd72124d5" 603 + dependencies = [ 604 + "nu-ansi-term", 605 + "sharded-slab", 606 + "smallvec", 607 + "thread_local", 608 + "tracing-core", 609 + "tracing-log", 610 + ] 611 + 612 + [[package]] 613 + name = "tungstenite" 614 + version = "0.23.0" 615 + source = "registry+https://github.com/rust-lang/crates.io-index" 616 + checksum = "6e2e2ce1e47ed2994fd43b04c8f618008d4cabdd5ee34027cf14f9d918edd9c8" 617 + dependencies = [ 618 + "byteorder", 619 + "bytes", 620 + "data-encoding", 621 + "http", 622 + "httparse", 623 + "log", 624 + "rand", 625 + "sha1", 626 + "thiserror", 627 + "utf-8", 628 + ] 629 + 630 + [[package]] 631 + name = "typenum" 632 + version = "1.19.0" 633 + source = "registry+https://github.com/rust-lang/crates.io-index" 634 + checksum = "562d481066bde0658276a35467c4af00bdc6ee726305698a55b86e61d7ad82bb" 635 + 636 + [[package]] 637 + name = "unicode-ident" 638 + version = "1.0.19" 639 + source = "registry+https://github.com/rust-lang/crates.io-index" 640 + checksum = "f63a545481291138910575129486daeaf8ac54aee4387fe7906919f7830c7d9d" 641 + 642 + [[package]] 643 + name = "utf-8" 644 + version = "0.7.6" 645 + source = "registry+https://github.com/rust-lang/crates.io-index" 646 + checksum = "09cc8ee72d2a9becf2f2febe0205bbed8fc6615b7cb429ad062dc7b7ddd036a9" 647 + 648 + [[package]] 649 + name = "uuid" 650 + version = "1.18.1" 651 + source = "registry+https://github.com/rust-lang/crates.io-index" 652 + checksum = "2f87b8aa10b915a06587d0dec516c282ff295b475d94abf425d62b57710070a2" 653 + dependencies = [ 654 + "getrandom 0.3.4", 655 + "js-sys", 656 + "wasm-bindgen", 657 + ] 658 + 659 + [[package]] 660 + name = "valuable" 661 + version = "0.1.1" 662 + source = "registry+https://github.com/rust-lang/crates.io-index" 663 + checksum = "ba73ea9cf16a25df0c8caa16c51acb937d5712a8429db78a3ee29d5dcacd3a65" 664 + 665 + [[package]] 666 + name = "version_check" 667 + version = "0.9.5" 668 + source = "registry+https://github.com/rust-lang/crates.io-index" 669 + checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" 670 + 671 + [[package]] 672 + name = "wasi" 673 + version = "0.11.1+wasi-snapshot-preview1" 674 + source = "registry+https://github.com/rust-lang/crates.io-index" 675 + checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b" 676 + 677 + [[package]] 678 + name = "wasip2" 679 + version = "1.0.1+wasi-0.2.4" 680 + source = "registry+https://github.com/rust-lang/crates.io-index" 681 + checksum = "0562428422c63773dad2c345a1882263bbf4d65cf3f42e90921f787ef5ad58e7" 682 + dependencies = [ 683 + "wit-bindgen", 684 + ] 685 + 686 + [[package]] 687 + name = "wasm-bindgen" 688 + version = "0.2.104" 689 + source = "registry+https://github.com/rust-lang/crates.io-index" 690 + checksum = "c1da10c01ae9f1ae40cbfac0bac3b1e724b320abfcf52229f80b547c0d250e2d" 691 + dependencies = [ 692 + "cfg-if", 693 + "once_cell", 694 + "rustversion", 695 + "wasm-bindgen-macro", 696 + "wasm-bindgen-shared", 697 + ] 698 + 699 + [[package]] 700 + name = "wasm-bindgen-backend" 701 + version = "0.2.104" 702 + source = "registry+https://github.com/rust-lang/crates.io-index" 703 + checksum = "671c9a5a66f49d8a47345ab942e2cb93c7d1d0339065d4f8139c486121b43b19" 704 + dependencies = [ 705 + "bumpalo", 706 + "log", 707 + "proc-macro2", 708 + "quote", 709 + "syn", 710 + "wasm-bindgen-shared", 711 + ] 712 + 713 + [[package]] 714 + name = "wasm-bindgen-macro" 715 + version = "0.2.104" 716 + source = "registry+https://github.com/rust-lang/crates.io-index" 717 + checksum = "7ca60477e4c59f5f2986c50191cd972e3a50d8a95603bc9434501cf156a9a119" 718 + dependencies = [ 719 + "quote", 720 + "wasm-bindgen-macro-support", 721 + ] 722 + 723 + [[package]] 724 + name = "wasm-bindgen-macro-support" 725 + version = "0.2.104" 726 + source = "registry+https://github.com/rust-lang/crates.io-index" 727 + checksum = "9f07d2f20d4da7b26400c9f4a0511e6e0345b040694e8a75bd41d578fa4421d7" 728 + dependencies = [ 729 + "proc-macro2", 730 + "quote", 731 + "syn", 732 + "wasm-bindgen-backend", 733 + "wasm-bindgen-shared", 734 + ] 735 + 736 + [[package]] 737 + name = "wasm-bindgen-shared" 738 + version = "0.2.104" 739 + source = "registry+https://github.com/rust-lang/crates.io-index" 740 + checksum = "bad67dc8b2a1a6e5448428adec4c3e84c43e561d8c9ee8a9e5aabeb193ec41d1" 741 + dependencies = [ 742 + "unicode-ident", 743 + ] 744 + 745 + [[package]] 746 + name = "windows-link" 747 + version = "0.2.1" 748 + source = "registry+https://github.com/rust-lang/crates.io-index" 749 + checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5" 750 + 751 + [[package]] 752 + name = "windows-sys" 753 + version = "0.59.0" 754 + source = "registry+https://github.com/rust-lang/crates.io-index" 755 + checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" 756 + dependencies = [ 757 + "windows-targets 0.52.6", 758 + ] 759 + 760 + [[package]] 761 + name = "windows-sys" 762 + version = "0.60.2" 763 + source = "registry+https://github.com/rust-lang/crates.io-index" 764 + checksum = "f2f500e4d28234f72040990ec9d39e3a6b950f9f22d3dba18416c35882612bcb" 765 + dependencies = [ 766 + "windows-targets 0.53.5", 767 + ] 768 + 769 + [[package]] 770 + name = "windows-sys" 771 + version = "0.61.2" 772 + source = "registry+https://github.com/rust-lang/crates.io-index" 773 + checksum = "ae137229bcbd6cdf0f7b80a31df61766145077ddf49416a728b02cb3921ff3fc" 774 + dependencies = [ 775 + "windows-link", 776 + ] 777 + 778 + [[package]] 779 + name = "windows-targets" 780 + version = "0.52.6" 781 + source = "registry+https://github.com/rust-lang/crates.io-index" 782 + checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" 783 + dependencies = [ 784 + "windows_aarch64_gnullvm 0.52.6", 785 + "windows_aarch64_msvc 0.52.6", 786 + "windows_i686_gnu 0.52.6", 787 + "windows_i686_gnullvm 0.52.6", 788 + "windows_i686_msvc 0.52.6", 789 + "windows_x86_64_gnu 0.52.6", 790 + "windows_x86_64_gnullvm 0.52.6", 791 + "windows_x86_64_msvc 0.52.6", 792 + ] 793 + 794 + [[package]] 795 + name = "windows-targets" 796 + version = "0.53.5" 797 + source = "registry+https://github.com/rust-lang/crates.io-index" 798 + checksum = "4945f9f551b88e0d65f3db0bc25c33b8acea4d9e41163edf90dcd0b19f9069f3" 799 + dependencies = [ 800 + "windows-link", 801 + "windows_aarch64_gnullvm 0.53.1", 802 + "windows_aarch64_msvc 0.53.1", 803 + "windows_i686_gnu 0.53.1", 804 + "windows_i686_gnullvm 0.53.1", 805 + "windows_i686_msvc 0.53.1", 806 + "windows_x86_64_gnu 0.53.1", 807 + "windows_x86_64_gnullvm 0.53.1", 808 + "windows_x86_64_msvc 0.53.1", 809 + ] 810 + 811 + [[package]] 812 + name = "windows_aarch64_gnullvm" 813 + version = "0.52.6" 814 + source = "registry+https://github.com/rust-lang/crates.io-index" 815 + checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" 816 + 817 + [[package]] 818 + name = "windows_aarch64_gnullvm" 819 + version = "0.53.1" 820 + source = "registry+https://github.com/rust-lang/crates.io-index" 821 + checksum = "a9d8416fa8b42f5c947f8482c43e7d89e73a173cead56d044f6a56104a6d1b53" 822 + 823 + [[package]] 824 + name = "windows_aarch64_msvc" 825 + version = "0.52.6" 826 + source = "registry+https://github.com/rust-lang/crates.io-index" 827 + checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" 828 + 829 + [[package]] 830 + name = "windows_aarch64_msvc" 831 + version = "0.53.1" 832 + source = "registry+https://github.com/rust-lang/crates.io-index" 833 + checksum = "b9d782e804c2f632e395708e99a94275910eb9100b2114651e04744e9b125006" 834 + 835 + [[package]] 836 + name = "windows_i686_gnu" 837 + version = "0.52.6" 838 + source = "registry+https://github.com/rust-lang/crates.io-index" 839 + checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" 840 + 841 + [[package]] 842 + name = "windows_i686_gnu" 843 + version = "0.53.1" 844 + source = "registry+https://github.com/rust-lang/crates.io-index" 845 + checksum = "960e6da069d81e09becb0ca57a65220ddff016ff2d6af6a223cf372a506593a3" 846 + 847 + [[package]] 848 + name = "windows_i686_gnullvm" 849 + version = "0.52.6" 850 + source = "registry+https://github.com/rust-lang/crates.io-index" 851 + checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" 852 + 853 + [[package]] 854 + name = "windows_i686_gnullvm" 855 + version = "0.53.1" 856 + source = "registry+https://github.com/rust-lang/crates.io-index" 857 + checksum = "fa7359d10048f68ab8b09fa71c3daccfb0e9b559aed648a8f95469c27057180c" 858 + 859 + [[package]] 860 + name = "windows_i686_msvc" 861 + version = "0.52.6" 862 + source = "registry+https://github.com/rust-lang/crates.io-index" 863 + checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" 864 + 865 + [[package]] 866 + name = "windows_i686_msvc" 867 + version = "0.53.1" 868 + source = "registry+https://github.com/rust-lang/crates.io-index" 869 + checksum = "1e7ac75179f18232fe9c285163565a57ef8d3c89254a30685b57d83a38d326c2" 870 + 871 + [[package]] 872 + name = "windows_x86_64_gnu" 873 + version = "0.52.6" 874 + source = "registry+https://github.com/rust-lang/crates.io-index" 875 + checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" 876 + 877 + [[package]] 878 + name = "windows_x86_64_gnu" 879 + version = "0.53.1" 880 + source = "registry+https://github.com/rust-lang/crates.io-index" 881 + checksum = "9c3842cdd74a865a8066ab39c8a7a473c0778a3f29370b5fd6b4b9aa7df4a499" 882 + 883 + [[package]] 884 + name = "windows_x86_64_gnullvm" 885 + version = "0.52.6" 886 + source = "registry+https://github.com/rust-lang/crates.io-index" 887 + checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" 888 + 889 + [[package]] 890 + name = "windows_x86_64_gnullvm" 891 + version = "0.53.1" 892 + source = "registry+https://github.com/rust-lang/crates.io-index" 893 + checksum = "0ffa179e2d07eee8ad8f57493436566c7cc30ac536a3379fdf008f47f6bb7ae1" 894 + 895 + [[package]] 896 + name = "windows_x86_64_msvc" 897 + version = "0.52.6" 898 + source = "registry+https://github.com/rust-lang/crates.io-index" 899 + checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" 900 + 901 + [[package]] 902 + name = "windows_x86_64_msvc" 903 + version = "0.53.1" 904 + source = "registry+https://github.com/rust-lang/crates.io-index" 905 + checksum = "d6bbff5f0aada427a1e5a6da5f1f98158182f26556f345ac9e04d36d0ebed650" 906 + 907 + [[package]] 908 + name = "wit-bindgen" 909 + version = "0.46.0" 910 + source = "registry+https://github.com/rust-lang/crates.io-index" 911 + checksum = "f17a85883d4e6d00e8a97c586de764dabcc06133f7f1d55dce5cdc070ad7fe59" 912 + 913 + [[package]] 914 + name = "zerocopy" 915 + version = "0.8.27" 916 + source = "registry+https://github.com/rust-lang/crates.io-index" 917 + checksum = "0894878a5fa3edfd6da3f88c4805f4c8558e2b996227a3d864f47fe11e38282c" 918 + dependencies = [ 919 + "zerocopy-derive", 920 + ] 921 + 922 + [[package]] 923 + name = "zerocopy-derive" 924 + version = "0.8.27" 925 + source = "registry+https://github.com/rust-lang/crates.io-index" 926 + checksum = "88d2b8d9c68ad2b9e4340d7832716a4d21a22a1154777ad56ea55c51a9cf3831" 927 + dependencies = [ 928 + "proc-macro2", 929 + "quote", 930 + "syn", 931 + ]
+30
control-plane/job-board/Cargo.toml
··· 1 + [package] 2 + name = "job-board-orchestrator" 3 + version = "0.1.0" 4 + edition = "2024" 5 + 6 + [dependencies] 7 + # The core async runtime for Rust 8 + tokio = { version = "1", features = ["full"] } 9 + 10 + # WebSocket library that integrates with Tokio 11 + tokio-tungstenite = "0.23" 12 + 13 + # Utilities for working with async streams and sinks 14 + futures-util = { version = "0.3", default-features = false, features = ["sink", "std"] } 15 + 16 + # Framework for serializing and deserializing Rust data structures 17 + serde = { version = "1.0", features = ["derive"] } 18 + 19 + # A JSON implementation for Serde 20 + serde_json = "1.0" 21 + 22 + # For generating unique identifiers for jobs 23 + uuid = { version = "1.8", features = ["v4"] } 24 + 25 + # A framework for structured, event-based logging 26 + tracing = "0.1" 27 + 28 + # A subscriber for the tracing framework that formats and outputs logs 29 + tracing-subscriber = "0.3" 30 +
+11
control-plane/job-board/README.md
··· 1 + # Job board 2 + 3 + This posts jobs for worker nodes to try to bid to recieve. So far in the development, the node with the most available resources wins. 4 + 5 + More coming soon. 6 + 7 + Here's an example response from a worker node in case you want to `wscat` to the job board to test responses: 8 + 9 + bash``` 10 + { "type": "BidResponse", "job_id": "PASTE_THE_JOB_ID_HERE", "available_cpu_cores": 999, "available_ram_mb": 99999, "available_storage_mb": 999999 } 11 + ```
+265
control-plane/job-board/src/main.rs
··· 1 + use futures_util::{ 2 + stream::{SplitSink}, 3 + SinkExt, StreamExt, 4 + }; 5 + use serde::{Deserialize, Serialize}; 6 + use std::{ 7 + collections::{HashMap, VecDeque}, 8 + net::SocketAddr, 9 + sync::Arc, 10 + time::{Duration, Instant}, 11 + }; 12 + use tokio::{ 13 + net::{TcpListener, TcpStream}, 14 + sync::Mutex, 15 + }; 16 + use tokio_tungstenite::{ 17 + accept_async, 18 + tungstenite::{Message}, 19 + WebSocketStream, 20 + }; 21 + use tracing::{error, info, instrument}; 22 + use tracing_subscriber::FmtSubscriber; 23 + use uuid::Uuid; 24 + 25 + type PeerMap = Arc<Mutex<HashMap<SocketAddr, SplitSink<WebSocketStream<TcpStream>, Message>>>>; 26 + type JobQueue = Arc<Mutex<VecDeque<Job>>>; 27 + type Bids = Arc<Mutex<HashMap<SocketAddr, Bid>>>; 28 + 29 + #[derive(Debug, Serialize, Deserialize, Clone)] 30 + struct Job { 31 + id: String, 32 + payload: String, 33 + } 34 + 35 + #[derive(Debug, Serialize, Deserialize, Clone)] 36 + struct Bid { 37 + job_id: String, 38 + available_cpu_cores: u32, 39 + available_ram_mb: u32, 40 + available_storage_mb: u32, 41 + } 42 + 43 + impl Bid { 44 + fn score(&self) -> u64 { 45 + (self.available_cpu_cores as u64 * 1000) 46 + + self.available_ram_mb as u64 47 + + (self.available_storage_mb as u64 / 10) 48 + } 49 + } 50 + 51 + #[derive(Debug, Serialize, Deserialize)] 52 + #[serde(tag = "type")] 53 + enum ServerMessage { 54 + PingForBids { job_id: String }, 55 + AssignJob { job: Job }, 56 + Acknowledge, 57 + } 58 + 59 + #[derive(Debug, Serialize, Deserialize)] 60 + #[serde(tag = "type")] 61 + enum WorkerMessage { 62 + BidResponse(Bid), 63 + } 64 + 65 + #[tokio::main] 66 + async fn main() { 67 + FmtSubscriber::builder() 68 + .with_max_level(tracing::Level::INFO) 69 + .init(); 70 + 71 + let peers: PeerMap = Arc::new(Mutex::new(HashMap::new())); 72 + let job_queue: JobQueue = Arc::new(Mutex::new(VecDeque::new())); 73 + let bids: Bids = Arc::new(Mutex::new(HashMap::new())); 74 + 75 + { 76 + let mut queue = job_queue.lock().await; 77 + info!("Populating job queue with initial jobs..."); 78 + for i in 1..=5 { 79 + queue.push_back(Job { 80 + id: Uuid::new_v4().to_string(), 81 + payload: format!("This is job number {}", i), 82 + }); 83 + } 84 + info!("{} jobs added to the queue.", queue.len()); 85 + } 86 + 87 + let peers_clone = Arc::clone(&peers); 88 + let queue_clone = Arc::clone(&job_queue); 89 + let bids_clone = Arc::clone(&bids); 90 + tokio::spawn(async move { 91 + queue_monitor(queue_clone, peers_clone, bids_clone).await; 92 + }); 93 + 94 + let addr = "127.0.0.1:9001"; 95 + let listener = TcpListener::bind(&addr).await.expect("Failed to bind"); 96 + info!("Job Board listening on: {}", addr); 97 + 98 + while let Ok((stream, addr)) = listener.accept().await { 99 + info!("New worker connection from: {}", addr); 100 + tokio::spawn(handle_connection( 101 + Arc::clone(&peers), 102 + Arc::clone(&bids), 103 + stream, 104 + addr, 105 + )); 106 + } 107 + } 108 + 109 + #[instrument(skip(peers, bids, stream))] 110 + async fn handle_connection( 111 + peers: PeerMap, 112 + bids: Bids, 113 + stream: TcpStream, 114 + addr: SocketAddr, 115 + ) { 116 + let ws_stream = match accept_async(stream).await { 117 + Ok(ws) => ws, 118 + Err(e) => { 119 + error!("Error during WebSocket handshake: {}", e); 120 + return; 121 + } 122 + }; 123 + info!("WebSocket connection established: {}", addr); 124 + 125 + let (mut ws_sender, mut ws_receiver) = ws_stream.split(); 126 + 127 + let ack_msg = ServerMessage::Acknowledge; 128 + let ack_json = serde_json::to_string(&ack_msg).unwrap(); 129 + if ws_sender.send(Message::Text(ack_json)).await.is_err() { 130 + error!("Failed to send Acknowledge to {}", addr); 131 + return; 132 + } 133 + 134 + peers.lock().await.insert(addr, ws_sender); 135 + 136 + while let Some(msg) = ws_receiver.next().await { 137 + match msg { 138 + Ok(Message::Text(text)) => { 139 + match serde_json::from_str::<WorkerMessage>(&text) { 140 + Ok(WorkerMessage::BidResponse(bid)) => { 141 + info!("Received bid from {}: {:?}", addr, bid); 142 + bids.lock().await.insert(addr, bid); 143 + } 144 + Err(e) => { 145 + error!("Error deserializing message from {}: {}", addr, e); 146 + } 147 + } 148 + } 149 + Ok(Message::Close(_)) => { 150 + info!("Received Close message from {}", addr); 151 + break; 152 + } 153 + Err(tokio_tungstenite::tungstenite::Error::ConnectionClosed) => { 154 + info!("Connection to {} closed gracefully.", addr); 155 + break; 156 + } 157 + Err(e) => { 158 + error!("Error receiving message from {}: {}", addr, e); 159 + break; 160 + } 161 + _ => {} 162 + } 163 + } 164 + 165 + info!("Worker {} disconnected.", addr); 166 + peers.lock().await.remove(&addr); 167 + } 168 + 169 + #[instrument(skip(job_queue, peers, bids))] 170 + async fn queue_monitor(job_queue: JobQueue, peers: PeerMap, bids: Bids) { 171 + loop { 172 + tokio::time::sleep(Duration::from_secs(3)).await; 173 + 174 + let job = { 175 + let mut queue = job_queue.lock().await; 176 + queue.pop_front() 177 + }; 178 + 179 + if let Some(job) = job { 180 + info!("Found job {} in queue. Starting bidding process.", job.id); 181 + 182 + bids.lock().await.clear(); 183 + 184 + let ping_msg = ServerMessage::PingForBids { 185 + job_id: job.id.clone(), 186 + }; 187 + let ping_json = serde_json::to_string(&ping_msg).unwrap(); 188 + let mut disconnected_peers = Vec::new(); 189 + 190 + let expected_bids = { 191 + let mut peers_map = peers.lock().await; 192 + if peers_map.is_empty() { 193 + info!("No workers connected. Returning job to the front of the queue."); 194 + job_queue.lock().await.push_front(job); 195 + continue; 196 + } 197 + 198 + info!("Pinging {} connected workers for bids.", peers_map.len()); 199 + for (addr, sender) in peers_map.iter_mut() { 200 + if sender.send(Message::Text(ping_json.clone())).await.is_err() { 201 + error!("Failed to send ping to {}. Marking for removal.", addr); 202 + disconnected_peers.push(*addr); 203 + } 204 + } 205 + peers_map.len() - disconnected_peers.len() 206 + }; 207 + 208 + if !disconnected_peers.is_empty() { 209 + let mut peers_map = peers.lock().await; 210 + for addr in disconnected_peers { 211 + peers_map.remove(&addr); 212 + } 213 + } 214 + 215 + if expected_bids == 0 { 216 + info!("No active workers to ping. Returning job to the front of the queue."); 217 + job_queue.lock().await.push_front(job); 218 + continue; 219 + } 220 + 221 + info!("Waiting up to 3 seconds for {} workers to submit bids...", expected_bids); 222 + let bidding_deadline = Instant::now() + Duration::from_secs(3); 223 + 224 + while Instant::now() < bidding_deadline { 225 + let bids_received = bids.lock().await.len(); 226 + if bids_received >= expected_bids { 227 + info!("All {} expected bids received early.", expected_bids); 228 + break; 229 + } 230 + // tokio::time::sleep(Duration::from_millis(100)).await; 231 + } 232 + 233 + let winner = { 234 + let bids_map = bids.lock().await; 235 + info!("Evaluating {} bids received.", bids_map.len()); 236 + bids_map 237 + .iter() 238 + .max_by_key(|(_, bid)| bid.score()) 239 + .map(|(addr, _)| *addr) 240 + }; 241 + 242 + if let Some(winner_addr) = winner { 243 + info!( 244 + "Bidding complete. Winner is {}. Assigning job {}.", 245 + winner_addr, job.id 246 + ); 247 + let mut peers_map = peers.lock().await; 248 + if let Some(winner_sender) = peers_map.get_mut(&winner_addr) { 249 + let assign_msg = ServerMessage::AssignJob { job }; 250 + let assign_json = serde_json::to_string(&assign_msg).unwrap(); 251 + if winner_sender 252 + .send(Message::Text(assign_json)) 253 + .await 254 + .is_err() 255 + { 256 + error!("Failed to assign job to winner {}.", winner_addr); 257 + } 258 + } 259 + } else { 260 + info!("No bids received for job {}. Returning it to the front of the queue.", job.id); 261 + job_queue.lock().await.push_front(job); 262 + } 263 + } 264 + } 265 + }
+4
worker-plane/vm/.gitignore
··· 1 + vmlinux* 2 + firecracker 3 + firecracker.log 4 + alpine-with-podman.ext4
+84
worker-plane/vm/README.md
··· 1 + # The VM that contains a given pod 2 + 3 + ## Manual installation 4 + 5 + Add the firecracker binary to your system. 6 + 7 + Download a vmlinux* that has the virtio etc installed in itself and not as modules. For example, AWS seems to have one readymade, from the firecracker docs: 8 + 9 + ``` 10 + ARCH="$(uname -m)" 11 + release_url="https://github.com/firecracker-microvm/firecracker/releases" 12 + latest_version=$(basename $(curl -fsSLI -o /dev/null -w %{url_effective} ${release_url}/latest)) 13 + CI_VERSION=${latest_version%.*} 14 + latest_kernel_key=$(curl "http://spec.ccfc.min.s3.amazonaws.com/?prefix=firecracker-ci/$CI_VERSION/$ARCH/vmlinux-&list-type=2" \ 15 + | grep -oP "(?<=<Key>)(firecracker-ci/$CI_VERSION/$ARCH/vmlinux-[0-9]+\.[0-9]+\.[0-9]{1,3})(?=</Key>)" \ 16 + | sort -V | tail -1) 17 + 18 + # Download a linux kernel binary 19 + wget "https://s3.amazonaws.com/spec.ccfc.min/${latest_kernel_key}" 20 + ``` 21 + 22 + Add the following network rules to your system (not necessary at this stage of the project but good to have) 23 + 24 + ``` 25 + TAP_DEV="tap0" 26 + TAP_IP="172.16.0.1" 27 + MASK_SHORT="/30" 28 + HOST_IFACE=$(ip -j route list default | jq -r '.[0].dev') 29 + 30 + # Setup network interface on the host 31 + sudo ip link del "$TAP_DEV" 2> /dev/null || true 32 + sudo ip tuntap add dev "$TAP_DEV" mode tap 33 + sudo ip addr add "${TAP_IP}${MASK_SHORT}" dev "$TAP_DEV" 34 + sudo ip link set dev "$TAP_DEV" up 35 + 36 + # Enable IP forwarding and masquerading 37 + sudo sh -c "echo 1 > /proc/sys/net/ipv4/ip_forward" 38 + sudo iptables -P FORWARD ACCEPT 39 + sudo iptables -t nat -A POSTROUTING -o "$HOST_IFACE" -j MASQUERADE 40 + ``` 41 + 42 + Allow execution (chmod +x) on the create_alpine_rootfs.sh, then run it. 43 + 44 + `touch firecracker.log` 45 + 46 + Finally, to run the image: 47 + 48 + `sudo rm -f /tmp/firecracker.socket && sudo ./firecracker --api-sock /tmp/firecracker.socket --config-file firecracker-config.json` 49 + 50 + The username and password is root and root. Change that in the create_alpine_rootfs.sh file if you want. 51 + 52 + To exit the tty you'll have to `shutdown` or `reboot`. 53 + 54 + If you want to wire up the networking, complete the guest side of the host networking that we added on the host earlier: 55 + 56 + ``` 57 + ip addr add 172.16.0.2/30 dev eth0 58 + ip link set eth0 up 59 + ip route add default via 172.16.0.1 dev eth0 60 + echo "nameserver 8.8.8.8" > /etc/resolv.conf 61 + ``` 62 + ### TODO: prod machines that dynamically assign internal IPs on rootfs creation time 63 + 64 + Add to /etc/network/interfaces 65 + 66 + ``` 67 + auto lo 68 + iface lo inet loopback 69 + 70 + auto eth0 71 + iface eth0 inet static 72 + address 172.16.0.2 73 + netmask 255.255.255.252 74 + gateway 172.16.0.1 75 + ``` 76 + 77 + and at startup 78 + 79 + ``` 80 + rc-update add networking boot 81 + rc-service networking start 82 + ``` 83 + 84 + Hmm.. also should do something for ipv6 too.
+85
worker-plane/vm/create_alpine_rootfs.sh
··· 1 + #!/bin/bash 2 + 3 + set -e 4 + 5 + ALPINE_VERSION="v3.20" 6 + ARCH=$(uname -m) 7 + ROOTFS_DIR="alpine-podman-rootfs" 8 + ROOTFS_FILE="alpine-with-podman.ext4" 9 + ROOTFS_SIZE_MB=2048 10 + 11 + echo "--- Finding and fetching apk-tools-static for ${ARCH} ---" 12 + # Map uname arch to Alpine's arch naming 13 + case ${ARCH} in 14 + x86_64) ALPINE_ARCH="x86_64" ;; 15 + aarch64) ALPINE_ARCH="aarch64" ;; 16 + *) echo "Unsupported architecture: ${ARCH}"; exit 1 ;; 17 + esac 18 + 19 + REPO_URL="https://dl-cdn.alpinelinux.org/alpine/${ALPINE_VERSION}/main/${ALPINE_ARCH}" 20 + 21 + APK_TOOLS_PKG=$(curl -sL "${REPO_URL}/APKINDEX.tar.gz" | tar -xz -O APKINDEX | grep -F 'P:apk-tools-static' -A1 | grep -F 'V:' | cut -d: -f2 | xargs -I{} echo "apk-tools-static-{}.apk") 22 + APK_TOOLS_URL="${REPO_URL}/${APK_TOOLS_PKG}" 23 + 24 + echo "Found package: ${APK_TOOLS_PKG}" 25 + echo "Downloading from: ${APK_TOOLS_URL}" 26 + 27 + curl -sL "${APK_TOOLS_URL}" | tar -xz -C . sbin/apk.static 28 + mv sbin/apk.static . 29 + rmdir sbin 30 + chmod +x apk.static 31 + 32 + echo "Successfully fetched ./apk.static" 33 + 34 + echo "--- Ensuring host has 'mkfs.ext4' (e2fsprogs) ---" 35 + if ! command -v mkfs.ext4 &> /dev/null; then 36 + if command -v apt-get &> /dev/null; then 37 + sudo apt-get update && sudo apt-get install -y e2fsprogs 38 + elif command -v dnf &> /dev/null || command -v yum &> /dev/null; then 39 + sudo yum install -y e2fsprogs 40 + else 41 + echo "Error: mkfs.ext4 not found. Please install 'e2fsprogs' manually." 42 + exit 1 43 + fi 44 + fi 45 + 46 + echo "--- Bootstrapping Alpine ${ALPINE_VERSION} with Podman ---" 47 + sudo rm -rf "${ROOTFS_DIR}" 48 + mkdir -p "${ROOTFS_DIR}" 49 + 50 + sudo ./apk.static \ 51 + -X "https://dl-cdn.alpinelinux.org/alpine/${ALPINE_VERSION}/main" \ 52 + -X "https://dl-cdn.alpinelinux.org/alpine/${ALPINE_VERSION}/community" \ 53 + -U --allow-untrusted --root "${ROOTFS_DIR}" \ 54 + --initdb add alpine-base openrc podman util-linux 55 + 56 + echo "--- Configuring the rootfs ---" 57 + echo "root:root" | sudo chroot "${ROOTFS_DIR}" chpasswd 58 + 59 + sudo chroot "${ROOTFS_DIR}" rc-update add cgroups default 60 + 61 + cat << EOF | sudo tee "${ROOTFS_DIR}/etc/fstab" > /dev/null 62 + proc /proc proc defaults 0 0 63 + sysfs /sys sysfs defaults 0 0 64 + EOF 65 + 66 + echo 'ttyS0::respawn:/sbin/agetty -L 115200 ttyS0 vt100' | sudo tee -a "${ROOTFS_DIR}/etc/inittab" > /dev/null 67 + 68 + echo "--- Creating ${ROOTFS_SIZE_MB}MB ext4 image: ${ROOTFS_FILE} ---" 69 + rm -f "${ROOTFS_FILE}" 70 + dd if=/dev/zero of="${ROOTFS_FILE}" bs=1M count=${ROOTFS_SIZE_MB} 71 + mkfs.ext4 "${ROOTFS_FILE}" 72 + 73 + echo "--- Mounting image and copying rootfs data ---" 74 + MOUNT_DIR=$(mktemp -d) 75 + sudo mount -o loop "${ROOTFS_FILE}" "${MOUNT_DIR}" 76 + (cd "${ROOTFS_DIR}" && sudo tar -cf - .) | (cd "${MOUNT_DIR}" && sudo tar -xf -) 77 + 78 + echo "--- Cleaning up ---" 79 + sudo umount "${MOUNT_DIR}" 80 + rm -rf "${MOUNT_DIR}" 81 + sudo rm -rf "${ROOTFS_DIR}" 82 + rm ./apk.static 83 + 84 + echo "Success! Rootfs created at ./${ROOTFS_FILE}" 85 +
+32
worker-plane/vm/firecracker-config.json
··· 1 + { 2 + "boot-source": { 3 + "kernel_image_path": "./vmlinux-6.1.141", 4 + "boot_args": "console=ttyS0 reboot=k panic=1 pci=off root=/dev/vda rw init=/sbin/init" 5 + }, 6 + "drives": [ 7 + { 8 + "drive_id": "rootfs", 9 + "path_on_host": "./alpine-with-podman.ext4", 10 + "is_root_device": true, 11 + "is_read_only": false 12 + } 13 + ], 14 + "machine-config": { 15 + "vcpu_count": 2, 16 + "mem_size_mib": 1024, 17 + "smt": false 18 + }, 19 + "network-interfaces": [ 20 + { 21 + "iface_id": "net1", 22 + "guest_mac": "06:00:AC:10:00:02", 23 + "host_dev_name": "tap0" 24 + } 25 + ], 26 + "logger": { 27 + "log_path": "./firecracker.log", 28 + "level": "Debug", 29 + "show_level": true, 30 + "show_log_origin": true 31 + } 32 + }