Prepare, configure, and manage Firecracker microVMs in seconds!
virtualization linux microvm firecracker

Merge pull request #1 from tsirysndr/firecracker-vm-states

persist microvm informations into database

authored by tsiry-sandratraina.com and committed by

GitHub 401edb5e 2ed8cae5

+3774 -210
+2459 -25
Cargo.lock
··· 3 3 version = 4 4 4 5 5 [[package]] 6 + name = "addr2line" 7 + version = "0.24.2" 8 + source = "registry+https://github.com/rust-lang/crates.io-index" 9 + checksum = "dfbe277e56a376000877090da837660b4427aad530e3028d44e0bffe4f89a1c1" 10 + dependencies = [ 11 + "gimli", 12 + ] 13 + 14 + [[package]] 15 + name = "adler2" 16 + version = "2.0.1" 17 + source = "registry+https://github.com/rust-lang/crates.io-index" 18 + checksum = "320119579fcad9c21884f5c4861d16174d0e06250625266f50fe6898340abefa" 19 + 20 + [[package]] 6 21 name = "aho-corasick" 7 22 version = "1.1.3" 8 23 source = "registry+https://github.com/rust-lang/crates.io-index" ··· 12 27 ] 13 28 14 29 [[package]] 30 + name = "allocator-api2" 31 + version = "0.2.21" 32 + source = "registry+https://github.com/rust-lang/crates.io-index" 33 + checksum = "683d7910e743518b0e34f1186f92494becacb047c7b6bf616c96772180fef923" 34 + 35 + [[package]] 36 + name = "android_system_properties" 37 + version = "0.1.5" 38 + source = "registry+https://github.com/rust-lang/crates.io-index" 39 + checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311" 40 + dependencies = [ 41 + "libc", 42 + ] 43 + 44 + [[package]] 15 45 name = "anstream" 16 46 version = "0.6.19" 17 47 source = "registry+https://github.com/rust-lang/crates.io-index" ··· 47 77 source = "registry+https://github.com/rust-lang/crates.io-index" 48 78 checksum = "6c8bdeb6047d8983be085bab0ba1472e6dc604e7041dbf6fcd5e71523014fae9" 49 79 dependencies = [ 50 - "windows-sys", 80 + "windows-sys 0.59.0", 51 81 ] 52 82 53 83 [[package]] ··· 58 88 dependencies = [ 59 89 "anstyle", 60 90 "once_cell_polyfill", 61 - "windows-sys", 91 + "windows-sys 0.59.0", 62 92 ] 63 93 64 94 [[package]] ··· 68 98 checksum = "e16d2d3311acee920a9eb8d33b8cbc1787ce4a264e85f964c2404b969bdcd487" 69 99 70 100 [[package]] 101 + name = "atoi" 102 + version = "2.0.0" 103 + source = "registry+https://github.com/rust-lang/crates.io-index" 104 + checksum = "f28d99ec8bfea296261ca1af174f24225171fea9664ba9003cbebee704810528" 105 + dependencies = [ 106 + "num-traits", 107 + ] 108 + 109 + [[package]] 110 + name = "atty" 111 + version = "0.2.14" 112 + source = "registry+https://github.com/rust-lang/crates.io-index" 113 + checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8" 114 + dependencies = [ 115 + "hermit-abi 0.1.19", 116 + "libc", 117 + "winapi", 118 + ] 119 + 120 + [[package]] 121 + name = "autocfg" 122 + version = "1.5.0" 123 + source = "registry+https://github.com/rust-lang/crates.io-index" 124 + checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8" 125 + 126 + [[package]] 127 + name = "aws-lc-rs" 128 + version = "1.14.0" 129 + source = "registry+https://github.com/rust-lang/crates.io-index" 130 + checksum = "94b8ff6c09cd57b16da53641caa860168b88c172a5ee163b0288d3d6eea12786" 131 + dependencies = [ 132 + "aws-lc-sys", 133 + "zeroize", 134 + ] 135 + 136 + [[package]] 137 + name = "aws-lc-sys" 138 + version = "0.31.0" 139 + source = "registry+https://github.com/rust-lang/crates.io-index" 140 + checksum = "0e44d16778acaf6a9ec9899b92cebd65580b83f685446bf2e1f5d3d732f99dcd" 141 + dependencies = [ 142 + "bindgen", 143 + "cc", 144 + "cmake", 145 + "dunce", 146 + "fs_extra", 147 + ] 148 + 149 + [[package]] 150 + name = "backtrace" 151 + version = "0.3.75" 152 + source = "registry+https://github.com/rust-lang/crates.io-index" 153 + checksum = "6806a6321ec58106fea15becdad98371e28d92ccbc7c8f1b3b6dd724fe8f1002" 154 + dependencies = [ 155 + "addr2line", 156 + "cfg-if", 157 + "libc", 158 + "miniz_oxide", 159 + "object", 160 + "rustc-demangle", 161 + "windows-targets 0.52.6", 162 + ] 163 + 164 + [[package]] 165 + name = "base64" 166 + version = "0.22.1" 167 + source = "registry+https://github.com/rust-lang/crates.io-index" 168 + checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" 169 + 170 + [[package]] 171 + name = "base64ct" 172 + version = "1.8.0" 173 + source = "registry+https://github.com/rust-lang/crates.io-index" 174 + checksum = "55248b47b0caf0546f7988906588779981c43bb1bc9d0c44087278f80cdb44ba" 175 + 176 + [[package]] 177 + name = "bindgen" 178 + version = "0.72.1" 179 + source = "registry+https://github.com/rust-lang/crates.io-index" 180 + checksum = "993776b509cfb49c750f11b8f07a46fa23e0a1386ffc01fb1e7d343efc387895" 181 + dependencies = [ 182 + "bitflags 2.9.1", 183 + "cexpr", 184 + "clang-sys", 185 + "itertools", 186 + "log", 187 + "prettyplease", 188 + "proc-macro2", 189 + "quote", 190 + "regex", 191 + "rustc-hash", 192 + "shlex", 193 + "syn 2.0.104", 194 + ] 195 + 196 + [[package]] 197 + name = "bitflags" 198 + version = "1.3.2" 199 + source = "registry+https://github.com/rust-lang/crates.io-index" 200 + checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" 201 + 202 + [[package]] 71 203 name = "bitflags" 72 204 version = "2.9.1" 73 205 source = "registry+https://github.com/rust-lang/crates.io-index" 74 206 checksum = "1b8e56985ec62d17e9c1001dc89c88ecd7dc08e47eba5ec7c29c7b5eeecde967" 207 + dependencies = [ 208 + "serde", 209 + ] 210 + 211 + [[package]] 212 + name = "block-buffer" 213 + version = "0.10.4" 214 + source = "registry+https://github.com/rust-lang/crates.io-index" 215 + checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71" 216 + dependencies = [ 217 + "generic-array", 218 + ] 219 + 220 + [[package]] 221 + name = "bumpalo" 222 + version = "3.19.0" 223 + source = "registry+https://github.com/rust-lang/crates.io-index" 224 + checksum = "46c5e41b57b8bba42a04676d81cb89e9ee8e859a1a66f80a5a72e1cb76b34d43" 225 + 226 + [[package]] 227 + name = "byteorder" 228 + version = "1.5.0" 229 + source = "registry+https://github.com/rust-lang/crates.io-index" 230 + checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" 231 + 232 + [[package]] 233 + name = "bytes" 234 + version = "1.10.1" 235 + source = "registry+https://github.com/rust-lang/crates.io-index" 236 + checksum = "d71b6127be86fdcfddb610f7182ac57211d4b18a3e9c82eb2d17662f2227ad6a" 237 + 238 + [[package]] 239 + name = "cc" 240 + version = "1.2.30" 241 + source = "registry+https://github.com/rust-lang/crates.io-index" 242 + checksum = "deec109607ca693028562ed836a5f1c4b8bd77755c4e132fc5ce11b0b6211ae7" 243 + dependencies = [ 244 + "jobserver", 245 + "libc", 246 + "shlex", 247 + ] 248 + 249 + [[package]] 250 + name = "cexpr" 251 + version = "0.6.0" 252 + source = "registry+https://github.com/rust-lang/crates.io-index" 253 + checksum = "6fac387a98bb7c37292057cffc56d62ecb629900026402633ae9160df93a8766" 254 + dependencies = [ 255 + "nom", 256 + ] 75 257 76 258 [[package]] 77 259 name = "cfg-if" ··· 80 262 checksum = "9555578bc9e57714c812a1f84e4fc5b4d21fcb063490c624de019f7464c91268" 81 263 82 264 [[package]] 265 + name = "chrono" 266 + version = "0.4.42" 267 + source = "registry+https://github.com/rust-lang/crates.io-index" 268 + checksum = "145052bdd345b87320e369255277e3fb5152762ad123a901ef5c262dd38fe8d2" 269 + dependencies = [ 270 + "iana-time-zone", 271 + "js-sys", 272 + "num-traits", 273 + "serde", 274 + "wasm-bindgen", 275 + "windows-link 0.2.0", 276 + ] 277 + 278 + [[package]] 279 + name = "clang-sys" 280 + version = "1.8.1" 281 + source = "registry+https://github.com/rust-lang/crates.io-index" 282 + checksum = "0b023947811758c97c59bf9d1c188fd619ad4718dcaa767947df1cadb14f39f4" 283 + dependencies = [ 284 + "glob", 285 + "libc", 286 + "libloading", 287 + ] 288 + 289 + [[package]] 290 + name = "clap" 291 + version = "3.2.25" 292 + source = "registry+https://github.com/rust-lang/crates.io-index" 293 + checksum = "4ea181bf566f71cb9a5d17a59e1871af638180a18fb0035c92ae62b705207123" 294 + dependencies = [ 295 + "atty", 296 + "bitflags 1.3.2", 297 + "clap_derive", 298 + "clap_lex 0.2.4", 299 + "indexmap 1.9.3", 300 + "once_cell", 301 + "strsim 0.10.0", 302 + "termcolor", 303 + "textwrap", 304 + ] 305 + 306 + [[package]] 83 307 name = "clap" 84 308 version = "4.5.41" 85 309 source = "registry+https://github.com/rust-lang/crates.io-index" ··· 96 320 dependencies = [ 97 321 "anstream", 98 322 "anstyle", 99 - "clap_lex", 100 - "strsim", 323 + "clap_lex 0.7.5", 324 + "strsim 0.11.1", 325 + ] 326 + 327 + [[package]] 328 + name = "clap_derive" 329 + version = "3.2.25" 330 + source = "registry+https://github.com/rust-lang/crates.io-index" 331 + checksum = "ae6371b8bdc8b7d3959e9cf7b22d4435ef3e79e138688421ec654acf8c81b008" 332 + dependencies = [ 333 + "heck 0.4.1", 334 + "proc-macro-error", 335 + "proc-macro2", 336 + "quote", 337 + "syn 1.0.109", 338 + ] 339 + 340 + [[package]] 341 + name = "clap_lex" 342 + version = "0.2.4" 343 + source = "registry+https://github.com/rust-lang/crates.io-index" 344 + checksum = "2850f2f5a82cbf437dd5af4d49848fbdfc27c157c3d010345776f952765261c5" 345 + dependencies = [ 346 + "os_str_bytes", 101 347 ] 102 348 103 349 [[package]] ··· 107 353 checksum = "b94f61472cee1439c0b966b47e3aca9ae07e45d070759512cd390ea2bebc6675" 108 354 109 355 [[package]] 356 + name = "cmake" 357 + version = "0.1.54" 358 + source = "registry+https://github.com/rust-lang/crates.io-index" 359 + checksum = "e7caa3f9de89ddbe2c607f4101924c5abec803763ae9534e4f4d7d8f84aa81f0" 360 + dependencies = [ 361 + "cc", 362 + ] 363 + 364 + [[package]] 110 365 name = "colorchoice" 111 366 version = "1.0.4" 112 367 source = "registry+https://github.com/rust-lang/crates.io-index" 113 368 checksum = "b05b61dc5112cbb17e4b6cd61790d9845d13888356391624cbe7e41efeac1e75" 114 369 115 370 [[package]] 371 + name = "concurrent-queue" 372 + version = "2.5.0" 373 + source = "registry+https://github.com/rust-lang/crates.io-index" 374 + checksum = "4ca0197aee26d1ae37445ee532fefce43251d24cc7c166799f4d46817f1d3973" 375 + dependencies = [ 376 + "crossbeam-utils", 377 + ] 378 + 379 + [[package]] 380 + name = "const-oid" 381 + version = "0.9.6" 382 + source = "registry+https://github.com/rust-lang/crates.io-index" 383 + checksum = "c2459377285ad874054d797f3ccebf984978aa39129f6eafde5cdc8315b612f8" 384 + 385 + [[package]] 386 + name = "core-foundation" 387 + version = "0.10.1" 388 + source = "registry+https://github.com/rust-lang/crates.io-index" 389 + checksum = "b2a6cd9ae233e7f62ba4e9353e81a88df7fc8a5987b8d445b4d90c879bd156f6" 390 + dependencies = [ 391 + "core-foundation-sys", 392 + "libc", 393 + ] 394 + 395 + [[package]] 396 + name = "core-foundation-sys" 397 + version = "0.8.7" 398 + source = "registry+https://github.com/rust-lang/crates.io-index" 399 + checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b" 400 + 401 + [[package]] 402 + name = "cpufeatures" 403 + version = "0.2.17" 404 + source = "registry+https://github.com/rust-lang/crates.io-index" 405 + checksum = "59ed5838eebb26a2bb2e58f6d5b5316989ae9d08bab10e0e6d103e656d1b0280" 406 + dependencies = [ 407 + "libc", 408 + ] 409 + 410 + [[package]] 411 + name = "crc" 412 + version = "3.3.0" 413 + source = "registry+https://github.com/rust-lang/crates.io-index" 414 + checksum = "9710d3b3739c2e349eb44fe848ad0b7c8cb1e42bd87ee49371df2f7acaf3e675" 415 + dependencies = [ 416 + "crc-catalog", 417 + ] 418 + 419 + [[package]] 420 + name = "crc-catalog" 421 + version = "2.4.0" 422 + source = "registry+https://github.com/rust-lang/crates.io-index" 423 + checksum = "19d374276b40fb8bbdee95aef7c7fa6b5316ec764510eb64b8dd0e2ed0d7e7f5" 424 + 425 + [[package]] 426 + name = "crc32fast" 427 + version = "1.5.0" 428 + source = "registry+https://github.com/rust-lang/crates.io-index" 429 + checksum = "9481c1c90cbf2ac953f07c8d4a58aa3945c425b7185c9154d67a65e4230da511" 430 + dependencies = [ 431 + "cfg-if", 432 + ] 433 + 434 + [[package]] 435 + name = "crossbeam-queue" 436 + version = "0.3.12" 437 + source = "registry+https://github.com/rust-lang/crates.io-index" 438 + checksum = "0f58bbc28f91df819d0aa2a2c00cd19754769c2fad90579b3592b1c9ba7a3115" 439 + dependencies = [ 440 + "crossbeam-utils", 441 + ] 442 + 443 + [[package]] 444 + name = "crossbeam-utils" 445 + version = "0.8.21" 446 + source = "registry+https://github.com/rust-lang/crates.io-index" 447 + checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28" 448 + 449 + [[package]] 450 + name = "crypto-common" 451 + version = "0.1.6" 452 + source = "registry+https://github.com/rust-lang/crates.io-index" 453 + checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" 454 + dependencies = [ 455 + "generic-array", 456 + "typenum", 457 + ] 458 + 459 + [[package]] 460 + name = "der" 461 + version = "0.7.10" 462 + source = "registry+https://github.com/rust-lang/crates.io-index" 463 + checksum = "e7c1832837b905bbfb5101e07cc24c8deddf52f93225eee6ead5f4d63d53ddcb" 464 + dependencies = [ 465 + "const-oid", 466 + "pem-rfc7468", 467 + "zeroize", 468 + ] 469 + 470 + [[package]] 471 + name = "digest" 472 + version = "0.10.7" 473 + source = "registry+https://github.com/rust-lang/crates.io-index" 474 + checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" 475 + dependencies = [ 476 + "block-buffer", 477 + "const-oid", 478 + "crypto-common", 479 + "subtle", 480 + ] 481 + 482 + [[package]] 116 483 name = "dirs" 117 484 version = "6.0.0" 118 485 source = "registry+https://github.com/rust-lang/crates.io-index" ··· 130 497 "libc", 131 498 "option-ext", 132 499 "redox_users", 133 - "windows-sys", 500 + "windows-sys 0.61.0", 501 + ] 502 + 503 + [[package]] 504 + name = "displaydoc" 505 + version = "0.2.5" 506 + source = "registry+https://github.com/rust-lang/crates.io-index" 507 + checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0" 508 + dependencies = [ 509 + "proc-macro2", 510 + "quote", 511 + "syn 2.0.104", 512 + ] 513 + 514 + [[package]] 515 + name = "dotenvy" 516 + version = "0.15.7" 517 + source = "registry+https://github.com/rust-lang/crates.io-index" 518 + checksum = "1aaf95b3e5c8f23aa320147307562d361db0ae0d51242340f558153b4eb2439b" 519 + 520 + [[package]] 521 + name = "dunce" 522 + version = "1.0.5" 523 + source = "registry+https://github.com/rust-lang/crates.io-index" 524 + checksum = "92773504d58c093f6de2459af4af33faa518c13451eb8f2b5698ed3d36e7c813" 525 + 526 + [[package]] 527 + name = "either" 528 + version = "1.15.0" 529 + source = "registry+https://github.com/rust-lang/crates.io-index" 530 + checksum = "48c757948c5ede0e46177b7add2e67155f70e33c07fea8284df6576da70b3719" 531 + dependencies = [ 532 + "serde", 134 533 ] 135 534 136 535 [[package]] ··· 140 539 checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f" 141 540 142 541 [[package]] 542 + name = "etcetera" 543 + version = "0.8.0" 544 + source = "registry+https://github.com/rust-lang/crates.io-index" 545 + checksum = "136d1b5283a1ab77bd9257427ffd09d8667ced0570b6f938942bc7568ed5b943" 546 + dependencies = [ 547 + "cfg-if", 548 + "home", 549 + "windows-sys 0.48.0", 550 + ] 551 + 552 + [[package]] 553 + name = "event-listener" 554 + version = "5.4.1" 555 + source = "registry+https://github.com/rust-lang/crates.io-index" 556 + checksum = "e13b66accf52311f30a0db42147dadea9850cb48cd070028831ae5f5d4b856ab" 557 + dependencies = [ 558 + "concurrent-queue", 559 + "parking", 560 + "pin-project-lite", 561 + ] 562 + 563 + [[package]] 143 564 name = "fire-config" 144 565 version = "0.1.0" 145 566 dependencies = [ ··· 169 590 version = "0.1.0" 170 591 dependencies = [ 171 592 "anyhow", 593 + "firecracker-state", 172 594 "firecracker-vm", 173 595 "libc", 174 596 "owo-colors", 175 597 ] 176 598 177 599 [[package]] 600 + name = "firecracker-state" 601 + version = "0.1.0" 602 + dependencies = [ 603 + "anyhow", 604 + "chrono", 605 + "dirs", 606 + "names", 607 + "serde", 608 + "sqlx", 609 + "tokio", 610 + "xid", 611 + ] 612 + 613 + [[package]] 178 614 name = "firecracker-vm" 179 615 version = "0.1.0" 180 616 dependencies = [ ··· 182 618 "dirs", 183 619 "fire-config", 184 620 "firecracker-prepare", 621 + "firecracker-state", 185 622 "glob", 186 623 "libc", 624 + "names", 187 625 "num_cpus", 188 626 "owo-colors", 627 + "rand", 628 + "rumqttc", 189 629 "serde_json", 630 + "tokio", 190 631 ] 191 632 192 633 [[package]] ··· 194 635 version = "0.4.1" 195 636 dependencies = [ 196 637 "anyhow", 197 - "clap", 638 + "chrono", 639 + "clap 4.5.41", 198 640 "dirs", 199 641 "fire-config", 200 642 "firecracker-prepare", 201 643 "firecracker-process", 644 + "firecracker-state", 202 645 "firecracker-vm", 203 646 "glob", 647 + "names", 204 648 "num_cpus", 205 649 "owo-colors", 650 + "sqlx", 651 + "tokio", 652 + ] 653 + 654 + [[package]] 655 + name = "fixedbitset" 656 + version = "0.5.7" 657 + source = "registry+https://github.com/rust-lang/crates.io-index" 658 + checksum = "1d674e81391d1e1ab681a28d99df07927c6d4aa5b027d7da16ba32d1d21ecd99" 659 + 660 + [[package]] 661 + name = "flume" 662 + version = "0.11.1" 663 + source = "registry+https://github.com/rust-lang/crates.io-index" 664 + checksum = "da0e4dd2a88388a1f4ccc7c9ce104604dab68d9f408dc34cd45823d5a9069095" 665 + dependencies = [ 666 + "futures-core", 667 + "futures-sink", 668 + "spin", 669 + ] 670 + 671 + [[package]] 672 + name = "foldhash" 673 + version = "0.1.5" 674 + source = "registry+https://github.com/rust-lang/crates.io-index" 675 + checksum = "d9c4f5dac5e15c24eb999c26181a6ca40b39fe946cbe4c263c7209467bc83af2" 676 + 677 + [[package]] 678 + name = "form_urlencoded" 679 + version = "1.2.1" 680 + source = "registry+https://github.com/rust-lang/crates.io-index" 681 + checksum = "e13624c2627564efccf4934284bdd98cbaa14e79b0b5a141218e507b3a823456" 682 + dependencies = [ 683 + "percent-encoding", 684 + ] 685 + 686 + [[package]] 687 + name = "fs_extra" 688 + version = "1.3.0" 689 + source = "registry+https://github.com/rust-lang/crates.io-index" 690 + checksum = "42703706b716c37f96a77aea830392ad231f44c9e9a67872fa5548707e11b11c" 691 + 692 + [[package]] 693 + name = "futures-channel" 694 + version = "0.3.31" 695 + source = "registry+https://github.com/rust-lang/crates.io-index" 696 + checksum = "2dff15bf788c671c1934e366d07e30c1814a8ef514e1af724a602e8a2fbe1b10" 697 + dependencies = [ 698 + "futures-core", 699 + "futures-sink", 700 + ] 701 + 702 + [[package]] 703 + name = "futures-core" 704 + version = "0.3.31" 705 + source = "registry+https://github.com/rust-lang/crates.io-index" 706 + checksum = "05f29059c0c2090612e8d742178b0580d2dc940c837851ad723096f87af6663e" 707 + 708 + [[package]] 709 + name = "futures-executor" 710 + version = "0.3.31" 711 + source = "registry+https://github.com/rust-lang/crates.io-index" 712 + checksum = "1e28d1d997f585e54aebc3f97d39e72338912123a67330d723fdbb564d646c9f" 713 + dependencies = [ 714 + "futures-core", 715 + "futures-task", 716 + "futures-util", 717 + ] 718 + 719 + [[package]] 720 + name = "futures-intrusive" 721 + version = "0.5.0" 722 + source = "registry+https://github.com/rust-lang/crates.io-index" 723 + checksum = "1d930c203dd0b6ff06e0201a4a2fe9149b43c684fd4420555b26d21b1a02956f" 724 + dependencies = [ 725 + "futures-core", 726 + "lock_api", 727 + "parking_lot", 728 + ] 729 + 730 + [[package]] 731 + name = "futures-io" 732 + version = "0.3.31" 733 + source = "registry+https://github.com/rust-lang/crates.io-index" 734 + checksum = "9e5c1b78ca4aae1ac06c48a526a655760685149f0d465d21f37abfe57ce075c6" 735 + 736 + [[package]] 737 + name = "futures-sink" 738 + version = "0.3.31" 739 + source = "registry+https://github.com/rust-lang/crates.io-index" 740 + checksum = "e575fab7d1e0dcb8d0c7bcf9a63ee213816ab51902e6d244a95819acacf1d4f7" 741 + 742 + [[package]] 743 + name = "futures-task" 744 + version = "0.3.31" 745 + source = "registry+https://github.com/rust-lang/crates.io-index" 746 + checksum = "f90f7dce0722e95104fcb095585910c0977252f286e354b5e3bd38902cd99988" 747 + 748 + [[package]] 749 + name = "futures-util" 750 + version = "0.3.31" 751 + source = "registry+https://github.com/rust-lang/crates.io-index" 752 + checksum = "9fa08315bb612088cc391249efdc3bc77536f16c91f6cf495e6fbe85b20a4a81" 753 + dependencies = [ 754 + "futures-core", 755 + "futures-io", 756 + "futures-sink", 757 + "futures-task", 758 + "memchr", 759 + "pin-project-lite", 760 + "pin-utils", 761 + "slab", 762 + ] 763 + 764 + [[package]] 765 + name = "generic-array" 766 + version = "0.14.7" 767 + source = "registry+https://github.com/rust-lang/crates.io-index" 768 + checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" 769 + dependencies = [ 770 + "typenum", 771 + "version_check", 206 772 ] 207 773 208 774 [[package]] ··· 213 779 dependencies = [ 214 780 "cfg-if", 215 781 "libc", 216 - "wasi", 782 + "wasi 0.11.1+wasi-snapshot-preview1", 783 + ] 784 + 785 + [[package]] 786 + name = "getrandom" 787 + version = "0.3.3" 788 + source = "registry+https://github.com/rust-lang/crates.io-index" 789 + checksum = "26145e563e54f2cadc477553f1ec5ee650b00862f0a58bcd12cbdc5f0ea2d2f4" 790 + dependencies = [ 791 + "cfg-if", 792 + "libc", 793 + "r-efi", 794 + "wasi 0.14.5+wasi-0.2.4", 217 795 ] 218 796 219 797 [[package]] 798 + name = "gimli" 799 + version = "0.31.1" 800 + source = "registry+https://github.com/rust-lang/crates.io-index" 801 + checksum = "07e28edb80900c19c28f1072f2e8aeca7fa06b23cd4169cefe1af5aa3260783f" 802 + 803 + [[package]] 220 804 name = "glob" 221 805 version = "0.3.2" 222 806 source = "registry+https://github.com/rust-lang/crates.io-index" ··· 224 808 225 809 [[package]] 226 810 name = "hashbrown" 811 + version = "0.12.3" 812 + source = "registry+https://github.com/rust-lang/crates.io-index" 813 + checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" 814 + 815 + [[package]] 816 + name = "hashbrown" 227 817 version = "0.15.4" 228 818 source = "registry+https://github.com/rust-lang/crates.io-index" 229 819 checksum = "5971ac85611da7067dbfcabef3c70ebb5606018acd9e2a3903a0da507521e0d5" 820 + dependencies = [ 821 + "allocator-api2", 822 + "equivalent", 823 + "foldhash", 824 + ] 825 + 826 + [[package]] 827 + name = "hashlink" 828 + version = "0.10.0" 829 + source = "registry+https://github.com/rust-lang/crates.io-index" 830 + checksum = "7382cf6263419f2d8df38c55d7da83da5c18aef87fc7a7fc1fb1e344edfe14c1" 831 + dependencies = [ 832 + "hashbrown 0.15.4", 833 + ] 834 + 835 + [[package]] 836 + name = "heck" 837 + version = "0.4.1" 838 + source = "registry+https://github.com/rust-lang/crates.io-index" 839 + checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" 840 + 841 + [[package]] 842 + name = "heck" 843 + version = "0.5.0" 844 + source = "registry+https://github.com/rust-lang/crates.io-index" 845 + checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" 846 + 847 + [[package]] 848 + name = "hermit-abi" 849 + version = "0.1.19" 850 + source = "registry+https://github.com/rust-lang/crates.io-index" 851 + checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33" 852 + dependencies = [ 853 + "libc", 854 + ] 230 855 231 856 [[package]] 232 857 name = "hermit-abi" ··· 235 860 checksum = "fc0fef456e4baa96da950455cd02c081ca953b141298e41db3fc7e36b1da849c" 236 861 237 862 [[package]] 863 + name = "hex" 864 + version = "0.4.3" 865 + source = "registry+https://github.com/rust-lang/crates.io-index" 866 + checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" 867 + 868 + [[package]] 869 + name = "hkdf" 870 + version = "0.12.4" 871 + source = "registry+https://github.com/rust-lang/crates.io-index" 872 + checksum = "7b5f8eb2ad728638ea2c7d47a21db23b7b58a72ed6a38256b8a1849f15fbbdf7" 873 + dependencies = [ 874 + "hmac", 875 + ] 876 + 877 + [[package]] 878 + name = "hmac" 879 + version = "0.12.1" 880 + source = "registry+https://github.com/rust-lang/crates.io-index" 881 + checksum = "6c49c37c09c17a53d937dfbb742eb3a961d65a994e6bcdcf37e7399d0cc8ab5e" 882 + dependencies = [ 883 + "digest", 884 + ] 885 + 886 + [[package]] 887 + name = "home" 888 + version = "0.5.11" 889 + source = "registry+https://github.com/rust-lang/crates.io-index" 890 + checksum = "589533453244b0995c858700322199b2becb13b627df2851f64a2775d024abcf" 891 + dependencies = [ 892 + "windows-sys 0.59.0", 893 + ] 894 + 895 + [[package]] 896 + name = "hostname" 897 + version = "0.3.1" 898 + source = "registry+https://github.com/rust-lang/crates.io-index" 899 + checksum = "3c731c3e10504cc8ed35cfe2f1db4c9274c3d35fa486e3b31df46f068ef3e867" 900 + dependencies = [ 901 + "libc", 902 + "match_cfg", 903 + "winapi", 904 + ] 905 + 906 + [[package]] 907 + name = "iana-time-zone" 908 + version = "0.1.63" 909 + source = "registry+https://github.com/rust-lang/crates.io-index" 910 + checksum = "b0c919e5debc312ad217002b8048a17b7d83f80703865bbfcfebb0458b0b27d8" 911 + dependencies = [ 912 + "android_system_properties", 913 + "core-foundation-sys", 914 + "iana-time-zone-haiku", 915 + "js-sys", 916 + "log", 917 + "wasm-bindgen", 918 + "windows-core", 919 + ] 920 + 921 + [[package]] 922 + name = "iana-time-zone-haiku" 923 + version = "0.1.2" 924 + source = "registry+https://github.com/rust-lang/crates.io-index" 925 + checksum = "f31827a206f56af32e590ba56d5d2d085f558508192593743f16b2306495269f" 926 + dependencies = [ 927 + "cc", 928 + ] 929 + 930 + [[package]] 931 + name = "icu_collections" 932 + version = "2.0.0" 933 + source = "registry+https://github.com/rust-lang/crates.io-index" 934 + checksum = "200072f5d0e3614556f94a9930d5dc3e0662a652823904c3a75dc3b0af7fee47" 935 + dependencies = [ 936 + "displaydoc", 937 + "potential_utf", 938 + "yoke", 939 + "zerofrom", 940 + "zerovec", 941 + ] 942 + 943 + [[package]] 944 + name = "icu_locale_core" 945 + version = "2.0.0" 946 + source = "registry+https://github.com/rust-lang/crates.io-index" 947 + checksum = "0cde2700ccaed3872079a65fb1a78f6c0a36c91570f28755dda67bc8f7d9f00a" 948 + dependencies = [ 949 + "displaydoc", 950 + "litemap", 951 + "tinystr", 952 + "writeable", 953 + "zerovec", 954 + ] 955 + 956 + [[package]] 957 + name = "icu_normalizer" 958 + version = "2.0.0" 959 + source = "registry+https://github.com/rust-lang/crates.io-index" 960 + checksum = "436880e8e18df4d7bbc06d58432329d6458cc84531f7ac5f024e93deadb37979" 961 + dependencies = [ 962 + "displaydoc", 963 + "icu_collections", 964 + "icu_normalizer_data", 965 + "icu_properties", 966 + "icu_provider", 967 + "smallvec", 968 + "zerovec", 969 + ] 970 + 971 + [[package]] 972 + name = "icu_normalizer_data" 973 + version = "2.0.0" 974 + source = "registry+https://github.com/rust-lang/crates.io-index" 975 + checksum = "00210d6893afc98edb752b664b8890f0ef174c8adbb8d0be9710fa66fbbf72d3" 976 + 977 + [[package]] 978 + name = "icu_properties" 979 + version = "2.0.1" 980 + source = "registry+https://github.com/rust-lang/crates.io-index" 981 + checksum = "016c619c1eeb94efb86809b015c58f479963de65bdb6253345c1a1276f22e32b" 982 + dependencies = [ 983 + "displaydoc", 984 + "icu_collections", 985 + "icu_locale_core", 986 + "icu_properties_data", 987 + "icu_provider", 988 + "potential_utf", 989 + "zerotrie", 990 + "zerovec", 991 + ] 992 + 993 + [[package]] 994 + name = "icu_properties_data" 995 + version = "2.0.1" 996 + source = "registry+https://github.com/rust-lang/crates.io-index" 997 + checksum = "298459143998310acd25ffe6810ed544932242d3f07083eee1084d83a71bd632" 998 + 999 + [[package]] 1000 + name = "icu_provider" 1001 + version = "2.0.0" 1002 + source = "registry+https://github.com/rust-lang/crates.io-index" 1003 + checksum = "03c80da27b5f4187909049ee2d72f276f0d9f99a42c306bd0131ecfe04d8e5af" 1004 + dependencies = [ 1005 + "displaydoc", 1006 + "icu_locale_core", 1007 + "stable_deref_trait", 1008 + "tinystr", 1009 + "writeable", 1010 + "yoke", 1011 + "zerofrom", 1012 + "zerotrie", 1013 + "zerovec", 1014 + ] 1015 + 1016 + [[package]] 1017 + name = "idna" 1018 + version = "1.0.3" 1019 + source = "registry+https://github.com/rust-lang/crates.io-index" 1020 + checksum = "686f825264d630750a544639377bae737628043f20d38bbc029e8f29ea968a7e" 1021 + dependencies = [ 1022 + "idna_adapter", 1023 + "smallvec", 1024 + "utf8_iter", 1025 + ] 1026 + 1027 + [[package]] 1028 + name = "idna_adapter" 1029 + version = "1.2.1" 1030 + source = "registry+https://github.com/rust-lang/crates.io-index" 1031 + checksum = "3acae9609540aa318d1bc588455225fb2085b9ed0c4f6bd0d9d5bcd86f1a0344" 1032 + dependencies = [ 1033 + "icu_normalizer", 1034 + "icu_properties", 1035 + ] 1036 + 1037 + [[package]] 1038 + name = "indexmap" 1039 + version = "1.9.3" 1040 + source = "registry+https://github.com/rust-lang/crates.io-index" 1041 + checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99" 1042 + dependencies = [ 1043 + "autocfg", 1044 + "hashbrown 0.12.3", 1045 + ] 1046 + 1047 + [[package]] 238 1048 name = "indexmap" 239 1049 version = "2.10.0" 240 1050 source = "registry+https://github.com/rust-lang/crates.io-index" 241 1051 checksum = "fe4cd85333e22411419a0bcae1297d25e58c9443848b11dc6a86fefe8c78a661" 242 1052 dependencies = [ 243 1053 "equivalent", 244 - "hashbrown", 1054 + "hashbrown 0.15.4", 1055 + ] 1056 + 1057 + [[package]] 1058 + name = "io-uring" 1059 + version = "0.7.9" 1060 + source = "registry+https://github.com/rust-lang/crates.io-index" 1061 + checksum = "d93587f37623a1a17d94ef2bc9ada592f5465fe7732084ab7beefabe5c77c0c4" 1062 + dependencies = [ 1063 + "bitflags 2.9.1", 1064 + "cfg-if", 1065 + "libc", 245 1066 ] 246 1067 247 1068 [[package]] ··· 249 1070 version = "1.70.1" 250 1071 source = "registry+https://github.com/rust-lang/crates.io-index" 251 1072 checksum = "7943c866cc5cd64cbc25b2e01621d07fa8eb2a1a23160ee81ce38704e97b8ecf" 1073 + 1074 + [[package]] 1075 + name = "itertools" 1076 + version = "0.13.0" 1077 + source = "registry+https://github.com/rust-lang/crates.io-index" 1078 + checksum = "413ee7dfc52ee1a4949ceeb7dbc8a33f2d6c088194d9f922fb8318faf1f01186" 1079 + dependencies = [ 1080 + "either", 1081 + ] 252 1082 253 1083 [[package]] 254 1084 name = "itoa" ··· 257 1087 checksum = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c" 258 1088 259 1089 [[package]] 1090 + name = "jobserver" 1091 + version = "0.1.34" 1092 + source = "registry+https://github.com/rust-lang/crates.io-index" 1093 + checksum = "9afb3de4395d6b3e67a780b6de64b51c978ecf11cb9a462c66be7d4ca9039d33" 1094 + dependencies = [ 1095 + "getrandom 0.3.3", 1096 + "libc", 1097 + ] 1098 + 1099 + [[package]] 1100 + name = "js-sys" 1101 + version = "0.3.77" 1102 + source = "registry+https://github.com/rust-lang/crates.io-index" 1103 + checksum = "1cfaf33c695fc6e08064efbc1f72ec937429614f25eef83af942d0e227c3a28f" 1104 + dependencies = [ 1105 + "once_cell", 1106 + "wasm-bindgen", 1107 + ] 1108 + 1109 + [[package]] 1110 + name = "lazy_static" 1111 + version = "1.5.0" 1112 + source = "registry+https://github.com/rust-lang/crates.io-index" 1113 + checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" 1114 + dependencies = [ 1115 + "spin", 1116 + ] 1117 + 1118 + [[package]] 260 1119 name = "libc" 261 1120 version = "0.2.174" 262 1121 source = "registry+https://github.com/rust-lang/crates.io-index" 263 1122 checksum = "1171693293099992e19cddea4e8b849964e9846f4acee11b3948bcc337be8776" 264 1123 265 1124 [[package]] 1125 + name = "libloading" 1126 + version = "0.8.8" 1127 + source = "registry+https://github.com/rust-lang/crates.io-index" 1128 + checksum = "07033963ba89ebaf1584d767badaa2e8fcec21aedea6b8c0346d487d49c28667" 1129 + dependencies = [ 1130 + "cfg-if", 1131 + "windows-targets 0.52.6", 1132 + ] 1133 + 1134 + [[package]] 1135 + name = "libm" 1136 + version = "0.2.15" 1137 + source = "registry+https://github.com/rust-lang/crates.io-index" 1138 + checksum = "f9fbbcab51052fe104eb5e5d351cf728d30a5be1fe14d9be8a3b097481fb97de" 1139 + 1140 + [[package]] 266 1141 name = "libredox" 267 1142 version = "0.1.8" 268 1143 source = "registry+https://github.com/rust-lang/crates.io-index" 269 1144 checksum = "360e552c93fa0e8152ab463bc4c4837fce76a225df11dfaeea66c313de5e61f7" 270 1145 dependencies = [ 271 - "bitflags", 1146 + "bitflags 2.9.1", 272 1147 "libc", 273 1148 ] 274 1149 275 1150 [[package]] 1151 + name = "libsqlite3-sys" 1152 + version = "0.30.1" 1153 + source = "registry+https://github.com/rust-lang/crates.io-index" 1154 + checksum = "2e99fb7a497b1e3339bc746195567ed8d3e24945ecd636e3619d20b9de9e9149" 1155 + dependencies = [ 1156 + "cc", 1157 + "pkg-config", 1158 + "vcpkg", 1159 + ] 1160 + 1161 + [[package]] 276 1162 name = "libyml" 277 1163 version = "0.0.5" 278 1164 source = "registry+https://github.com/rust-lang/crates.io-index" ··· 283 1169 ] 284 1170 285 1171 [[package]] 1172 + name = "litemap" 1173 + version = "0.8.0" 1174 + source = "registry+https://github.com/rust-lang/crates.io-index" 1175 + checksum = "241eaef5fd12c88705a01fc1066c48c4b36e0dd4377dcdc7ec3942cea7a69956" 1176 + 1177 + [[package]] 1178 + name = "lock_api" 1179 + version = "0.4.13" 1180 + source = "registry+https://github.com/rust-lang/crates.io-index" 1181 + checksum = "96936507f153605bddfcda068dd804796c84324ed2510809e5b2a624c81da765" 1182 + dependencies = [ 1183 + "autocfg", 1184 + "scopeguard", 1185 + ] 1186 + 1187 + [[package]] 1188 + name = "log" 1189 + version = "0.4.27" 1190 + source = "registry+https://github.com/rust-lang/crates.io-index" 1191 + checksum = "13dc2df351e3202783a1fe0d44375f7295ffb4049267b0f3018346dc122a1d94" 1192 + 1193 + [[package]] 1194 + name = "match_cfg" 1195 + version = "0.1.0" 1196 + source = "registry+https://github.com/rust-lang/crates.io-index" 1197 + checksum = "ffbee8634e0d45d258acb448e7eaab3fce7a0a467395d4d9f228e3c1f01fb2e4" 1198 + 1199 + [[package]] 1200 + name = "md-5" 1201 + version = "0.10.6" 1202 + source = "registry+https://github.com/rust-lang/crates.io-index" 1203 + checksum = "d89e7ee0cfbedfc4da3340218492196241d89eefb6dab27de5df917a6d2e78cf" 1204 + dependencies = [ 1205 + "cfg-if", 1206 + "digest", 1207 + ] 1208 + 1209 + [[package]] 1210 + name = "md5" 1211 + version = "0.7.0" 1212 + source = "registry+https://github.com/rust-lang/crates.io-index" 1213 + checksum = "490cc448043f947bae3cbee9c203358d62dbee0db12107a74be5c30ccfd09771" 1214 + 1215 + [[package]] 286 1216 name = "memchr" 287 1217 version = "2.7.5" 288 1218 source = "registry+https://github.com/rust-lang/crates.io-index" 289 1219 checksum = "32a282da65faaf38286cf3be983213fcf1d2e2a58700e808f83f4ea9a4804bc0" 290 1220 291 1221 [[package]] 1222 + name = "minimal-lexical" 1223 + version = "0.2.1" 1224 + source = "registry+https://github.com/rust-lang/crates.io-index" 1225 + checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" 1226 + 1227 + [[package]] 1228 + name = "miniz_oxide" 1229 + version = "0.8.9" 1230 + source = "registry+https://github.com/rust-lang/crates.io-index" 1231 + checksum = "1fa76a2c86f704bdb222d66965fb3d63269ce38518b83cb0575fca855ebb6316" 1232 + dependencies = [ 1233 + "adler2", 1234 + ] 1235 + 1236 + [[package]] 1237 + name = "mio" 1238 + version = "1.0.4" 1239 + source = "registry+https://github.com/rust-lang/crates.io-index" 1240 + checksum = "78bed444cc8a2160f01cbcf811ef18cac863ad68ae8ca62092e8db51d51c761c" 1241 + dependencies = [ 1242 + "libc", 1243 + "wasi 0.11.1+wasi-snapshot-preview1", 1244 + "windows-sys 0.59.0", 1245 + ] 1246 + 1247 + [[package]] 1248 + name = "names" 1249 + version = "0.14.0" 1250 + source = "registry+https://github.com/rust-lang/crates.io-index" 1251 + checksum = "7bddcd3bf5144b6392de80e04c347cd7fab2508f6df16a85fc496ecd5cec39bc" 1252 + dependencies = [ 1253 + "clap 3.2.25", 1254 + "rand", 1255 + ] 1256 + 1257 + [[package]] 1258 + name = "nom" 1259 + version = "7.1.3" 1260 + source = "registry+https://github.com/rust-lang/crates.io-index" 1261 + checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a" 1262 + dependencies = [ 1263 + "memchr", 1264 + "minimal-lexical", 1265 + ] 1266 + 1267 + [[package]] 1268 + name = "num-bigint-dig" 1269 + version = "0.8.4" 1270 + source = "registry+https://github.com/rust-lang/crates.io-index" 1271 + checksum = "dc84195820f291c7697304f3cbdadd1cb7199c0efc917ff5eafd71225c136151" 1272 + dependencies = [ 1273 + "byteorder", 1274 + "lazy_static", 1275 + "libm", 1276 + "num-integer", 1277 + "num-iter", 1278 + "num-traits", 1279 + "rand", 1280 + "smallvec", 1281 + "zeroize", 1282 + ] 1283 + 1284 + [[package]] 1285 + name = "num-integer" 1286 + version = "0.1.46" 1287 + source = "registry+https://github.com/rust-lang/crates.io-index" 1288 + checksum = "7969661fd2958a5cb096e56c8e1ad0444ac2bbcd0061bd28660485a44879858f" 1289 + dependencies = [ 1290 + "num-traits", 1291 + ] 1292 + 1293 + [[package]] 1294 + name = "num-iter" 1295 + version = "0.1.45" 1296 + source = "registry+https://github.com/rust-lang/crates.io-index" 1297 + checksum = "1429034a0490724d0075ebb2bc9e875d6503c3cf69e235a8941aa757d83ef5bf" 1298 + dependencies = [ 1299 + "autocfg", 1300 + "num-integer", 1301 + "num-traits", 1302 + ] 1303 + 1304 + [[package]] 1305 + name = "num-traits" 1306 + version = "0.2.19" 1307 + source = "registry+https://github.com/rust-lang/crates.io-index" 1308 + checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" 1309 + dependencies = [ 1310 + "autocfg", 1311 + "libm", 1312 + ] 1313 + 1314 + [[package]] 292 1315 name = "num_cpus" 293 1316 version = "1.17.0" 294 1317 source = "registry+https://github.com/rust-lang/crates.io-index" 295 1318 checksum = "91df4bbde75afed763b708b7eee1e8e7651e02d97f6d5dd763e89367e957b23b" 296 1319 dependencies = [ 297 - "hermit-abi", 1320 + "hermit-abi 0.5.2", 298 1321 "libc", 299 1322 ] 300 1323 301 1324 [[package]] 1325 + name = "object" 1326 + version = "0.36.7" 1327 + source = "registry+https://github.com/rust-lang/crates.io-index" 1328 + checksum = "62948e14d923ea95ea2c7c86c71013138b66525b86bdc08d2dcc262bdb497b87" 1329 + dependencies = [ 1330 + "memchr", 1331 + ] 1332 + 1333 + [[package]] 1334 + name = "once_cell" 1335 + version = "1.21.3" 1336 + source = "registry+https://github.com/rust-lang/crates.io-index" 1337 + checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d" 1338 + 1339 + [[package]] 302 1340 name = "once_cell_polyfill" 303 1341 version = "1.70.1" 304 1342 source = "registry+https://github.com/rust-lang/crates.io-index" 305 1343 checksum = "a4895175b425cb1f87721b59f0f286c2092bd4af812243672510e1ac53e2e0ad" 306 1344 307 1345 [[package]] 1346 + name = "openssl-probe" 1347 + version = "0.1.6" 1348 + source = "registry+https://github.com/rust-lang/crates.io-index" 1349 + checksum = "d05e27ee213611ffe7d6348b942e8f942b37114c00cc03cec254295a4a17852e" 1350 + 1351 + [[package]] 308 1352 name = "option-ext" 309 1353 version = "0.2.0" 310 1354 source = "registry+https://github.com/rust-lang/crates.io-index" 311 1355 checksum = "04744f49eae99ab78e0d5c0b603ab218f515ea8cfe5a456d7629ad883a3b6e7d" 312 1356 313 1357 [[package]] 1358 + name = "os_str_bytes" 1359 + version = "6.6.1" 1360 + source = "registry+https://github.com/rust-lang/crates.io-index" 1361 + checksum = "e2355d85b9a3786f481747ced0e0ff2ba35213a1f9bd406ed906554d7af805a1" 1362 + 1363 + [[package]] 314 1364 name = "owo-colors" 315 1365 version = "4.2.2" 316 1366 source = "registry+https://github.com/rust-lang/crates.io-index" 317 1367 checksum = "48dd4f4a2c8405440fd0462561f0e5806bd0f77e86f51c761481bdd4018b545e" 318 1368 319 1369 [[package]] 1370 + name = "parking" 1371 + version = "2.2.1" 1372 + source = "registry+https://github.com/rust-lang/crates.io-index" 1373 + checksum = "f38d5652c16fde515bb1ecef450ab0f6a219d619a7274976324d5e377f7dceba" 1374 + 1375 + [[package]] 1376 + name = "parking_lot" 1377 + version = "0.12.4" 1378 + source = "registry+https://github.com/rust-lang/crates.io-index" 1379 + checksum = "70d58bf43669b5795d1576d0641cfb6fbb2057bf629506267a92807158584a13" 1380 + dependencies = [ 1381 + "lock_api", 1382 + "parking_lot_core", 1383 + ] 1384 + 1385 + [[package]] 1386 + name = "parking_lot_core" 1387 + version = "0.9.11" 1388 + source = "registry+https://github.com/rust-lang/crates.io-index" 1389 + checksum = "bc838d2a56b5b1a6c25f55575dfc605fabb63bb2365f6c2353ef9159aa69e4a5" 1390 + dependencies = [ 1391 + "cfg-if", 1392 + "libc", 1393 + "redox_syscall", 1394 + "smallvec", 1395 + "windows-targets 0.52.6", 1396 + ] 1397 + 1398 + [[package]] 1399 + name = "pem-rfc7468" 1400 + version = "0.7.0" 1401 + source = "registry+https://github.com/rust-lang/crates.io-index" 1402 + checksum = "88b39c9bfcfc231068454382784bb460aae594343fb030d46e9f50a645418412" 1403 + dependencies = [ 1404 + "base64ct", 1405 + ] 1406 + 1407 + [[package]] 1408 + name = "percent-encoding" 1409 + version = "2.3.1" 1410 + source = "registry+https://github.com/rust-lang/crates.io-index" 1411 + checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" 1412 + 1413 + [[package]] 1414 + name = "pin-project-lite" 1415 + version = "0.2.16" 1416 + source = "registry+https://github.com/rust-lang/crates.io-index" 1417 + checksum = "3b3cff922bd51709b605d9ead9aa71031d81447142d828eb4a6eba76fe619f9b" 1418 + 1419 + [[package]] 1420 + name = "pin-utils" 1421 + version = "0.1.0" 1422 + source = "registry+https://github.com/rust-lang/crates.io-index" 1423 + checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" 1424 + 1425 + [[package]] 1426 + name = "pkcs1" 1427 + version = "0.7.5" 1428 + source = "registry+https://github.com/rust-lang/crates.io-index" 1429 + checksum = "c8ffb9f10fa047879315e6625af03c164b16962a5368d724ed16323b68ace47f" 1430 + dependencies = [ 1431 + "der", 1432 + "pkcs8", 1433 + "spki", 1434 + ] 1435 + 1436 + [[package]] 1437 + name = "pkcs8" 1438 + version = "0.10.2" 1439 + source = "registry+https://github.com/rust-lang/crates.io-index" 1440 + checksum = "f950b2377845cebe5cf8b5165cb3cc1a5e0fa5cfa3e1f7f55707d8fd82e0a7b7" 1441 + dependencies = [ 1442 + "der", 1443 + "spki", 1444 + ] 1445 + 1446 + [[package]] 1447 + name = "pkg-config" 1448 + version = "0.3.32" 1449 + source = "registry+https://github.com/rust-lang/crates.io-index" 1450 + checksum = "7edddbd0b52d732b21ad9a5fab5c704c14cd949e5e9a1ec5929a24fded1b904c" 1451 + 1452 + [[package]] 1453 + name = "potential_utf" 1454 + version = "0.1.2" 1455 + source = "registry+https://github.com/rust-lang/crates.io-index" 1456 + checksum = "e5a7c30837279ca13e7c867e9e40053bc68740f988cb07f7ca6df43cc734b585" 1457 + dependencies = [ 1458 + "zerovec", 1459 + ] 1460 + 1461 + [[package]] 1462 + name = "ppv-lite86" 1463 + version = "0.2.21" 1464 + source = "registry+https://github.com/rust-lang/crates.io-index" 1465 + checksum = "85eae3c4ed2f50dcfe72643da4befc30deadb458a9b590d720cde2f2b1e97da9" 1466 + dependencies = [ 1467 + "zerocopy", 1468 + ] 1469 + 1470 + [[package]] 1471 + name = "prettyplease" 1472 + version = "0.2.36" 1473 + source = "registry+https://github.com/rust-lang/crates.io-index" 1474 + checksum = "ff24dfcda44452b9816fff4cd4227e1bb73ff5a2f1bc1105aa92fb8565ce44d2" 1475 + dependencies = [ 1476 + "proc-macro2", 1477 + "syn 2.0.104", 1478 + ] 1479 + 1480 + [[package]] 1481 + name = "proc-macro-error" 1482 + version = "1.0.4" 1483 + source = "registry+https://github.com/rust-lang/crates.io-index" 1484 + checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c" 1485 + dependencies = [ 1486 + "proc-macro-error-attr", 1487 + "proc-macro2", 1488 + "quote", 1489 + "syn 1.0.109", 1490 + "version_check", 1491 + ] 1492 + 1493 + [[package]] 1494 + name = "proc-macro-error-attr" 1495 + version = "1.0.4" 1496 + source = "registry+https://github.com/rust-lang/crates.io-index" 1497 + checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869" 1498 + dependencies = [ 1499 + "proc-macro2", 1500 + "quote", 1501 + "version_check", 1502 + ] 1503 + 1504 + [[package]] 320 1505 name = "proc-macro2" 321 1506 version = "1.0.95" 322 1507 source = "registry+https://github.com/rust-lang/crates.io-index" ··· 335 1520 ] 336 1521 337 1522 [[package]] 1523 + name = "r-efi" 1524 + version = "5.3.0" 1525 + source = "registry+https://github.com/rust-lang/crates.io-index" 1526 + checksum = "69cdb34c158ceb288df11e18b4bd39de994f6657d83847bdffdbd7f346754b0f" 1527 + 1528 + [[package]] 1529 + name = "rand" 1530 + version = "0.8.5" 1531 + source = "registry+https://github.com/rust-lang/crates.io-index" 1532 + checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" 1533 + dependencies = [ 1534 + "libc", 1535 + "rand_chacha", 1536 + "rand_core", 1537 + ] 1538 + 1539 + [[package]] 1540 + name = "rand_chacha" 1541 + version = "0.3.1" 1542 + source = "registry+https://github.com/rust-lang/crates.io-index" 1543 + checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" 1544 + dependencies = [ 1545 + "ppv-lite86", 1546 + "rand_core", 1547 + ] 1548 + 1549 + [[package]] 1550 + name = "rand_core" 1551 + version = "0.6.4" 1552 + source = "registry+https://github.com/rust-lang/crates.io-index" 1553 + checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" 1554 + dependencies = [ 1555 + "getrandom 0.2.16", 1556 + ] 1557 + 1558 + [[package]] 1559 + name = "redox_syscall" 1560 + version = "0.5.17" 1561 + source = "registry+https://github.com/rust-lang/crates.io-index" 1562 + checksum = "5407465600fb0548f1442edf71dd20683c6ed326200ace4b1ef0763521bb3b77" 1563 + dependencies = [ 1564 + "bitflags 2.9.1", 1565 + ] 1566 + 1567 + [[package]] 338 1568 name = "redox_users" 339 1569 version = "0.5.0" 340 1570 source = "registry+https://github.com/rust-lang/crates.io-index" 341 1571 checksum = "dd6f9d3d47bdd2ad6945c5015a226ec6155d0bcdfd8f7cd29f86b71f8de99d2b" 342 1572 dependencies = [ 343 - "getrandom", 1573 + "getrandom 0.2.16", 344 1574 "libredox", 345 - "thiserror", 1575 + "thiserror 2.0.12", 346 1576 ] 347 1577 348 1578 [[package]] ··· 375 1605 checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c" 376 1606 377 1607 [[package]] 1608 + name = "ring" 1609 + version = "0.17.14" 1610 + source = "registry+https://github.com/rust-lang/crates.io-index" 1611 + checksum = "a4689e6c2294d81e88dc6261c768b63bc4fcdb852be6d1352498b114f61383b7" 1612 + dependencies = [ 1613 + "cc", 1614 + "cfg-if", 1615 + "getrandom 0.2.16", 1616 + "libc", 1617 + "untrusted", 1618 + "windows-sys 0.52.0", 1619 + ] 1620 + 1621 + [[package]] 1622 + name = "rsa" 1623 + version = "0.9.8" 1624 + source = "registry+https://github.com/rust-lang/crates.io-index" 1625 + checksum = "78928ac1ed176a5ca1d17e578a1825f3d81ca54cf41053a592584b020cfd691b" 1626 + dependencies = [ 1627 + "const-oid", 1628 + "digest", 1629 + "num-bigint-dig", 1630 + "num-integer", 1631 + "num-traits", 1632 + "pkcs1", 1633 + "pkcs8", 1634 + "rand_core", 1635 + "signature", 1636 + "spki", 1637 + "subtle", 1638 + "zeroize", 1639 + ] 1640 + 1641 + [[package]] 1642 + name = "rumqttc" 1643 + version = "0.25.0" 1644 + source = "registry+https://github.com/rust-lang/crates.io-index" 1645 + checksum = "128f632072dc89ced3359668399026d90eadc06c65c807c298d15ff3d1eacf63" 1646 + dependencies = [ 1647 + "bytes", 1648 + "fixedbitset", 1649 + "flume", 1650 + "futures-util", 1651 + "log", 1652 + "rustls-native-certs", 1653 + "rustls-pemfile", 1654 + "rustls-webpki 0.102.8", 1655 + "thiserror 2.0.12", 1656 + "tokio", 1657 + "tokio-rustls", 1658 + "tokio-stream", 1659 + "tokio-util", 1660 + ] 1661 + 1662 + [[package]] 1663 + name = "rustc-demangle" 1664 + version = "0.1.26" 1665 + source = "registry+https://github.com/rust-lang/crates.io-index" 1666 + checksum = "56f7d92ca342cea22a06f2121d944b4fd82af56988c270852495420f961d4ace" 1667 + 1668 + [[package]] 1669 + name = "rustc-hash" 1670 + version = "2.1.1" 1671 + source = "registry+https://github.com/rust-lang/crates.io-index" 1672 + checksum = "357703d41365b4b27c590e3ed91eabb1b663f07c4c084095e60cbed4362dff0d" 1673 + 1674 + [[package]] 1675 + name = "rustls" 1676 + version = "0.23.29" 1677 + source = "registry+https://github.com/rust-lang/crates.io-index" 1678 + checksum = "2491382039b29b9b11ff08b76ff6c97cf287671dbb74f0be44bda389fffe9bd1" 1679 + dependencies = [ 1680 + "aws-lc-rs", 1681 + "log", 1682 + "once_cell", 1683 + "ring", 1684 + "rustls-pki-types", 1685 + "rustls-webpki 0.103.4", 1686 + "subtle", 1687 + "zeroize", 1688 + ] 1689 + 1690 + [[package]] 1691 + name = "rustls-native-certs" 1692 + version = "0.8.1" 1693 + source = "registry+https://github.com/rust-lang/crates.io-index" 1694 + checksum = "7fcff2dd52b58a8d98a70243663a0d234c4e2b79235637849d15913394a247d3" 1695 + dependencies = [ 1696 + "openssl-probe", 1697 + "rustls-pki-types", 1698 + "schannel", 1699 + "security-framework", 1700 + ] 1701 + 1702 + [[package]] 1703 + name = "rustls-pemfile" 1704 + version = "2.2.0" 1705 + source = "registry+https://github.com/rust-lang/crates.io-index" 1706 + checksum = "dce314e5fee3f39953d46bb63bb8a46d40c2f8fb7cc5a3b6cab2bde9721d6e50" 1707 + dependencies = [ 1708 + "rustls-pki-types", 1709 + ] 1710 + 1711 + [[package]] 1712 + name = "rustls-pki-types" 1713 + version = "1.12.0" 1714 + source = "registry+https://github.com/rust-lang/crates.io-index" 1715 + checksum = "229a4a4c221013e7e1f1a043678c5cc39fe5171437c88fb47151a21e6f5b5c79" 1716 + dependencies = [ 1717 + "zeroize", 1718 + ] 1719 + 1720 + [[package]] 1721 + name = "rustls-webpki" 1722 + version = "0.102.8" 1723 + source = "registry+https://github.com/rust-lang/crates.io-index" 1724 + checksum = "64ca1bc8749bd4cf37b5ce386cc146580777b4e8572c7b97baf22c83f444bee9" 1725 + dependencies = [ 1726 + "ring", 1727 + "rustls-pki-types", 1728 + "untrusted", 1729 + ] 1730 + 1731 + [[package]] 1732 + name = "rustls-webpki" 1733 + version = "0.103.4" 1734 + source = "registry+https://github.com/rust-lang/crates.io-index" 1735 + checksum = "0a17884ae0c1b773f1ccd2bd4a8c72f16da897310a98b0e84bf349ad5ead92fc" 1736 + dependencies = [ 1737 + "aws-lc-rs", 1738 + "ring", 1739 + "rustls-pki-types", 1740 + "untrusted", 1741 + ] 1742 + 1743 + [[package]] 1744 + name = "rustversion" 1745 + version = "1.0.21" 1746 + source = "registry+https://github.com/rust-lang/crates.io-index" 1747 + checksum = "8a0d197bd2c9dc6e53b84da9556a69ba4cdfab8619eb41a8bd1cc2027a0f6b1d" 1748 + 1749 + [[package]] 378 1750 name = "ryu" 379 1751 version = "1.0.20" 380 1752 source = "registry+https://github.com/rust-lang/crates.io-index" 381 1753 checksum = "28d3b2b1366ec20994f1fd18c3c594f05c5dd4bc44d8bb0c1c632c8d6829481f" 382 1754 383 1755 [[package]] 1756 + name = "same-file" 1757 + version = "1.0.6" 1758 + source = "registry+https://github.com/rust-lang/crates.io-index" 1759 + checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502" 1760 + dependencies = [ 1761 + "winapi-util", 1762 + ] 1763 + 1764 + [[package]] 1765 + name = "schannel" 1766 + version = "0.1.28" 1767 + source = "registry+https://github.com/rust-lang/crates.io-index" 1768 + checksum = "891d81b926048e76efe18581bf793546b4c0eaf8448d72be8de2bbee5fd166e1" 1769 + dependencies = [ 1770 + "windows-sys 0.61.0", 1771 + ] 1772 + 1773 + [[package]] 1774 + name = "scopeguard" 1775 + version = "1.2.0" 1776 + source = "registry+https://github.com/rust-lang/crates.io-index" 1777 + checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" 1778 + 1779 + [[package]] 1780 + name = "security-framework" 1781 + version = "3.4.0" 1782 + source = "registry+https://github.com/rust-lang/crates.io-index" 1783 + checksum = "60b369d18893388b345804dc0007963c99b7d665ae71d275812d828c6f089640" 1784 + dependencies = [ 1785 + "bitflags 2.9.1", 1786 + "core-foundation", 1787 + "core-foundation-sys", 1788 + "libc", 1789 + "security-framework-sys", 1790 + ] 1791 + 1792 + [[package]] 1793 + name = "security-framework-sys" 1794 + version = "2.15.0" 1795 + source = "registry+https://github.com/rust-lang/crates.io-index" 1796 + checksum = "cc1f0cbffaac4852523ce30d8bd3c5cdc873501d96ff467ca09b6767bb8cd5c0" 1797 + dependencies = [ 1798 + "core-foundation-sys", 1799 + "libc", 1800 + ] 1801 + 1802 + [[package]] 384 1803 name = "serde" 385 1804 version = "1.0.219" 386 1805 source = "registry+https://github.com/rust-lang/crates.io-index" ··· 397 1816 dependencies = [ 398 1817 "proc-macro2", 399 1818 "quote", 400 - "syn", 1819 + "syn 2.0.104", 401 1820 ] 402 1821 403 1822 [[package]] ··· 418 1837 source = "registry+https://github.com/rust-lang/crates.io-index" 419 1838 checksum = "40734c41988f7306bb04f0ecf60ec0f3f1caa34290e4e8ea471dcd3346483b83" 420 1839 dependencies = [ 1840 + "serde", 1841 + ] 1842 + 1843 + [[package]] 1844 + name = "serde_urlencoded" 1845 + version = "0.7.1" 1846 + source = "registry+https://github.com/rust-lang/crates.io-index" 1847 + checksum = "d3491c14715ca2294c4d6a88f15e84739788c1d030eed8c110436aafdaa2f3fd" 1848 + dependencies = [ 1849 + "form_urlencoded", 1850 + "itoa", 1851 + "ryu", 421 1852 "serde", 422 1853 ] 423 1854 ··· 427 1858 source = "registry+https://github.com/rust-lang/crates.io-index" 428 1859 checksum = "59e2dd588bf1597a252c3b920e0143eb99b0f76e4e082f4c92ce34fbc9e71ddd" 429 1860 dependencies = [ 430 - "indexmap", 1861 + "indexmap 2.10.0", 431 1862 "itoa", 432 1863 "libyml", 433 1864 "memchr", ··· 437 1868 ] 438 1869 439 1870 [[package]] 1871 + name = "sha1" 1872 + version = "0.10.6" 1873 + source = "registry+https://github.com/rust-lang/crates.io-index" 1874 + checksum = "e3bf829a2d51ab4a5ddf1352d8470c140cadc8301b2ae1789db023f01cedd6ba" 1875 + dependencies = [ 1876 + "cfg-if", 1877 + "cpufeatures", 1878 + "digest", 1879 + ] 1880 + 1881 + [[package]] 1882 + name = "sha2" 1883 + version = "0.10.9" 1884 + source = "registry+https://github.com/rust-lang/crates.io-index" 1885 + checksum = "a7507d819769d01a365ab707794a4084392c824f54a7a6a7862f8c3d0892b283" 1886 + dependencies = [ 1887 + "cfg-if", 1888 + "cpufeatures", 1889 + "digest", 1890 + ] 1891 + 1892 + [[package]] 1893 + name = "shlex" 1894 + version = "1.3.0" 1895 + source = "registry+https://github.com/rust-lang/crates.io-index" 1896 + checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" 1897 + 1898 + [[package]] 1899 + name = "signal-hook-registry" 1900 + version = "1.4.5" 1901 + source = "registry+https://github.com/rust-lang/crates.io-index" 1902 + checksum = "9203b8055f63a2a00e2f593bb0510367fe707d7ff1e5c872de2f537b339e5410" 1903 + dependencies = [ 1904 + "libc", 1905 + ] 1906 + 1907 + [[package]] 1908 + name = "signature" 1909 + version = "2.2.0" 1910 + source = "registry+https://github.com/rust-lang/crates.io-index" 1911 + checksum = "77549399552de45a898a580c1b41d445bf730df867cc44e6c0233bbc4b8329de" 1912 + dependencies = [ 1913 + "digest", 1914 + "rand_core", 1915 + ] 1916 + 1917 + [[package]] 1918 + name = "slab" 1919 + version = "0.4.10" 1920 + source = "registry+https://github.com/rust-lang/crates.io-index" 1921 + checksum = "04dc19736151f35336d325007ac991178d504a119863a2fcb3758cdb5e52c50d" 1922 + 1923 + [[package]] 1924 + name = "smallvec" 1925 + version = "1.15.1" 1926 + source = "registry+https://github.com/rust-lang/crates.io-index" 1927 + checksum = "67b1b7a3b5fe4f1376887184045fcf45c69e92af734b7aaddc05fb777b6fbd03" 1928 + dependencies = [ 1929 + "serde", 1930 + ] 1931 + 1932 + [[package]] 1933 + name = "socket2" 1934 + version = "0.6.0" 1935 + source = "registry+https://github.com/rust-lang/crates.io-index" 1936 + checksum = "233504af464074f9d066d7b5416c5f9b894a5862a6506e306f7b816cdd6f1807" 1937 + dependencies = [ 1938 + "libc", 1939 + "windows-sys 0.59.0", 1940 + ] 1941 + 1942 + [[package]] 1943 + name = "spin" 1944 + version = "0.9.8" 1945 + source = "registry+https://github.com/rust-lang/crates.io-index" 1946 + checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67" 1947 + dependencies = [ 1948 + "lock_api", 1949 + ] 1950 + 1951 + [[package]] 1952 + name = "spki" 1953 + version = "0.7.3" 1954 + source = "registry+https://github.com/rust-lang/crates.io-index" 1955 + checksum = "d91ed6c858b01f942cd56b37a94b3e0a1798290327d1236e4d9cf4eaca44d29d" 1956 + dependencies = [ 1957 + "base64ct", 1958 + "der", 1959 + ] 1960 + 1961 + [[package]] 1962 + name = "sqlx" 1963 + version = "0.8.6" 1964 + source = "registry+https://github.com/rust-lang/crates.io-index" 1965 + checksum = "1fefb893899429669dcdd979aff487bd78f4064e5e7907e4269081e0ef7d97dc" 1966 + dependencies = [ 1967 + "sqlx-core", 1968 + "sqlx-macros", 1969 + "sqlx-mysql", 1970 + "sqlx-postgres", 1971 + "sqlx-sqlite", 1972 + ] 1973 + 1974 + [[package]] 1975 + name = "sqlx-core" 1976 + version = "0.8.6" 1977 + source = "registry+https://github.com/rust-lang/crates.io-index" 1978 + checksum = "ee6798b1838b6a0f69c007c133b8df5866302197e404e8b6ee8ed3e3a5e68dc6" 1979 + dependencies = [ 1980 + "base64", 1981 + "bytes", 1982 + "chrono", 1983 + "crc", 1984 + "crossbeam-queue", 1985 + "either", 1986 + "event-listener", 1987 + "futures-core", 1988 + "futures-intrusive", 1989 + "futures-io", 1990 + "futures-util", 1991 + "hashbrown 0.15.4", 1992 + "hashlink", 1993 + "indexmap 2.10.0", 1994 + "log", 1995 + "memchr", 1996 + "once_cell", 1997 + "percent-encoding", 1998 + "rustls", 1999 + "serde", 2000 + "serde_json", 2001 + "sha2", 2002 + "smallvec", 2003 + "thiserror 2.0.12", 2004 + "tokio", 2005 + "tokio-stream", 2006 + "tracing", 2007 + "url", 2008 + "webpki-roots 0.26.11", 2009 + ] 2010 + 2011 + [[package]] 2012 + name = "sqlx-macros" 2013 + version = "0.8.6" 2014 + source = "registry+https://github.com/rust-lang/crates.io-index" 2015 + checksum = "a2d452988ccaacfbf5e0bdbc348fb91d7c8af5bee192173ac3636b5fb6e6715d" 2016 + dependencies = [ 2017 + "proc-macro2", 2018 + "quote", 2019 + "sqlx-core", 2020 + "sqlx-macros-core", 2021 + "syn 2.0.104", 2022 + ] 2023 + 2024 + [[package]] 2025 + name = "sqlx-macros-core" 2026 + version = "0.8.6" 2027 + source = "registry+https://github.com/rust-lang/crates.io-index" 2028 + checksum = "19a9c1841124ac5a61741f96e1d9e2ec77424bf323962dd894bdb93f37d5219b" 2029 + dependencies = [ 2030 + "dotenvy", 2031 + "either", 2032 + "heck 0.5.0", 2033 + "hex", 2034 + "once_cell", 2035 + "proc-macro2", 2036 + "quote", 2037 + "serde", 2038 + "serde_json", 2039 + "sha2", 2040 + "sqlx-core", 2041 + "sqlx-mysql", 2042 + "sqlx-postgres", 2043 + "sqlx-sqlite", 2044 + "syn 2.0.104", 2045 + "tokio", 2046 + "url", 2047 + ] 2048 + 2049 + [[package]] 2050 + name = "sqlx-mysql" 2051 + version = "0.8.6" 2052 + source = "registry+https://github.com/rust-lang/crates.io-index" 2053 + checksum = "aa003f0038df784eb8fecbbac13affe3da23b45194bd57dba231c8f48199c526" 2054 + dependencies = [ 2055 + "atoi", 2056 + "base64", 2057 + "bitflags 2.9.1", 2058 + "byteorder", 2059 + "bytes", 2060 + "chrono", 2061 + "crc", 2062 + "digest", 2063 + "dotenvy", 2064 + "either", 2065 + "futures-channel", 2066 + "futures-core", 2067 + "futures-io", 2068 + "futures-util", 2069 + "generic-array", 2070 + "hex", 2071 + "hkdf", 2072 + "hmac", 2073 + "itoa", 2074 + "log", 2075 + "md-5", 2076 + "memchr", 2077 + "once_cell", 2078 + "percent-encoding", 2079 + "rand", 2080 + "rsa", 2081 + "serde", 2082 + "sha1", 2083 + "sha2", 2084 + "smallvec", 2085 + "sqlx-core", 2086 + "stringprep", 2087 + "thiserror 2.0.12", 2088 + "tracing", 2089 + "whoami", 2090 + ] 2091 + 2092 + [[package]] 2093 + name = "sqlx-postgres" 2094 + version = "0.8.6" 2095 + source = "registry+https://github.com/rust-lang/crates.io-index" 2096 + checksum = "db58fcd5a53cf07c184b154801ff91347e4c30d17a3562a635ff028ad5deda46" 2097 + dependencies = [ 2098 + "atoi", 2099 + "base64", 2100 + "bitflags 2.9.1", 2101 + "byteorder", 2102 + "chrono", 2103 + "crc", 2104 + "dotenvy", 2105 + "etcetera", 2106 + "futures-channel", 2107 + "futures-core", 2108 + "futures-util", 2109 + "hex", 2110 + "hkdf", 2111 + "hmac", 2112 + "home", 2113 + "itoa", 2114 + "log", 2115 + "md-5", 2116 + "memchr", 2117 + "once_cell", 2118 + "rand", 2119 + "serde", 2120 + "serde_json", 2121 + "sha2", 2122 + "smallvec", 2123 + "sqlx-core", 2124 + "stringprep", 2125 + "thiserror 2.0.12", 2126 + "tracing", 2127 + "whoami", 2128 + ] 2129 + 2130 + [[package]] 2131 + name = "sqlx-sqlite" 2132 + version = "0.8.6" 2133 + source = "registry+https://github.com/rust-lang/crates.io-index" 2134 + checksum = "c2d12fe70b2c1b4401038055f90f151b78208de1f9f89a7dbfd41587a10c3eea" 2135 + dependencies = [ 2136 + "atoi", 2137 + "chrono", 2138 + "flume", 2139 + "futures-channel", 2140 + "futures-core", 2141 + "futures-executor", 2142 + "futures-intrusive", 2143 + "futures-util", 2144 + "libsqlite3-sys", 2145 + "log", 2146 + "percent-encoding", 2147 + "serde", 2148 + "serde_urlencoded", 2149 + "sqlx-core", 2150 + "thiserror 2.0.12", 2151 + "tracing", 2152 + "url", 2153 + ] 2154 + 2155 + [[package]] 2156 + name = "stable_deref_trait" 2157 + version = "1.2.0" 2158 + source = "registry+https://github.com/rust-lang/crates.io-index" 2159 + checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" 2160 + 2161 + [[package]] 2162 + name = "stringprep" 2163 + version = "0.1.5" 2164 + source = "registry+https://github.com/rust-lang/crates.io-index" 2165 + checksum = "7b4df3d392d81bd458a8a621b8bffbd2302a12ffe288a9d931670948749463b1" 2166 + dependencies = [ 2167 + "unicode-bidi", 2168 + "unicode-normalization", 2169 + "unicode-properties", 2170 + ] 2171 + 2172 + [[package]] 2173 + name = "strsim" 2174 + version = "0.10.0" 2175 + source = "registry+https://github.com/rust-lang/crates.io-index" 2176 + checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" 2177 + 2178 + [[package]] 440 2179 name = "strsim" 441 2180 version = "0.11.1" 442 2181 source = "registry+https://github.com/rust-lang/crates.io-index" 443 2182 checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" 444 2183 445 2184 [[package]] 2185 + name = "subtle" 2186 + version = "2.6.1" 2187 + source = "registry+https://github.com/rust-lang/crates.io-index" 2188 + checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" 2189 + 2190 + [[package]] 2191 + name = "syn" 2192 + version = "1.0.109" 2193 + source = "registry+https://github.com/rust-lang/crates.io-index" 2194 + checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" 2195 + dependencies = [ 2196 + "proc-macro2", 2197 + "quote", 2198 + "unicode-ident", 2199 + ] 2200 + 2201 + [[package]] 446 2202 name = "syn" 447 2203 version = "2.0.104" 448 2204 source = "registry+https://github.com/rust-lang/crates.io-index" ··· 454 2210 ] 455 2211 456 2212 [[package]] 2213 + name = "synstructure" 2214 + version = "0.13.2" 2215 + source = "registry+https://github.com/rust-lang/crates.io-index" 2216 + checksum = "728a70f3dbaf5bab7f0c4b1ac8d7ae5ea60a4b5549c8a5914361c99147a709d2" 2217 + dependencies = [ 2218 + "proc-macro2", 2219 + "quote", 2220 + "syn 2.0.104", 2221 + ] 2222 + 2223 + [[package]] 2224 + name = "sysctl" 2225 + version = "0.4.6" 2226 + source = "registry+https://github.com/rust-lang/crates.io-index" 2227 + checksum = "225e483f02d0ad107168dc57381a8a40c3aeea6abe47f37506931f861643cfa8" 2228 + dependencies = [ 2229 + "bitflags 1.3.2", 2230 + "byteorder", 2231 + "libc", 2232 + "thiserror 1.0.69", 2233 + "walkdir", 2234 + ] 2235 + 2236 + [[package]] 2237 + name = "termcolor" 2238 + version = "1.4.1" 2239 + source = "registry+https://github.com/rust-lang/crates.io-index" 2240 + checksum = "06794f8f6c5c898b3275aebefa6b8a1cb24cd2c6c79397ab15774837a0bc5755" 2241 + dependencies = [ 2242 + "winapi-util", 2243 + ] 2244 + 2245 + [[package]] 2246 + name = "textwrap" 2247 + version = "0.16.2" 2248 + source = "registry+https://github.com/rust-lang/crates.io-index" 2249 + checksum = "c13547615a44dc9c452a8a534638acdf07120d4b6847c8178705da06306a3057" 2250 + 2251 + [[package]] 2252 + name = "thiserror" 2253 + version = "1.0.69" 2254 + source = "registry+https://github.com/rust-lang/crates.io-index" 2255 + checksum = "b6aaf5339b578ea85b50e080feb250a3e8ae8cfcdff9a461c9ec2904bc923f52" 2256 + dependencies = [ 2257 + "thiserror-impl 1.0.69", 2258 + ] 2259 + 2260 + [[package]] 457 2261 name = "thiserror" 458 2262 version = "2.0.12" 459 2263 source = "registry+https://github.com/rust-lang/crates.io-index" 460 2264 checksum = "567b8a2dae586314f7be2a752ec7474332959c6460e02bde30d702a66d488708" 461 2265 dependencies = [ 462 - "thiserror-impl", 2266 + "thiserror-impl 2.0.12", 2267 + ] 2268 + 2269 + [[package]] 2270 + name = "thiserror-impl" 2271 + version = "1.0.69" 2272 + source = "registry+https://github.com/rust-lang/crates.io-index" 2273 + checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" 2274 + dependencies = [ 2275 + "proc-macro2", 2276 + "quote", 2277 + "syn 2.0.104", 463 2278 ] 464 2279 465 2280 [[package]] ··· 470 2285 dependencies = [ 471 2286 "proc-macro2", 472 2287 "quote", 473 - "syn", 2288 + "syn 2.0.104", 2289 + ] 2290 + 2291 + [[package]] 2292 + name = "tinystr" 2293 + version = "0.8.1" 2294 + source = "registry+https://github.com/rust-lang/crates.io-index" 2295 + checksum = "5d4f6d1145dcb577acf783d4e601bc1d76a13337bb54e6233add580b07344c8b" 2296 + dependencies = [ 2297 + "displaydoc", 2298 + "zerovec", 2299 + ] 2300 + 2301 + [[package]] 2302 + name = "tinyvec" 2303 + version = "1.9.0" 2304 + source = "registry+https://github.com/rust-lang/crates.io-index" 2305 + checksum = "09b3661f17e86524eccd4371ab0429194e0d7c008abb45f7a7495b1719463c71" 2306 + dependencies = [ 2307 + "tinyvec_macros", 2308 + ] 2309 + 2310 + [[package]] 2311 + name = "tinyvec_macros" 2312 + version = "0.1.1" 2313 + source = "registry+https://github.com/rust-lang/crates.io-index" 2314 + checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" 2315 + 2316 + [[package]] 2317 + name = "tokio" 2318 + version = "1.47.1" 2319 + source = "registry+https://github.com/rust-lang/crates.io-index" 2320 + checksum = "89e49afdadebb872d3145a5638b59eb0691ea23e46ca484037cfab3b76b95038" 2321 + dependencies = [ 2322 + "backtrace", 2323 + "bytes", 2324 + "io-uring", 2325 + "libc", 2326 + "mio", 2327 + "parking_lot", 2328 + "pin-project-lite", 2329 + "signal-hook-registry", 2330 + "slab", 2331 + "socket2", 2332 + "tokio-macros", 2333 + "windows-sys 0.59.0", 2334 + ] 2335 + 2336 + [[package]] 2337 + name = "tokio-macros" 2338 + version = "2.5.0" 2339 + source = "registry+https://github.com/rust-lang/crates.io-index" 2340 + checksum = "6e06d43f1345a3bcd39f6a56dbb7dcab2ba47e68e8ac134855e7e2bdbaf8cab8" 2341 + dependencies = [ 2342 + "proc-macro2", 2343 + "quote", 2344 + "syn 2.0.104", 2345 + ] 2346 + 2347 + [[package]] 2348 + name = "tokio-rustls" 2349 + version = "0.26.2" 2350 + source = "registry+https://github.com/rust-lang/crates.io-index" 2351 + checksum = "8e727b36a1a0e8b74c376ac2211e40c2c8af09fb4013c60d910495810f008e9b" 2352 + dependencies = [ 2353 + "rustls", 2354 + "tokio", 2355 + ] 2356 + 2357 + [[package]] 2358 + name = "tokio-stream" 2359 + version = "0.1.17" 2360 + source = "registry+https://github.com/rust-lang/crates.io-index" 2361 + checksum = "eca58d7bba4a75707817a2c44174253f9236b2d5fbd055602e9d5c07c139a047" 2362 + dependencies = [ 2363 + "futures-core", 2364 + "pin-project-lite", 2365 + "tokio", 2366 + ] 2367 + 2368 + [[package]] 2369 + name = "tokio-util" 2370 + version = "0.7.16" 2371 + source = "registry+https://github.com/rust-lang/crates.io-index" 2372 + checksum = "14307c986784f72ef81c89db7d9e28d6ac26d16213b109ea501696195e6e3ce5" 2373 + dependencies = [ 2374 + "bytes", 2375 + "futures-core", 2376 + "futures-sink", 2377 + "pin-project-lite", 2378 + "tokio", 474 2379 ] 475 2380 476 2381 [[package]] ··· 479 2384 source = "registry+https://github.com/rust-lang/crates.io-index" 480 2385 checksum = "41ae868b5a0f67631c14589f7e250c1ea2c574ee5ba21c6c8dd4b1485705a5a1" 481 2386 dependencies = [ 482 - "indexmap", 2387 + "indexmap 2.10.0", 483 2388 "serde", 484 2389 "serde_spanned", 485 2390 "toml_datetime", ··· 513 2418 checksum = "fcc842091f2def52017664b53082ecbbeb5c7731092bad69d2c63050401dfd64" 514 2419 515 2420 [[package]] 2421 + name = "tracing" 2422 + version = "0.1.41" 2423 + source = "registry+https://github.com/rust-lang/crates.io-index" 2424 + checksum = "784e0ac535deb450455cbfa28a6f0df145ea1bb7ae51b821cf5e7927fdcfbdd0" 2425 + dependencies = [ 2426 + "log", 2427 + "pin-project-lite", 2428 + "tracing-attributes", 2429 + "tracing-core", 2430 + ] 2431 + 2432 + [[package]] 2433 + name = "tracing-attributes" 2434 + version = "0.1.30" 2435 + source = "registry+https://github.com/rust-lang/crates.io-index" 2436 + checksum = "81383ab64e72a7a8b8e13130c49e3dab29def6d0c7d76a03087b3cf71c5c6903" 2437 + dependencies = [ 2438 + "proc-macro2", 2439 + "quote", 2440 + "syn 2.0.104", 2441 + ] 2442 + 2443 + [[package]] 2444 + name = "tracing-core" 2445 + version = "0.1.34" 2446 + source = "registry+https://github.com/rust-lang/crates.io-index" 2447 + checksum = "b9d12581f227e93f094d3af2ae690a574abb8a2b9b7a96e7cfe9647b2b617678" 2448 + dependencies = [ 2449 + "once_cell", 2450 + ] 2451 + 2452 + [[package]] 2453 + name = "typenum" 2454 + version = "1.18.0" 2455 + source = "registry+https://github.com/rust-lang/crates.io-index" 2456 + checksum = "1dccffe3ce07af9386bfd29e80c0ab1a8205a2fc34e4bcd40364df902cfa8f3f" 2457 + 2458 + [[package]] 2459 + name = "unicode-bidi" 2460 + version = "0.3.18" 2461 + source = "registry+https://github.com/rust-lang/crates.io-index" 2462 + checksum = "5c1cb5db39152898a79168971543b1cb5020dff7fe43c8dc468b0885f5e29df5" 2463 + 2464 + [[package]] 516 2465 name = "unicode-ident" 517 2466 version = "1.0.18" 518 2467 source = "registry+https://github.com/rust-lang/crates.io-index" 519 2468 checksum = "5a5f39404a5da50712a4c1eecf25e90dd62b613502b7e925fd4e4d19b5c96512" 520 2469 521 2470 [[package]] 2471 + name = "unicode-normalization" 2472 + version = "0.1.24" 2473 + source = "registry+https://github.com/rust-lang/crates.io-index" 2474 + checksum = "5033c97c4262335cded6d6fc3e5c18ab755e1a3dc96376350f3d8e9f009ad956" 2475 + dependencies = [ 2476 + "tinyvec", 2477 + ] 2478 + 2479 + [[package]] 2480 + name = "unicode-properties" 2481 + version = "0.1.3" 2482 + source = "registry+https://github.com/rust-lang/crates.io-index" 2483 + checksum = "e70f2a8b45122e719eb623c01822704c4e0907e7e426a05927e1a1cfff5b75d0" 2484 + 2485 + [[package]] 2486 + name = "untrusted" 2487 + version = "0.9.0" 2488 + source = "registry+https://github.com/rust-lang/crates.io-index" 2489 + checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" 2490 + 2491 + [[package]] 2492 + name = "url" 2493 + version = "2.5.4" 2494 + source = "registry+https://github.com/rust-lang/crates.io-index" 2495 + checksum = "32f8b686cadd1473f4bd0117a5d28d36b1ade384ea9b5069a1c40aefed7fda60" 2496 + dependencies = [ 2497 + "form_urlencoded", 2498 + "idna", 2499 + "percent-encoding", 2500 + ] 2501 + 2502 + [[package]] 2503 + name = "utf8_iter" 2504 + version = "1.0.4" 2505 + source = "registry+https://github.com/rust-lang/crates.io-index" 2506 + checksum = "b6c140620e7ffbb22c2dee59cafe6084a59b5ffc27a8859a5f0d494b5d52b6be" 2507 + 2508 + [[package]] 522 2509 name = "utf8parse" 523 2510 version = "0.2.2" 524 2511 source = "registry+https://github.com/rust-lang/crates.io-index" 525 2512 checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" 526 2513 527 2514 [[package]] 2515 + name = "vcpkg" 2516 + version = "0.2.15" 2517 + source = "registry+https://github.com/rust-lang/crates.io-index" 2518 + checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" 2519 + 2520 + [[package]] 528 2521 name = "version_check" 529 2522 version = "0.9.5" 530 2523 source = "registry+https://github.com/rust-lang/crates.io-index" 531 2524 checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" 532 2525 533 2526 [[package]] 2527 + name = "walkdir" 2528 + version = "2.5.0" 2529 + source = "registry+https://github.com/rust-lang/crates.io-index" 2530 + checksum = "29790946404f91d9c5d06f9874efddea1dc06c5efe94541a7d6863108e3a5e4b" 2531 + dependencies = [ 2532 + "same-file", 2533 + "winapi-util", 2534 + ] 2535 + 2536 + [[package]] 534 2537 name = "wasi" 535 2538 version = "0.11.1+wasi-snapshot-preview1" 536 2539 source = "registry+https://github.com/rust-lang/crates.io-index" 537 2540 checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b" 538 2541 539 2542 [[package]] 2543 + name = "wasi" 2544 + version = "0.14.5+wasi-0.2.4" 2545 + source = "registry+https://github.com/rust-lang/crates.io-index" 2546 + checksum = "a4494f6290a82f5fe584817a676a34b9d6763e8d9d18204009fb31dceca98fd4" 2547 + dependencies = [ 2548 + "wasip2", 2549 + ] 2550 + 2551 + [[package]] 2552 + name = "wasip2" 2553 + version = "1.0.0+wasi-0.2.4" 2554 + source = "registry+https://github.com/rust-lang/crates.io-index" 2555 + checksum = "03fa2761397e5bd52002cd7e73110c71af2109aca4e521a9f40473fe685b0a24" 2556 + dependencies = [ 2557 + "wit-bindgen", 2558 + ] 2559 + 2560 + [[package]] 2561 + name = "wasite" 2562 + version = "0.1.0" 2563 + source = "registry+https://github.com/rust-lang/crates.io-index" 2564 + checksum = "b8dad83b4f25e74f184f64c43b150b91efe7647395b42289f38e50566d82855b" 2565 + 2566 + [[package]] 2567 + name = "wasm-bindgen" 2568 + version = "0.2.100" 2569 + source = "registry+https://github.com/rust-lang/crates.io-index" 2570 + checksum = "1edc8929d7499fc4e8f0be2262a241556cfc54a0bea223790e71446f2aab1ef5" 2571 + dependencies = [ 2572 + "cfg-if", 2573 + "once_cell", 2574 + "rustversion", 2575 + "wasm-bindgen-macro", 2576 + ] 2577 + 2578 + [[package]] 2579 + name = "wasm-bindgen-backend" 2580 + version = "0.2.100" 2581 + source = "registry+https://github.com/rust-lang/crates.io-index" 2582 + checksum = "2f0a0651a5c2bc21487bde11ee802ccaf4c51935d0d3d42a6101f98161700bc6" 2583 + dependencies = [ 2584 + "bumpalo", 2585 + "log", 2586 + "proc-macro2", 2587 + "quote", 2588 + "syn 2.0.104", 2589 + "wasm-bindgen-shared", 2590 + ] 2591 + 2592 + [[package]] 2593 + name = "wasm-bindgen-macro" 2594 + version = "0.2.100" 2595 + source = "registry+https://github.com/rust-lang/crates.io-index" 2596 + checksum = "7fe63fc6d09ed3792bd0897b314f53de8e16568c2b3f7982f468c0bf9bd0b407" 2597 + dependencies = [ 2598 + "quote", 2599 + "wasm-bindgen-macro-support", 2600 + ] 2601 + 2602 + [[package]] 2603 + name = "wasm-bindgen-macro-support" 2604 + version = "0.2.100" 2605 + source = "registry+https://github.com/rust-lang/crates.io-index" 2606 + checksum = "8ae87ea40c9f689fc23f209965b6fb8a99ad69aeeb0231408be24920604395de" 2607 + dependencies = [ 2608 + "proc-macro2", 2609 + "quote", 2610 + "syn 2.0.104", 2611 + "wasm-bindgen-backend", 2612 + "wasm-bindgen-shared", 2613 + ] 2614 + 2615 + [[package]] 2616 + name = "wasm-bindgen-shared" 2617 + version = "0.2.100" 2618 + source = "registry+https://github.com/rust-lang/crates.io-index" 2619 + checksum = "1a05d73b933a847d6cccdda8f838a22ff101ad9bf93e33684f39c1f5f0eece3d" 2620 + dependencies = [ 2621 + "unicode-ident", 2622 + ] 2623 + 2624 + [[package]] 2625 + name = "webpki-roots" 2626 + version = "0.26.11" 2627 + source = "registry+https://github.com/rust-lang/crates.io-index" 2628 + checksum = "521bc38abb08001b01866da9f51eb7c5d647a19260e00054a8c7fd5f9e57f7a9" 2629 + dependencies = [ 2630 + "webpki-roots 1.0.2", 2631 + ] 2632 + 2633 + [[package]] 2634 + name = "webpki-roots" 2635 + version = "1.0.2" 2636 + source = "registry+https://github.com/rust-lang/crates.io-index" 2637 + checksum = "7e8983c3ab33d6fb807cfcdad2491c4ea8cbc8ed839181c7dfd9c67c83e261b2" 2638 + dependencies = [ 2639 + "rustls-pki-types", 2640 + ] 2641 + 2642 + [[package]] 2643 + name = "whoami" 2644 + version = "1.6.0" 2645 + source = "registry+https://github.com/rust-lang/crates.io-index" 2646 + checksum = "6994d13118ab492c3c80c1f81928718159254c53c472bf9ce36f8dae4add02a7" 2647 + dependencies = [ 2648 + "redox_syscall", 2649 + "wasite", 2650 + ] 2651 + 2652 + [[package]] 2653 + name = "winapi" 2654 + version = "0.3.9" 2655 + source = "registry+https://github.com/rust-lang/crates.io-index" 2656 + checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" 2657 + dependencies = [ 2658 + "winapi-i686-pc-windows-gnu", 2659 + "winapi-x86_64-pc-windows-gnu", 2660 + ] 2661 + 2662 + [[package]] 2663 + name = "winapi-i686-pc-windows-gnu" 2664 + version = "0.4.0" 2665 + source = "registry+https://github.com/rust-lang/crates.io-index" 2666 + checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" 2667 + 2668 + [[package]] 2669 + name = "winapi-util" 2670 + version = "0.1.9" 2671 + source = "registry+https://github.com/rust-lang/crates.io-index" 2672 + checksum = "cf221c93e13a30d793f7645a0e7762c55d169dbb0a49671918a2319d289b10bb" 2673 + dependencies = [ 2674 + "windows-sys 0.59.0", 2675 + ] 2676 + 2677 + [[package]] 2678 + name = "winapi-x86_64-pc-windows-gnu" 2679 + version = "0.4.0" 2680 + source = "registry+https://github.com/rust-lang/crates.io-index" 2681 + checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" 2682 + 2683 + [[package]] 2684 + name = "windows-core" 2685 + version = "0.61.2" 2686 + source = "registry+https://github.com/rust-lang/crates.io-index" 2687 + checksum = "c0fdd3ddb90610c7638aa2b3a3ab2904fb9e5cdbecc643ddb3647212781c4ae3" 2688 + dependencies = [ 2689 + "windows-implement", 2690 + "windows-interface", 2691 + "windows-link 0.1.3", 2692 + "windows-result", 2693 + "windows-strings", 2694 + ] 2695 + 2696 + [[package]] 2697 + name = "windows-implement" 2698 + version = "0.60.0" 2699 + source = "registry+https://github.com/rust-lang/crates.io-index" 2700 + checksum = "a47fddd13af08290e67f4acabf4b459f647552718f683a7b415d290ac744a836" 2701 + dependencies = [ 2702 + "proc-macro2", 2703 + "quote", 2704 + "syn 2.0.104", 2705 + ] 2706 + 2707 + [[package]] 2708 + name = "windows-interface" 2709 + version = "0.59.1" 2710 + source = "registry+https://github.com/rust-lang/crates.io-index" 2711 + checksum = "bd9211b69f8dcdfa817bfd14bf1c97c9188afa36f4750130fcdf3f400eca9fa8" 2712 + dependencies = [ 2713 + "proc-macro2", 2714 + "quote", 2715 + "syn 2.0.104", 2716 + ] 2717 + 2718 + [[package]] 2719 + name = "windows-link" 2720 + version = "0.1.3" 2721 + source = "registry+https://github.com/rust-lang/crates.io-index" 2722 + checksum = "5e6ad25900d524eaabdbbb96d20b4311e1e7ae1699af4fb28c17ae66c80d798a" 2723 + 2724 + [[package]] 2725 + name = "windows-link" 2726 + version = "0.2.0" 2727 + source = "registry+https://github.com/rust-lang/crates.io-index" 2728 + checksum = "45e46c0661abb7180e7b9c281db115305d49ca1709ab8242adf09666d2173c65" 2729 + 2730 + [[package]] 2731 + name = "windows-result" 2732 + version = "0.3.4" 2733 + source = "registry+https://github.com/rust-lang/crates.io-index" 2734 + checksum = "56f42bd332cc6c8eac5af113fc0c1fd6a8fd2aa08a0119358686e5160d0586c6" 2735 + dependencies = [ 2736 + "windows-link 0.1.3", 2737 + ] 2738 + 2739 + [[package]] 2740 + name = "windows-strings" 2741 + version = "0.4.2" 2742 + source = "registry+https://github.com/rust-lang/crates.io-index" 2743 + checksum = "56e6c93f3a0c3b36176cb1327a4958a0353d5d166c2a35cb268ace15e91d3b57" 2744 + dependencies = [ 2745 + "windows-link 0.1.3", 2746 + ] 2747 + 2748 + [[package]] 2749 + name = "windows-sys" 2750 + version = "0.48.0" 2751 + source = "registry+https://github.com/rust-lang/crates.io-index" 2752 + checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" 2753 + dependencies = [ 2754 + "windows-targets 0.48.5", 2755 + ] 2756 + 2757 + [[package]] 2758 + name = "windows-sys" 2759 + version = "0.52.0" 2760 + source = "registry+https://github.com/rust-lang/crates.io-index" 2761 + checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" 2762 + dependencies = [ 2763 + "windows-targets 0.52.6", 2764 + ] 2765 + 2766 + [[package]] 540 2767 name = "windows-sys" 541 2768 version = "0.59.0" 542 2769 source = "registry+https://github.com/rust-lang/crates.io-index" 543 2770 checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" 544 2771 dependencies = [ 545 - "windows-targets", 2772 + "windows-targets 0.52.6", 2773 + ] 2774 + 2775 + [[package]] 2776 + name = "windows-sys" 2777 + version = "0.61.0" 2778 + source = "registry+https://github.com/rust-lang/crates.io-index" 2779 + checksum = "e201184e40b2ede64bc2ea34968b28e33622acdbbf37104f0e4a33f7abe657aa" 2780 + dependencies = [ 2781 + "windows-link 0.2.0", 2782 + ] 2783 + 2784 + [[package]] 2785 + name = "windows-targets" 2786 + version = "0.48.5" 2787 + source = "registry+https://github.com/rust-lang/crates.io-index" 2788 + checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c" 2789 + dependencies = [ 2790 + "windows_aarch64_gnullvm 0.48.5", 2791 + "windows_aarch64_msvc 0.48.5", 2792 + "windows_i686_gnu 0.48.5", 2793 + "windows_i686_msvc 0.48.5", 2794 + "windows_x86_64_gnu 0.48.5", 2795 + "windows_x86_64_gnullvm 0.48.5", 2796 + "windows_x86_64_msvc 0.48.5", 546 2797 ] 547 2798 548 2799 [[package]] ··· 551 2802 source = "registry+https://github.com/rust-lang/crates.io-index" 552 2803 checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" 553 2804 dependencies = [ 554 - "windows_aarch64_gnullvm", 555 - "windows_aarch64_msvc", 556 - "windows_i686_gnu", 2805 + "windows_aarch64_gnullvm 0.52.6", 2806 + "windows_aarch64_msvc 0.52.6", 2807 + "windows_i686_gnu 0.52.6", 557 2808 "windows_i686_gnullvm", 558 - "windows_i686_msvc", 559 - "windows_x86_64_gnu", 560 - "windows_x86_64_gnullvm", 561 - "windows_x86_64_msvc", 2809 + "windows_i686_msvc 0.52.6", 2810 + "windows_x86_64_gnu 0.52.6", 2811 + "windows_x86_64_gnullvm 0.52.6", 2812 + "windows_x86_64_msvc 0.52.6", 562 2813 ] 563 2814 564 2815 [[package]] 565 2816 name = "windows_aarch64_gnullvm" 2817 + version = "0.48.5" 2818 + source = "registry+https://github.com/rust-lang/crates.io-index" 2819 + checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" 2820 + 2821 + [[package]] 2822 + name = "windows_aarch64_gnullvm" 566 2823 version = "0.52.6" 567 2824 source = "registry+https://github.com/rust-lang/crates.io-index" 568 2825 checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" 569 2826 570 2827 [[package]] 571 2828 name = "windows_aarch64_msvc" 2829 + version = "0.48.5" 2830 + source = "registry+https://github.com/rust-lang/crates.io-index" 2831 + checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" 2832 + 2833 + [[package]] 2834 + name = "windows_aarch64_msvc" 572 2835 version = "0.52.6" 573 2836 source = "registry+https://github.com/rust-lang/crates.io-index" 574 2837 checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" 2838 + 2839 + [[package]] 2840 + name = "windows_i686_gnu" 2841 + version = "0.48.5" 2842 + source = "registry+https://github.com/rust-lang/crates.io-index" 2843 + checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" 575 2844 576 2845 [[package]] 577 2846 name = "windows_i686_gnu" ··· 587 2856 588 2857 [[package]] 589 2858 name = "windows_i686_msvc" 2859 + version = "0.48.5" 2860 + source = "registry+https://github.com/rust-lang/crates.io-index" 2861 + checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" 2862 + 2863 + [[package]] 2864 + name = "windows_i686_msvc" 590 2865 version = "0.52.6" 591 2866 source = "registry+https://github.com/rust-lang/crates.io-index" 592 2867 checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" 593 2868 594 2869 [[package]] 595 2870 name = "windows_x86_64_gnu" 2871 + version = "0.48.5" 2872 + source = "registry+https://github.com/rust-lang/crates.io-index" 2873 + checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" 2874 + 2875 + [[package]] 2876 + name = "windows_x86_64_gnu" 596 2877 version = "0.52.6" 597 2878 source = "registry+https://github.com/rust-lang/crates.io-index" 598 2879 checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" 599 2880 600 2881 [[package]] 601 2882 name = "windows_x86_64_gnullvm" 2883 + version = "0.48.5" 2884 + source = "registry+https://github.com/rust-lang/crates.io-index" 2885 + checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" 2886 + 2887 + [[package]] 2888 + name = "windows_x86_64_gnullvm" 602 2889 version = "0.52.6" 603 2890 source = "registry+https://github.com/rust-lang/crates.io-index" 604 2891 checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" 605 2892 606 2893 [[package]] 607 2894 name = "windows_x86_64_msvc" 2895 + version = "0.48.5" 2896 + source = "registry+https://github.com/rust-lang/crates.io-index" 2897 + checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" 2898 + 2899 + [[package]] 2900 + name = "windows_x86_64_msvc" 608 2901 version = "0.52.6" 609 2902 source = "registry+https://github.com/rust-lang/crates.io-index" 610 2903 checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" ··· 614 2907 version = "0.7.12" 615 2908 source = "registry+https://github.com/rust-lang/crates.io-index" 616 2909 checksum = "f3edebf492c8125044983378ecb5766203ad3b4c2f7a922bd7dd207f6d443e95" 2910 + 2911 + [[package]] 2912 + name = "winreg" 2913 + version = "0.8.0" 2914 + source = "registry+https://github.com/rust-lang/crates.io-index" 2915 + checksum = "d107f8c6e916235c4c01cabb3e8acf7bea8ef6a63ca2e7fa0527c049badfc48c" 2916 + dependencies = [ 2917 + "winapi", 2918 + ] 2919 + 2920 + [[package]] 2921 + name = "wit-bindgen" 2922 + version = "0.45.1" 2923 + source = "registry+https://github.com/rust-lang/crates.io-index" 2924 + checksum = "5c573471f125075647d03df72e026074b7203790d41351cd6edc96f46bcccd36" 2925 + 2926 + [[package]] 2927 + name = "writeable" 2928 + version = "0.6.1" 2929 + source = "registry+https://github.com/rust-lang/crates.io-index" 2930 + checksum = "ea2f10b9bb0928dfb1b42b65e1f9e36f7f54dbdf08457afefb38afcdec4fa2bb" 2931 + 2932 + [[package]] 2933 + name = "xid" 2934 + version = "1.1.1" 2935 + source = "registry+https://github.com/rust-lang/crates.io-index" 2936 + checksum = "3752a194518cdee5d019812fb7978c51d8f0b7cfe9ace5983df1780964bb84c0" 2937 + dependencies = [ 2938 + "crc32fast", 2939 + "hostname", 2940 + "md5", 2941 + "once_cell", 2942 + "rand", 2943 + "sysctl", 2944 + "thiserror 1.0.69", 2945 + "winreg", 2946 + ] 2947 + 2948 + [[package]] 2949 + name = "yoke" 2950 + version = "0.8.0" 2951 + source = "registry+https://github.com/rust-lang/crates.io-index" 2952 + checksum = "5f41bb01b8226ef4bfd589436a297c53d118f65921786300e427be8d487695cc" 2953 + dependencies = [ 2954 + "serde", 2955 + "stable_deref_trait", 2956 + "yoke-derive", 2957 + "zerofrom", 2958 + ] 2959 + 2960 + [[package]] 2961 + name = "yoke-derive" 2962 + version = "0.8.0" 2963 + source = "registry+https://github.com/rust-lang/crates.io-index" 2964 + checksum = "38da3c9736e16c5d3c8c597a9aaa5d1fa565d0532ae05e27c24aa62fb32c0ab6" 2965 + dependencies = [ 2966 + "proc-macro2", 2967 + "quote", 2968 + "syn 2.0.104", 2969 + "synstructure", 2970 + ] 2971 + 2972 + [[package]] 2973 + name = "zerocopy" 2974 + version = "0.8.26" 2975 + source = "registry+https://github.com/rust-lang/crates.io-index" 2976 + checksum = "1039dd0d3c310cf05de012d8a39ff557cb0d23087fd44cad61df08fc31907a2f" 2977 + dependencies = [ 2978 + "zerocopy-derive", 2979 + ] 2980 + 2981 + [[package]] 2982 + name = "zerocopy-derive" 2983 + version = "0.8.26" 2984 + source = "registry+https://github.com/rust-lang/crates.io-index" 2985 + checksum = "9ecf5b4cc5364572d7f4c329661bcc82724222973f2cab6f050a4e5c22f75181" 2986 + dependencies = [ 2987 + "proc-macro2", 2988 + "quote", 2989 + "syn 2.0.104", 2990 + ] 2991 + 2992 + [[package]] 2993 + name = "zerofrom" 2994 + version = "0.1.6" 2995 + source = "registry+https://github.com/rust-lang/crates.io-index" 2996 + checksum = "50cc42e0333e05660c3587f3bf9d0478688e15d870fab3346451ce7f8c9fbea5" 2997 + dependencies = [ 2998 + "zerofrom-derive", 2999 + ] 3000 + 3001 + [[package]] 3002 + name = "zerofrom-derive" 3003 + version = "0.1.6" 3004 + source = "registry+https://github.com/rust-lang/crates.io-index" 3005 + checksum = "d71e5d6e06ab090c67b5e44993ec16b72dcbaabc526db883a360057678b48502" 3006 + dependencies = [ 3007 + "proc-macro2", 3008 + "quote", 3009 + "syn 2.0.104", 3010 + "synstructure", 3011 + ] 3012 + 3013 + [[package]] 3014 + name = "zeroize" 3015 + version = "1.8.1" 3016 + source = "registry+https://github.com/rust-lang/crates.io-index" 3017 + checksum = "ced3678a2879b30306d323f4542626697a464a97c0a07c9aebf7ebca65cd4dde" 3018 + 3019 + [[package]] 3020 + name = "zerotrie" 3021 + version = "0.2.2" 3022 + source = "registry+https://github.com/rust-lang/crates.io-index" 3023 + checksum = "36f0bbd478583f79edad978b407914f61b2972f5af6fa089686016be8f9af595" 3024 + dependencies = [ 3025 + "displaydoc", 3026 + "yoke", 3027 + "zerofrom", 3028 + ] 3029 + 3030 + [[package]] 3031 + name = "zerovec" 3032 + version = "0.11.2" 3033 + source = "registry+https://github.com/rust-lang/crates.io-index" 3034 + checksum = "4a05eb080e015ba39cc9e23bbe5e7fb04d5fb040350f99f34e338d5fdd294428" 3035 + dependencies = [ 3036 + "yoke", 3037 + "zerofrom", 3038 + "zerovec-derive", 3039 + ] 3040 + 3041 + [[package]] 3042 + name = "zerovec-derive" 3043 + version = "0.11.1" 3044 + source = "registry+https://github.com/rust-lang/crates.io-index" 3045 + checksum = "5b96237efa0c878c64bd89c436f661be4e46b2f3eff1ebb976f7ef2321d2f58f" 3046 + dependencies = [ 3047 + "proc-macro2", 3048 + "quote", 3049 + "syn 2.0.104", 3050 + ]
+1
crates/firecracker-process/Cargo.toml
··· 11 11 libc = "0.2.174" 12 12 owo-colors = "4.2.2" 13 13 firecracker-vm = { path = "../firecracker-vm" } 14 + firecracker-state = { path = "../firecracker-state" }
+18 -2
crates/firecracker-process/src/command.rs
··· 1 1 use anyhow::{anyhow, Context, Error, Result}; 2 + use owo_colors::OwoColorize; 2 3 use std::{ 3 4 process::{Command, Output, Stdio}, 4 5 thread, ··· 49 50 Ok(output) 50 51 } 51 52 52 - pub fn run_command_in_background(command: &str, args: &[&str], use_sudo: bool) -> Result<()> { 53 + pub fn run_command_in_background(command: &str, args: &[&str], use_sudo: bool) -> Result<u32> { 53 54 let mut cmd = if use_sudo { 54 55 if !has_sudo() && !is_root() { 55 56 return Err(anyhow!( ··· 71 72 let command_owned = command.to_string(); 72 73 let args_owned: Vec<String> = args.iter().map(|s| s.to_string()).collect(); 73 74 75 + let (tx, rx) = std::sync::mpsc::channel::<u32>(); 76 + 74 77 thread::spawn(move || { 75 78 let mut child = cmd 76 79 .args(&args_owned) ··· 80 83 .spawn() 81 84 .with_context(|| format!("Failed to execute {}", command_owned))?; 82 85 86 + let pid = child.id(); 87 + tx.send(pid) 88 + .with_context(|| format!("Failed to send PID for command {}", command_owned))?; 89 + println!( 90 + "[+] Started command {} with PID {}", 91 + command_owned.bright_cyan(), 92 + pid.bright_cyan() 93 + ); 94 + 83 95 child 84 96 .wait() 85 97 .with_context(|| format!("Failed to wait for command {}", command_owned))?; 86 98 Ok::<(), Error>(()) 87 99 }); 88 100 89 - Ok(()) 101 + let pid = rx 102 + .recv() 103 + .with_context(|| format!("Failed to receive PID for command {}", command))?; 104 + 105 + Ok(pid) 90 106 }
+84 -11
crates/firecracker-process/src/lib.rs
··· 1 + use std::process; 2 + 1 3 use anyhow::Result; 4 + use firecracker_state::repo; 2 5 use firecracker_vm::types::VmOptions; 6 + use owo_colors::OwoColorize; 3 7 4 8 use crate::command::{run_command, run_command_in_background}; 5 9 6 10 pub mod command; 7 11 8 - pub fn start(config: &VmOptions) -> Result<()> { 9 - stop(config)?; 12 + pub async fn start(config: &VmOptions) -> Result<u32> { 13 + let name = config 14 + .api_socket 15 + .trim_start_matches("/tmp/firecracker-") 16 + .trim_end_matches(".sock") 17 + .to_string(); 18 + 19 + stop(Some(name)).await?; 10 20 println!("[+] Starting Firecracker..."); 11 - run_command_in_background("firecracker", &["--api-sock", &config.api_socket], true)?; 12 - Ok(()) 21 + let pid = run_command_in_background("firecracker", &["--api-sock", &config.api_socket], true)?; 22 + Ok(pid) 13 23 } 14 24 15 - pub fn stop(config: &VmOptions) -> Result<()> { 16 - if !is_running() { 17 - println!("[!] Firecracker is not running."); 18 - run_command("rm", &["-rf", &config.api_socket], true)?; 25 + pub async fn stop(name: Option<String>) -> Result<()> { 26 + if name.is_none() { 27 + return stop_all().await; 28 + } 29 + 30 + let name = name.unwrap(); 31 + 32 + if !vm_is_running(&name).await? { 33 + println!("[!] {} is not running.", name.cyan()); 19 34 return Ok(()); 20 35 } 21 - run_command("killall", &["-s", "KILL", "firecracker"], true)?; 36 + 37 + let config = VmOptions { 38 + api_socket: format!("/tmp/firecracker-{}.sock", name), 39 + ..Default::default() 40 + }; 41 + 42 + let pool = firecracker_state::create_connection_pool().await?; 43 + 44 + let vm = repo::virtual_machine::find(&pool, &name).await?; 45 + if vm.is_none() { 46 + println!( 47 + "[!] No virtual machine found with name or id '{}'.", 48 + name.cyan() 49 + ); 50 + process::exit(1); 51 + } 52 + 53 + let vm = vm.unwrap(); 54 + if let Some(pid) = vm.pid { 55 + run_command("kill", &["-s", "KILL", &pid.to_string()], true)?; 56 + } 57 + 22 58 run_command("rm", &["-rf", &config.api_socket], true)?; 23 - println!("[+] Firecracker has been stopped."); 59 + println!("[+] {} has been stopped.", name.cyan()); 60 + 61 + repo::virtual_machine::update_status(&pool, &name, "STOPPED").await?; 62 + 24 63 Ok(()) 25 64 } 26 65 66 + pub async fn vm_is_running(name: &str) -> Result<bool> { 67 + let pool = firecracker_state::create_connection_pool().await?; 68 + let vm = repo::virtual_machine::find(&pool, name).await?; 69 + 70 + if let Some(vm) = vm { 71 + if std::path::Path::new(&vm.api_socket).exists() { 72 + return Ok(true); 73 + } 74 + if vm.status == "RUNNING" { 75 + return Ok(true); 76 + } 77 + } 78 + 79 + Ok(false) 80 + } 81 + 27 82 pub fn is_running() -> bool { 28 - run_command("pgrep", &["firecracker"], false).is_ok() 83 + match run_command("pgrep", &["-x", "firecracker"], false) { 84 + Ok(output) => output.status.success(), 85 + Err(_) => false, 86 + } 87 + } 88 + 89 + pub async fn stop_all() -> Result<()> { 90 + if !is_running() { 91 + println!("[!] No Firecracker process is running."); 92 + return Ok(()); 93 + } 94 + 95 + run_command("pkill", &["-x", "firecracker"], true)?; 96 + run_command("bash", &["-c", "rm -rf /tmp/firecracker-*.sock"], true)?; 97 + println!("[+] All Firecracker processes have been stopped."); 98 + 99 + let pool = firecracker_state::create_connection_pool().await?; 100 + repo::virtual_machine::update_all_status(&pool, "STOPPED").await?; 101 + Ok(()) 29 102 }
+24
crates/firecracker-state/Cargo.toml
··· 1 + [package] 2 + name = "firecracker-state" 3 + version = "0.1.0" 4 + authors.workspace = true 5 + edition.workspace = true 6 + license.workspace = true 7 + repository.workspace = true 8 + 9 + [dependencies] 10 + anyhow = "1.0.98" 11 + chrono = { version = "0.4.41", features = ["serde"] } 12 + dirs = "6.0.0" 13 + names = "0.14.0" 14 + serde = { version = "1.0.219", features = ["serde_derive", "derive"] } 15 + sqlx = { version = "0.8.6", features = [ 16 + "runtime-tokio", 17 + "tls-rustls", 18 + "sqlite", 19 + "chrono", 20 + "derive", 21 + "macros", 22 + ] } 23 + tokio = { version = "1.47.1", features = ["full"] } 24 + xid = "1.1.1"
+17
crates/firecracker-state/migrations/20250804092946_init.sql
··· 1 + -- Add migration script here 2 + CREATE TABLE IF NOT EXISTS virtual_machines ( 3 + id VARCHAR(255) PRIMARY KEY, 4 + name VARCHAR(255) UNIQUE NOT NULL, 5 + status VARCHAR(255) NOT NULL, 6 + vcpu INT NOT NULL, 7 + memory INT NOT NULL, 8 + distro VARCHAR(255) NOT NULL, 9 + pid INT, 10 + mac_address VARCHAR(255) NOT NULL, 11 + bridge VARCHAR(255) NOT NULL, 12 + tap VARCHAR(255) NOT NULL, 13 + api_socket VARCHAR(255) UNIQUE NOT NULL, 14 + project_dir VARCHAR(255) UNIQUE, 15 + created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, 16 + updated_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP 17 + );
+3
crates/firecracker-state/migrations/20250910164344_ip_address.sql
··· 1 + -- Add migration script here 2 + ALTER TABLE virtual_machines 3 + ADD COLUMN ip_address VARCHAR(255);
+9
crates/firecracker-state/migrations/20250910202353_add_vmlinux_rootfs_bootargs.sql
··· 1 + -- Add migration script here 2 + ALTER TABLE virtual_machines 3 + ADD COLUMN vmlinux VARCHAR(255); 4 + 5 + ALTER TABLE virtual_machines 6 + ADD COLUMN rootfs VARCHAR(255); 7 + 8 + ALTER TABLE virtual_machines 9 + ADD COLUMN bootargs TEXT;
+4
crates/firecracker-state/migrations/20250911084132_ensure_unique_columns.sql
··· 1 + -- Add migration script here 2 + CREATE UNIQUE INDEX IF NOT EXISTS idx_unique_mac_address ON virtual_machines (mac_address); 3 + CREATE UNIQUE INDEX IF NOT EXISTS idx_unique_pid ON virtual_machines (pid); 4 + CREATE UNIQUE INDEX IF NOT EXISTS idx_unique_tap ON virtual_machines (tap);
+1
crates/firecracker-state/src/entity/mod.rs
··· 1 + pub mod virtual_machine;
+26
crates/firecracker-state/src/entity/virtual_machine.rs
··· 1 + use chrono::{DateTime, Utc}; 2 + use serde::{Deserialize, Serialize}; 3 + 4 + #[derive(sqlx::FromRow, Default, Debug, Clone, Serialize, Deserialize)] 5 + pub struct VirtualMachine { 6 + pub id: String, 7 + pub name: String, 8 + pub status: String, 9 + pub vcpu: u16, 10 + pub memory: u16, 11 + pub distro: String, 12 + pub pid: Option<u32>, 13 + pub mac_address: String, 14 + pub bridge: String, 15 + pub tap: String, 16 + pub api_socket: String, 17 + pub project_dir: Option<String>, 18 + pub ip_address: Option<String>, 19 + pub vmlinux: Option<String>, 20 + pub rootfs: Option<String>, 21 + pub bootargs: Option<String>, 22 + #[serde(with = "chrono::serde::ts_seconds")] 23 + pub created_at: DateTime<Utc>, 24 + #[serde(with = "chrono::serde::ts_seconds")] 25 + pub updated_at: DateTime<Utc>, 26 + }
+70
crates/firecracker-state/src/lib.rs
··· 1 + use anyhow::{anyhow, Context, Error}; 2 + use sqlx::{sqlite::SqliteConnectOptions, Executor, Pool, Sqlite, SqlitePool}; 3 + use std::fs; 4 + 5 + pub mod entity; 6 + pub mod repo; 7 + 8 + pub async fn create_connection_pool() -> Result<Pool<Sqlite>, Error> { 9 + let config_dir = get_config_dir()?; 10 + let db_path = format!("{}/firecracker_state.db", config_dir); 11 + let options = SqliteConnectOptions::new() 12 + .filename(db_path) 13 + .create_if_missing(true); 14 + let pool = SqlitePool::connect_with(options).await?; 15 + 16 + pool.execute(include_str!("../migrations/20250804092946_init.sql")) 17 + .await?; 18 + 19 + match pool 20 + .execute(include_str!("../migrations/20250910164344_ip_address.sql")) 21 + .await 22 + { 23 + Ok(_) => (), 24 + Err(e) => { 25 + if e.to_string().contains("duplicate column name: ip_address") { 26 + } else { 27 + return Err(anyhow!("Failed to apply migration: {}", e)); 28 + } 29 + } 30 + } 31 + 32 + match pool 33 + .execute(include_str!( 34 + "../migrations/20250910202353_add_vmlinux_rootfs_bootargs.sql" 35 + )) 36 + .await 37 + { 38 + Ok(_) => (), 39 + Err(e) => { 40 + if e.to_string().contains("duplicate column name: vmlinux") 41 + || e.to_string().contains("duplicate column name: rootfs") 42 + || e.to_string().contains("duplicate column name: bootargs") 43 + { 44 + } else { 45 + return Err(anyhow!("Failed to apply migration: {}", e)); 46 + } 47 + } 48 + } 49 + 50 + pool.execute(include_str!( 51 + "../migrations/20250911084132_ensure_unique_columns.sql" 52 + )) 53 + .await?; 54 + 55 + sqlx::query("PRAGMA journal_mode=WAL") 56 + .execute(&pool) 57 + .await?; 58 + 59 + Ok(pool) 60 + } 61 + 62 + fn get_config_dir() -> Result<String, Error> { 63 + let app_dir = dirs::home_dir() 64 + .ok_or_else(|| anyhow!("Failed to get home directory"))? 65 + .join(".fireup"); 66 + fs::create_dir_all(&app_dir) 67 + .with_context(|| format!("Failed to create app directory: {}", app_dir.display()))?; 68 + 69 + Ok(app_dir.display().to_string()) 70 + }
+1
crates/firecracker-state/src/repo/mod.rs
··· 1 + pub mod virtual_machine;
+193
crates/firecracker-state/src/repo/virtual_machine.rs
··· 1 + use std::path::Path; 2 + 3 + use anyhow::{Context, Error}; 4 + use sqlx::{Pool, Sqlite}; 5 + 6 + use crate::entity::virtual_machine::VirtualMachine; 7 + 8 + pub async fn all(pool: &Pool<Sqlite>) -> Result<Vec<VirtualMachine>, Error> { 9 + let result: Vec<VirtualMachine> = sqlx::query_as("SELECT * FROM virtual_machines") 10 + .fetch_all(pool) 11 + .await 12 + .with_context(|| "Failed to fetch virtual machines")?; 13 + Ok(result) 14 + } 15 + 16 + pub async fn find(pool: &Pool<Sqlite>, name: &str) -> Result<Option<VirtualMachine>, Error> { 17 + let result: Option<VirtualMachine> = 18 + sqlx::query_as("SELECT * FROM virtual_machines WHERE name = ? OR id = ?") 19 + .bind(name) 20 + .fetch_optional(pool) 21 + .await 22 + .with_context(|| { 23 + format!("Failed to find virtual machine with name or id '{}'", name) 24 + })?; 25 + Ok(result) 26 + } 27 + 28 + pub async fn find_by_project_dir( 29 + pool: &Pool<Sqlite>, 30 + path: &str, 31 + ) -> Result<Option<VirtualMachine>, Error> { 32 + let result: Option<VirtualMachine> = 33 + sqlx::query_as("SELECT * FROM virtual_machines WHERE project_dir = ?") 34 + .bind(path) 35 + .fetch_optional(pool) 36 + .await 37 + .with_context(|| { 38 + format!("Failed to find virtual machine with project_dir '{}'", path) 39 + })?; 40 + Ok(result) 41 + } 42 + 43 + pub async fn create(pool: &Pool<Sqlite>, vm: VirtualMachine) -> Result<(), Error> { 44 + let id = xid::new().to_string(); 45 + let project_dir = match Path::exists(Path::new("fire.toml")) { 46 + true => Some(std::env::current_dir()?.display().to_string()), 47 + false => None, 48 + }; 49 + sqlx::query( 50 + "INSERT INTO virtual_machines ( 51 + name, 52 + id, 53 + project_dir, 54 + bridge, 55 + tap, 56 + api_socket, 57 + mac_address, 58 + vcpu, 59 + memory, 60 + distro, 61 + pid, 62 + status, 63 + ip_address, 64 + vmlinux, 65 + rootfs, 66 + bootargs 67 + ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", 68 + ) 69 + .bind(&vm.name) 70 + .bind(&id) 71 + .bind(project_dir) 72 + .bind(&vm.bridge) 73 + .bind(&vm.tap) 74 + .bind(&vm.api_socket) 75 + .bind(&vm.mac_address) 76 + .bind(&vm.vcpu) 77 + .bind(&vm.memory) 78 + .bind(&vm.distro) 79 + .bind(&vm.pid) 80 + .bind("RUNNING") 81 + .bind(&vm.ip_address) 82 + .bind(&vm.vmlinux) 83 + .bind(&vm.rootfs) 84 + .bind(&vm.bootargs) 85 + .execute(pool) 86 + .await 87 + .with_context(|| "Failed to create virtual machine")?; 88 + Ok(()) 89 + } 90 + 91 + pub async fn delete(pool: &Pool<Sqlite>, name: &str) -> Result<(), Error> { 92 + sqlx::query("DELETE FROM virtual_machines WHERE name = ? OR id = ?") 93 + .bind(name) 94 + .bind(name) 95 + .execute(pool) 96 + .await 97 + .with_context(|| { 98 + format!( 99 + "Failed to delete virtual machine with name or id '{}'", 100 + name 101 + ) 102 + })?; 103 + Ok(()) 104 + } 105 + 106 + pub async fn update(pool: &Pool<Sqlite>, id: &str, vm: VirtualMachine) -> Result<(), Error> { 107 + sqlx::query( 108 + r#" 109 + UPDATE virtual_machines 110 + SET project_dir = ?, 111 + bridge = ?, 112 + tap = ?, 113 + api_socket = ?, 114 + mac_address = ?, 115 + status = ?, 116 + pid = ?, 117 + ip_address = ?, 118 + vcpu = ?, 119 + memory = ?, 120 + distro = ?, 121 + vmlinux = ?, 122 + rootfs = ?, 123 + bootargs = ? 124 + WHERE id = ?"#, 125 + ) 126 + .bind(&vm.project_dir) 127 + .bind(&vm.bridge) 128 + .bind(&vm.tap) 129 + .bind(&vm.api_socket) 130 + .bind(&vm.mac_address) 131 + .bind(&vm.status) 132 + .bind(&vm.pid) 133 + .bind(&vm.ip_address) 134 + .bind(&vm.vcpu) 135 + .bind(&vm.memory) 136 + .bind(&vm.distro) 137 + .bind(&vm.vmlinux) 138 + .bind(&vm.rootfs) 139 + .bind(&vm.bootargs) 140 + .bind(id) 141 + .execute(pool) 142 + .await 143 + .with_context(|| { 144 + format!( 145 + "Failed to update virtual machine with name or id '{}'", 146 + vm.name 147 + ) 148 + })?; 149 + Ok(()) 150 + } 151 + 152 + pub async fn update_status(pool: &Pool<Sqlite>, name: &str, status: &str) -> Result<(), Error> { 153 + sqlx::query("UPDATE virtual_machines SET status = ? WHERE name = ? OR id = ?") 154 + .bind(status) 155 + .bind(name) 156 + .bind(name) 157 + .execute(pool) 158 + .await 159 + .with_context(|| { 160 + format!( 161 + "Failed to update status for virtual machine with name or id '{}'", 162 + name 163 + ) 164 + })?; 165 + Ok(()) 166 + } 167 + 168 + pub async fn update_all_status(pool: &Pool<Sqlite>, status: &str) -> Result<(), Error> { 169 + sqlx::query("UPDATE virtual_machines SET status = ?") 170 + .bind(status) 171 + .execute(pool) 172 + .await 173 + .with_context(|| "Failed to update status for all virtual machines")?; 174 + Ok(()) 175 + } 176 + 177 + pub async fn find_by_api_socket( 178 + pool: &Pool<Sqlite>, 179 + api_socket: &str, 180 + ) -> Result<Option<VirtualMachine>, Error> { 181 + let result: Option<VirtualMachine> = 182 + sqlx::query_as("SELECT * FROM virtual_machines WHERE api_socket = ?") 183 + .bind(api_socket) 184 + .fetch_optional(pool) 185 + .await 186 + .with_context(|| { 187 + format!( 188 + "Failed to find virtual machine with api_socket '{}'", 189 + api_socket 190 + ) 191 + })?; 192 + Ok(result) 193 + }
+12
crates/firecracker-up/Cargo.toml
··· 11 11 firecracker-vm = { path = "../firecracker-vm" } 12 12 firecracker-prepare = { path = "../firecracker-prepare" } 13 13 firecracker-process = { path = "../firecracker-process" } 14 + firecracker-state = { path = "../firecracker-state" } 14 15 fire-config = { path = "../fire-config" } 15 16 clap = "4.5.41" 16 17 owo-colors = "4.2.2" 17 18 glob = "0.3.2" 18 19 dirs = "6.0.0" 19 20 num_cpus = "1.17.0" 21 + tokio = { version = "1.47.1", features = ["full"] } 22 + names = "0.14.0" 23 + sqlx = { version = "0.8.6", features = [ 24 + "runtime-tokio", 25 + "tls-rustls", 26 + "sqlite", 27 + "chrono", 28 + "derive", 29 + "macros", 30 + ] } 31 + chrono = "0.4.42"
+2 -3
crates/firecracker-up/src/cmd/down.rs
··· 1 1 use anyhow::Error; 2 - use firecracker_vm::types::VmOptions; 3 2 4 - pub fn down(options: &VmOptions) -> Result<(), Error> { 5 - firecracker_process::stop(options)?; 3 + pub async fn down() -> Result<(), Error> { 4 + firecracker_process::stop(None).await?; 6 5 Ok(()) 7 6 }
+3
crates/firecracker-up/src/cmd/mod.rs
··· 1 1 pub mod down; 2 2 pub mod init; 3 3 pub mod logs; 4 + pub mod ps; 4 5 pub mod reset; 5 6 pub mod ssh; 7 + pub mod start; 6 8 pub mod status; 9 + pub mod stop; 7 10 pub mod up;
+39
crates/firecracker-up/src/cmd/ps.rs
··· 1 + use anyhow::Error; 2 + 3 + use crate::date::format_duration_ago; 4 + 5 + pub async fn list_all_instances(all: bool) -> Result<(), Error> { 6 + let pool = firecracker_state::create_connection_pool().await?; 7 + let mut vms = firecracker_state::repo::virtual_machine::all(&pool).await?; 8 + if !all { 9 + vms = vms 10 + .into_iter() 11 + .filter(|vm| vm.status == "RUNNING") 12 + .collect::<Vec<_>>(); 13 + } 14 + 15 + if vms.is_empty() { 16 + println!("No Firecracker MicroVM instances found."); 17 + return Ok(()); 18 + } 19 + 20 + println!( 21 + "{:<20} {:<10} {:<5} {:<10} {:<15} {:<10} {:<15} {:<10}", 22 + "NAME", "DISTRO", "VCPU", "MEMORY", "STATUS", "PID", "IP", "CREATED" 23 + ); 24 + for vm in vms { 25 + println!( 26 + "{:<20} {:<10} {:<5} {:<10} {:<15} {:<10} {:<15} {:<10}", 27 + vm.name, 28 + vm.distro, 29 + vm.vcpu, 30 + format!("{} MiB", vm.memory), 31 + vm.status, 32 + vm.pid.unwrap_or(0), 33 + vm.ip_address.unwrap_or_default(), 34 + format_duration_ago(vm.created_at), 35 + ); 36 + } 37 + 38 + Ok(()) 39 + }
+9 -4
crates/firecracker-up/src/cmd/reset.rs
··· 1 1 use anyhow::Error; 2 + use firecracker_process::stop; 2 3 use firecracker_vm::types::VmOptions; 3 4 use glob::glob; 4 5 use owo_colors::OwoColorize; 5 6 6 - use crate::cmd::down::down; 7 - 8 - pub fn reset(options: VmOptions) -> Result<(), Error> { 7 + pub async fn reset(options: VmOptions) -> Result<(), Error> { 9 8 println!( 10 9 "Are you sure you want to reset? This will remove all ext4 files. Type '{}' to confirm:", 11 10 "yes".bright_green() ··· 21 20 return Ok(()); 22 21 } 23 22 24 - down(&options)?; 23 + let name = options 24 + .api_socket 25 + .trim_start_matches("/tmp/firecracker-") 26 + .trim_end_matches(".sock") 27 + .to_string(); 28 + 29 + stop(Some(name)).await?; 25 30 26 31 let app_dir = crate::config::get_config_dir()?; 27 32 let ext4_file = glob(format!("{}/*.ext4", app_dir).as_str())
+22 -4
crates/firecracker-up/src/cmd/ssh.rs
··· 1 1 use crate::{command::run_command, config::get_config_dir}; 2 2 use anyhow::Error; 3 + use firecracker_state::repo; 3 4 use glob::glob; 5 + use sqlx::{Pool, Sqlite}; 4 6 5 - const GUEST_IP: &str = "vm0.firecracker.local"; 6 - 7 - pub fn ssh() -> Result<(), Error> { 7 + pub async fn ssh(pool: Pool<Sqlite>, name: Option<String>) -> Result<(), Error> { 8 + let guest_ip = match name { 9 + Some(name) => format!("{}.firecracker", name), 10 + None => { 11 + let current_dir = std::env::current_dir() 12 + .map_err(|e| Error::msg(format!("Failed to get current directory: {}", e)))? 13 + .display() 14 + .to_string(); 15 + let vm = repo::virtual_machine::find_by_project_dir(&pool, &current_dir).await?; 16 + match vm { 17 + Some(vm) => format!("{}.firecracker", vm.name), 18 + None => { 19 + return Err(Error::msg( 20 + "No virtual machine found with the given name or project directory.", 21 + )) 22 + } 23 + } 24 + } 25 + }; 8 26 let app_dir = get_config_dir()?; 9 27 let private_key = glob(format!("{}/id_rsa", app_dir).as_str()) 10 28 .map_err(|e| Error::msg(format!("Failed to find SSH key: {}", e)))? ··· 19 37 "StrictHostKeyChecking=no", 20 38 "-o", 21 39 "UserKnownHostsFile=/dev/null", 22 - &format!("root@{}", GUEST_IP), 40 + &format!("root@{}", guest_ip), 23 41 ], 24 42 true, 25 43 )?;
+37
crates/firecracker-up/src/cmd/start.rs
··· 1 + use std::process; 2 + 3 + use anyhow::Error; 4 + use firecracker_state::repo; 5 + use firecracker_vm::types::VmOptions; 6 + 7 + use crate::cmd::up::up; 8 + 9 + pub async fn start(name: &str) -> Result<(), Error> { 10 + let pool = firecracker_state::create_connection_pool().await?; 11 + let vm = repo::virtual_machine::find(&pool, name).await?; 12 + if vm.is_none() { 13 + println!("[!] No virtual machine found with the name: {}", name); 14 + process::exit(1); 15 + } 16 + 17 + let vm = vm.unwrap(); 18 + 19 + up(VmOptions { 20 + debian: Some(vm.distro == "debian"), 21 + alpine: Some(vm.distro == "alpine"), 22 + ubuntu: Some(vm.distro == "ubuntu"), 23 + nixos: Some(vm.distro == "nixos"), 24 + vcpu: vm.vcpu, 25 + memory: vm.memory, 26 + vmlinux: vm.vmlinux, 27 + rootfs: vm.rootfs, 28 + bootargs: vm.bootargs, 29 + bridge: vm.bridge, 30 + tap: vm.tap, 31 + api_socket: vm.api_socket, 32 + mac_address: vm.mac_address, 33 + }) 34 + .await?; 35 + 36 + Ok(()) 37 + }
+26 -11
crates/firecracker-up/src/cmd/status.rs
··· 1 1 use anyhow::Error; 2 2 use owo_colors::OwoColorize; 3 3 4 - pub fn status() -> Result<(), Error> { 5 - if firecracker_process::is_running() { 6 - println!( 7 - "Firecracker MicroVM is running. {}", 8 - "[✓] RUNNING".bright_green() 9 - ); 10 - return Ok(()); 4 + pub async fn status(name: Option<String>) -> Result<(), Error> { 5 + match name { 6 + Some(name) => { 7 + if firecracker_process::vm_is_running(&name).await? { 8 + println!( 9 + "{} is running. {}", 10 + name.cyan(), 11 + "[✓] RUNNING".bright_green() 12 + ); 13 + return Ok(()); 14 + } 15 + 16 + println!( 17 + "{} is not running. {}", 18 + name.cyan(), 19 + "[✗] STOPPED".bright_red() 20 + ); 21 + } 22 + None => { 23 + if firecracker_process::is_running() { 24 + println!("Firecracker is running. {}", "[✓] RUNNING".bright_green()); 25 + return Ok(()); 26 + } 27 + 28 + println!("Firecracker is not running. {}", "[✗] STOPPED".bright_red()); 29 + } 11 30 } 12 31 13 - println!( 14 - "Firecracker MicroVM is not running. {}", 15 - "[✗] STOPPED".bright_red() 16 - ); 17 32 Ok(()) 18 33 }
+6
crates/firecracker-up/src/cmd/stop.rs
··· 1 + use anyhow::Error; 2 + 3 + pub async fn stop(name: &str) -> Result<(), Error> { 4 + firecracker_process::stop(Some(name.to_string())).await?; 5 + Ok(()) 6 + }
+58 -5
crates/firecracker-up/src/cmd/up.rs
··· 1 - use std::thread; 1 + use std::{process, thread}; 2 2 3 3 use anyhow::Error; 4 4 use fire_config::read_config; 5 + use firecracker_state::repo; 5 6 use firecracker_vm::types::VmOptions; 6 7 use owo_colors::OwoColorize; 7 8 8 9 use crate::command::run_command; 9 10 10 - pub fn up(options: VmOptions) -> Result<(), Error> { 11 + pub async fn up(options: VmOptions) -> Result<(), Error> { 11 12 check_kvm_support()?; 12 13 13 - let options = match read_config() { 14 + let mut options = match read_config() { 14 15 Ok(config) => VmOptions::from(config), 15 16 Err(_) => options.clone(), 16 17 }; 17 18 18 - firecracker_process::start(&options)?; 19 + let current_dir = std::env::current_dir()?; 20 + let fire_toml = current_dir.join("fire.toml"); 21 + let mut vm_id = None; 22 + let pool = firecracker_state::create_connection_pool().await?; 23 + let vm = repo::virtual_machine::find_by_api_socket(&pool, &options.api_socket).await?; 24 + 25 + if let Some(vm) = vm { 26 + vm_id = Some(vm.id.clone()); 27 + } 28 + 29 + if fire_toml.exists() { 30 + let vm = 31 + repo::virtual_machine::find_by_project_dir(&pool, &current_dir.display().to_string()) 32 + .await?; 33 + 34 + if let Some(vm) = vm { 35 + options.api_socket = vm.api_socket.clone(); 36 + vm_id = Some(vm.id.clone()); 37 + } 38 + } 39 + 40 + let vms = repo::virtual_machine::all(&pool).await?; 41 + if options.tap.is_empty() { 42 + let vms = vms 43 + .into_iter() 44 + .filter(|vm| vm.tap.starts_with("tap")) 45 + .collect::<Vec<_>>(); 46 + options.tap = format!("tap{}", vms.len()); 47 + 48 + while vms.iter().any(|vm| vm.tap == options.tap) { 49 + let tap_num: u32 = options 50 + .tap 51 + .trim_start_matches("tap") 52 + .parse::<u32>() 53 + .unwrap_or(0) 54 + .checked_add(1) 55 + .unwrap_or(0); 56 + options.tap = format!("tap{}", tap_num); 57 + } 58 + } else { 59 + if vms 60 + .iter() 61 + .any(|vm| vm.tap == options.tap && vm.api_socket != options.api_socket) 62 + { 63 + println!( 64 + "[!] Tap device name {} is already in use. Please choose a different name.", 65 + options.tap.cyan() 66 + ); 67 + process::exit(1); 68 + } 69 + } 70 + 71 + let pid = firecracker_process::start(&options).await?; 19 72 20 73 loop { 21 74 thread::sleep(std::time::Duration::from_secs(1)); ··· 26 79 } 27 80 28 81 firecracker_prepare::prepare(options.clone().into())?; 29 - firecracker_vm::setup(&options)?; 82 + firecracker_vm::setup(&options, pid, vm_id).await?; 30 83 Ok(()) 31 84 } 32 85
+38
crates/firecracker-up/src/date.rs
··· 1 + use chrono::{DateTime, Utc}; 2 + 3 + pub fn format_duration_ago(created: DateTime<Utc>) -> String { 4 + let now = Utc::now(); 5 + let duration = now - created; 6 + 7 + let seconds = duration.num_seconds(); 8 + let minutes = duration.num_minutes(); 9 + let hours = duration.num_hours(); 10 + let days = duration.num_days(); 11 + let weeks = duration.num_weeks(); 12 + let months = days / 30; // Approximate months 13 + let years = days / 365; // Approximate years 14 + 15 + if years > 0 { 16 + format!("{} year{} ago", years, if years == 1 { "" } else { "s" }) 17 + } else if months > 0 { 18 + format!("{} month{} ago", months, if months == 1 { "" } else { "s" }) 19 + } else if weeks > 0 { 20 + format!("{} week{} ago", weeks, if weeks == 1 { "" } else { "s" }) 21 + } else if days > 0 { 22 + format!("{} day{} ago", days, if days == 1 { "" } else { "s" }) 23 + } else if hours > 0 { 24 + format!("{} hour{} ago", hours, if hours == 1 { "" } else { "s" }) 25 + } else if minutes > 0 { 26 + format!( 27 + "{} minute{} ago", 28 + minutes, 29 + if minutes == 1 { "" } else { "s" } 30 + ) 31 + } else { 32 + format!( 33 + "{} second{} ago", 34 + seconds, 35 + if seconds == 1 { "" } else { "s" } 36 + ) 37 + } 38 + }
+92 -47
crates/firecracker-up/src/main.rs
··· 1 1 use anyhow::Result; 2 2 use clap::{arg, Arg, Command}; 3 - use firecracker_vm::{ 4 - constants::{BRIDGE_DEV, FC_MAC, FIRECRACKER_SOCKET, TAP_DEV}, 5 - types::VmOptions, 6 - }; 3 + use firecracker_vm::{constants::BRIDGE_DEV, mac::generate_unique_mac, types::VmOptions}; 7 4 use owo_colors::OwoColorize; 8 5 9 6 use crate::cmd::{ 10 - down::down, init::init, logs::logs, reset::reset, ssh::ssh, status::status, up::up, 7 + down::down, init::init, logs::logs, ps::list_all_instances, reset::reset, ssh::ssh, 8 + start::start, status::status, stop::stop, up::up, 11 9 }; 12 10 13 11 pub mod cmd; 14 12 pub mod command; 15 13 pub mod config; 14 + pub mod date; 16 15 17 16 fn cli() -> Command { 18 17 let banner = format!( ··· 35 34 "Create a new Firecracker MicroVM configuration `fire.toml` in the current directory", 36 35 )) 37 36 .subcommand( 37 + Command::new("ps") 38 + .alias("list") 39 + .arg(arg!(-a --all "Show all Firecracker MicroVM instances").default_value("false")) 40 + .about("List all Firecracker MicroVM instances"), 41 + ) 42 + .subcommand( 43 + Command::new("start") 44 + .arg(arg!(<name> "Name of the Firecracker MicroVM to start").required(true)) 45 + .about("Start Firecracker MicroVM"), 46 + ) 47 + .subcommand( 48 + Command::new("stop") 49 + .arg(arg!([name] "Name of the Firecracker MicroVM to stop").required(false)) 50 + .about("Stop Firecracker MicroVM"), 51 + ) 52 + .subcommand( 53 + Command::new("restart") 54 + .arg(arg!(<name> "Name of the Firecracker MicroVM to restart").required(true)) 55 + .about("Restart Firecracker MicroVM"), 56 + ) 57 + .subcommand( 38 58 Command::new("up") 39 59 .arg(arg!(--debian "Prepare Debian MicroVM").default_value("false")) 40 60 .arg(arg!(--alpine "Prepare Alpine MicroVM").default_value("false")) ··· 45 65 .arg(arg!(--vmlinux <path> "Path to the kernel image")) 46 66 .arg(arg!(--rootfs <path> "Path to the root filesystem image")) 47 67 .arg(arg!(--bridge <name> "Name of the bridge interface").default_value(BRIDGE_DEV)) 48 - .arg(arg!(--tap <name> "Name of the tap interface").default_value(TAP_DEV)) 68 + .arg(arg!(--tap <name> "Name of the tap interface").default_value("")) 49 69 .arg( 50 70 Arg::new("mac-address") 51 71 .long("mac-address") 52 72 .value_name("MAC") 53 - .default_value(FC_MAC) 54 73 .help("MAC address for the network interface"), 55 74 ) 56 75 .arg( 57 76 Arg::new("api-socket") 58 77 .long("api-socket") 59 78 .value_name("path") 60 - .default_value(FIRECRACKER_SOCKET) 61 79 .help("Path to the Firecracker API socket"), 62 80 ) 63 81 .arg( ··· 66 84 .value_name("ARGS") 67 85 .help("Override boot arguments"), 68 86 ) 69 - .about("Start Firecracker MicroVM"), 87 + .about("Start a new Firecracker MicroVM"), 70 88 ) 89 + .subcommand(Command::new("down").about("Stop Firecracker MicroVM")) 71 90 .subcommand( 72 - Command::new("down") 73 - .arg( 74 - Arg::new("api-socket") 75 - .long("api-socket") 76 - .value_name("path") 77 - .default_value(FIRECRACKER_SOCKET) 78 - .help("Path to the Firecracker API socket"), 79 - ) 80 - .about("Stop Firecracker MicroVM"), 91 + Command::new("status") 92 + .arg(arg!([name] "Name of the Firecracker MicroVM to check status").required(false)) 93 + .about("Check the status of Firecracker MicroVM"), 81 94 ) 82 - .subcommand(Command::new("status").about("Check the status of Firecracker MicroVM")) 83 95 .subcommand( 84 96 Command::new("logs") 85 97 .arg( ··· 90 102 ) 91 103 .about("View the logs of the Firecracker MicroVM"), 92 104 ) 93 - .subcommand(Command::new("ssh").about("SSH into the Firecracker MicroVM")) 105 + .subcommand( 106 + Command::new("ssh") 107 + .arg(arg!([name] "Name of the Firecracker MicroVM to SSH into")) 108 + .about("SSH into the Firecracker MicroVM"), 109 + ) 94 110 .subcommand( 95 111 Command::new("reset") 96 - .arg( 97 - Arg::new("api-socket") 98 - .long("api-socket") 99 - .value_name("path") 100 - .default_value(FIRECRACKER_SOCKET) 101 - .help("Path to the Firecracker API socket"), 102 - ) 112 + .arg(arg!([name] "Name of the Firecracker MicroVM to reset").required(false)) 103 113 .about("Reset the Firecracker MicroVM"), 104 114 ) 105 115 .arg(arg!(--debian "Prepare Debian MicroVM").default_value("false")) ··· 111 121 .arg(arg!(--vmlinux <path> "Path to the kernel image")) 112 122 .arg(arg!(--rootfs <path> "Path to the root filesystem image")) 113 123 .arg(arg!(--bridge <name> "Name of the bridge interface").default_value(BRIDGE_DEV)) 114 - .arg(arg!(--tap <name> "Name of the tap interface").default_value(TAP_DEV)) 124 + .arg(arg!(--tap <name> "Name of the tap interface").default_value("")) 115 125 .arg( 116 126 Arg::new("mac-address") 117 127 .long("mac-address") 118 128 .value_name("MAC") 119 - .default_value(FC_MAC) 120 129 .help("MAC address for the network interface"), 121 130 ) 122 131 .arg( 123 132 Arg::new("api-socket") 124 133 .long("api-socket") 125 134 .value_name("path") 126 - .default_value(FIRECRACKER_SOCKET) 127 135 .help("Path to the Firecracker API socket"), 128 136 ) 129 137 .arg( ··· 134 142 ) 135 143 } 136 144 137 - fn main() -> Result<()> { 145 + #[tokio::main] 146 + async fn main() -> Result<()> { 138 147 let matches = cli().get_matches(); 139 148 149 + let pool = firecracker_state::create_connection_pool().await?; 150 + let vm_name = names::Generator::default().next().unwrap(); 151 + let default_socket = format!("/tmp/firecracker-{}.sock", vm_name); 152 + let default_mac = generate_unique_mac(); 153 + 140 154 match matches.subcommand() { 141 155 Some(("init", _)) => init()?, 156 + Some(("ps", args)) => { 157 + let all = args.get_one::<bool>("all").copied().unwrap_or(false); 158 + list_all_instances(all).await?; 159 + } 160 + Some(("stop", args)) => { 161 + let name = args.get_one::<String>("name").cloned().unwrap(); 162 + stop(&name).await?; 163 + } 164 + Some(("start", args)) => { 165 + let name = args.get_one::<String>("name").cloned().unwrap(); 166 + start(&name).await?; 167 + } 168 + Some(("restart", args)) => { 169 + let name = args.get_one::<String>("name").cloned().unwrap(); 170 + stop(&name).await?; 171 + start(&name).await?; 172 + } 142 173 Some(("up", args)) => { 143 174 let vcpu = matches 144 175 .get_one::<String>("vcpu") ··· 153 184 let bootargs = matches.get_one::<String>("boot-args").cloned(); 154 185 let bridge = args.get_one::<String>("bridge").cloned().unwrap(); 155 186 let tap = args.get_one::<String>("tap").cloned().unwrap(); 156 - let api_socket = args.get_one::<String>("api-socket").cloned().unwrap(); 157 - let mac_address = args.get_one::<String>("mac-address").cloned().unwrap(); 187 + let api_socket = args 188 + .get_one::<String>("api-socket") 189 + .cloned() 190 + .unwrap_or(default_socket); 191 + let mac_address = args 192 + .get_one::<String>("mac-address") 193 + .cloned() 194 + .unwrap_or(default_mac); 158 195 let options = VmOptions { 159 196 debian: args.get_one::<bool>("debian").copied(), 160 197 alpine: args.get_one::<bool>("alpine").copied(), ··· 170 207 api_socket, 171 208 mac_address, 172 209 }; 173 - up(options)? 210 + up(options).await? 174 211 } 175 - Some(("down", args)) => { 176 - let api_socket = args.get_one::<String>("api-socket").cloned().unwrap(); 177 - down(&VmOptions { 178 - api_socket, 179 - ..Default::default() 180 - })? 212 + Some(("down", _)) => down().await?, 213 + Some(("status", args)) => { 214 + let name = args.get_one::<String>("name").cloned(); 215 + status(name).await?; 181 216 } 182 - Some(("status", _)) => status()?, 183 217 Some(("logs", args)) => { 184 218 let follow = args.get_one::<bool>("follow").copied().unwrap_or(false); 185 219 logs(follow)?; 186 220 } 187 - Some(("ssh", _)) => ssh()?, 221 + Some(("ssh", args)) => { 222 + let name = args.get_one::<String>("name").cloned(); 223 + ssh(pool, name).await? 224 + } 188 225 Some(("reset", args)) => { 189 - let api_socket = args.get_one::<String>("api-socket").cloned().unwrap(); 226 + let name = args.get_one::<String>("name").cloned().unwrap(); 227 + let api_socket = format!("/tmp/firecracker-{}.sock", name); 190 228 reset(VmOptions { 191 229 api_socket, 192 230 ..Default::default() 193 - })? 231 + }) 232 + .await? 194 233 } 195 234 _ => { 196 235 let debian = matches.get_one::<bool>("debian").copied().unwrap_or(false); ··· 210 249 let bootargs = matches.get_one::<String>("boot-args").cloned(); 211 250 let bridge = matches.get_one::<String>("bridge").cloned().unwrap(); 212 251 let tap = matches.get_one::<String>("tap").cloned().unwrap(); 213 - let api_socket = matches.get_one::<String>("api-socket").cloned().unwrap(); 214 - let mac_address = matches.get_one::<String>("mac-address").cloned().unwrap(); 252 + let api_socket = matches 253 + .get_one::<String>("api-socket") 254 + .cloned() 255 + .unwrap_or(default_socket); 256 + let mac_address = matches 257 + .get_one::<String>("mac-address") 258 + .cloned() 259 + .unwrap_or(default_mac); 215 260 216 261 let options = VmOptions { 217 262 debian: Some(debian), ··· 228 273 api_socket, 229 274 mac_address, 230 275 }; 231 - up(options)? 276 + up(options).await? 232 277 } 233 278 } 234 279
+5
crates/firecracker-vm/Cargo.toml
··· 8 8 9 9 [dependencies] 10 10 firecracker-prepare = { path = "../firecracker-prepare" } 11 + firecracker-state = { path = "../firecracker-state" } 11 12 fire-config = { path = "../fire-config" } 12 13 anyhow = "1.0.98" 13 14 dirs = "6.0.0" ··· 16 17 num_cpus = "1.17.0" 17 18 owo-colors = "4.2.2" 18 19 serde_json = "1.0.141" 20 + rand = "0.8" 21 + names = "0.14.0" 22 + rumqttc = "0.25.0" 23 + tokio = { version = "1.47.1", features = ["full"] }
-1
crates/firecracker-vm/src/constants.rs
··· 1 - pub const TAP_DEV: &str = "tap0"; 2 1 pub const BRIDGE_DEV: &str = "br0"; 3 2 pub const FIRECRACKER_SOCKET: &str = "/tmp/firecracker.sock"; 4 3 pub const BRIDGE_IP: &str = "172.16.0.1";
+138
crates/firecracker-vm/src/coredns.rs
··· 1 + use std::{process, thread}; 2 + 3 + use anyhow::{Context, Error}; 4 + use firecracker_state::repo; 5 + 6 + use crate::{command::run_command, mqttc, types::VmOptions}; 7 + 8 + pub const COREDNS_CONFIG_PATH: &str = "/etc/coredns/Corefile"; 9 + pub const COREDNS_SERVICE_TEMPLATE: &str = include_str!("./systemd/coredns.service"); 10 + 11 + pub fn setup_coredns(config: &VmOptions) -> Result<(), Error> { 12 + let api_socket = config.api_socket.clone(); 13 + thread::spawn(move || { 14 + let runtime = tokio::runtime::Runtime::new().unwrap(); 15 + match runtime.block_on(async { 16 + println!("[+] Checking if CoreDNS is installed..."); 17 + if !coredns_is_installed()? { 18 + // TODO: install it automatically 19 + println!("[✗] CoreDNS is not installed. Please install it first to /usr/sbin."); 20 + process::exit(1); 21 + } 22 + 23 + let message = mqttc::wait_for_mqtt_message("REQUEST").await?; 24 + let ip_addr = message 25 + .split_whitespace() 26 + .nth(2) 27 + .ok_or_else(|| anyhow::anyhow!("Failed to extract IP address from MQTT message"))?; 28 + 29 + let name = api_socket 30 + .split('/') 31 + .last() 32 + .ok_or_else(|| anyhow::anyhow!("Failed to extract VM name from API socket path"))? 33 + .replace("firecracker-", "") 34 + .replace(".sock", ""); 35 + 36 + std::fs::write(format!("/tmp/firecracker-{}.ip", name), ip_addr) 37 + .with_context(|| "Failed to write IP address to file")?; 38 + 39 + let pool = firecracker_state::create_connection_pool().await?; 40 + let vms = repo::virtual_machine::all(&pool).await?; 41 + let mut hosts = vms 42 + .into_iter() 43 + .filter(|vm| vm.ip_address.is_some() && vm.name != name) 44 + .map(|vm| format!("{} {}.firecracker", vm.ip_address.unwrap(), vm.name)) 45 + .collect::<Vec<String>>(); 46 + 47 + hosts.extend(vec![format!("{} {}.firecracker", ip_addr, name)]); 48 + 49 + let hosts = hosts.join("\n "); 50 + 51 + let coredns_config: &str = &format!( 52 + r#" 53 + firecracker:53 {{ 54 + hosts {{ 55 + 172.16.0.1 br.firecracker 56 + {} 57 + fallthrough 58 + }} 59 + 60 + loadbalance 61 + }} 62 + 63 + ts.net:53 {{ 64 + # Forward non-internal queries (e.g., to Tailscale DNS) 65 + forward . 100.100.100.100 66 + # Log and errors for debugging 67 + log 68 + errors 69 + health 70 + }} 71 + 72 + .:53 {{ 73 + # Forward non-internal queries (e.g., to Google DNS) 74 + forward . 8.8.8.8 8.8.4.4 1.1.1.1 1.0.0.1 {{ 75 + max_fails 3 76 + expire 10s 77 + health_check 5s 78 + policy round_robin 79 + except ts.net 80 + }} 81 + # Log and errors for debugging 82 + log 83 + errors 84 + health 85 + }} 86 + "#, 87 + hosts 88 + ); 89 + 90 + run_command( 91 + "sh", 92 + &[ 93 + "-c", 94 + &format!("echo '{}' > {}", coredns_config, COREDNS_CONFIG_PATH), 95 + ], 96 + true, 97 + )?; 98 + 99 + run_command( 100 + "sh", 101 + &[ 102 + "-c", 103 + &format!( 104 + "echo '{}' > /etc/systemd/system/coredns.service", 105 + COREDNS_SERVICE_TEMPLATE 106 + ), 107 + ], 108 + true, 109 + )?; 110 + restart_coredns()?; 111 + 112 + Ok::<(), Error>(()) 113 + }) { 114 + Ok(_) => {} 115 + Err(e) => { 116 + eprintln!("[✗] Error setting up CoreDNS: {}", e); 117 + process::exit(1); 118 + } 119 + } 120 + Ok::<(), Error>(()) 121 + }); 122 + 123 + Ok(()) 124 + } 125 + 126 + pub fn restart_coredns() -> Result<(), Error> { 127 + println!("[+] Starting CoreDNS..."); 128 + run_command("systemctl", &["enable", "coredns"], true)?; 129 + run_command("systemctl", &["daemon-reload"], true)?; 130 + run_command("systemctl", &["restart", "coredns"], true)?; 131 + println!("[✓] CoreDNS started successfully."); 132 + Ok(()) 133 + } 134 + 135 + pub fn coredns_is_installed() -> Result<bool, Error> { 136 + let output = run_command("which", &["coredns"], false)?; 137 + Ok(output.status.success()) 138 + }
-64
crates/firecracker-vm/src/dnsmasq.rs
··· 1 - use std::process; 2 - 3 - use anyhow::Error; 4 - 5 - use crate::{command::run_command, constants::BRIDGE_IP, types::VmOptions}; 6 - 7 - pub const DNSMASQ_CONFIG_PATH: &str = "/etc/dnsmasq.d/firecracker.conf"; 8 - 9 - pub fn setup_dnsmasq(config: &VmOptions) -> Result<(), Error> { 10 - println!("[+] Checking if DNSMasq is installed..."); 11 - if !dnsmasq_is_installed()? { 12 - println!("[✗] DNSMasq is not installed. Please install it first."); 13 - process::exit(1); 14 - } 15 - 16 - if std::path::Path::new(DNSMASQ_CONFIG_PATH).exists() { 17 - println!("[✓] DNSMasq configuration already exists. Skipping setup."); 18 - return Ok(()); 19 - } 20 - println!("[+] Setting up DNSMasq configuration..."); 21 - run_command("mkdir", &["-p", "/etc/dnsmasq.d"], true)?; 22 - 23 - let dnsmasq_config: &str = &format!( 24 - r#" 25 - interface={} 26 - bind-interfaces 27 - domain=firecracker.local 28 - dhcp-option=option:router,{} 29 - dhcp-option=option:dns-server,{} 30 - dhcp-range=172.16.0.2,172.16.0.150,12h 31 - dhcp-host={},vm0 32 - server=8.8.8.8 33 - server=8.8.4.4 34 - server=1.1.1.1 35 - "#, 36 - &config.bridge, BRIDGE_IP, BRIDGE_IP, &config.mac_address 37 - ); 38 - 39 - run_command( 40 - "sh", 41 - &[ 42 - "-c", 43 - &format!("echo '{}' > {}", dnsmasq_config, DNSMASQ_CONFIG_PATH), 44 - ], 45 - true, 46 - )?; 47 - 48 - restart_dnsmasq()?; 49 - 50 - Ok(()) 51 - } 52 - 53 - pub fn restart_dnsmasq() -> Result<(), Error> { 54 - println!("[+] Starting DNSMasq..."); 55 - run_command("systemctl", &["enable", "dnsmasq"], true)?; 56 - run_command("systemctl", &["restart", "dnsmasq"], true)?; 57 - println!("[✓] DNSMasq started successfully."); 58 - Ok(()) 59 - } 60 - 61 - pub fn dnsmasq_is_installed() -> Result<bool, Error> { 62 - let output = run_command("which", &["dnsmasq"], false)?; 63 - Ok(output.status.success()) 64 - }
+7 -2
crates/firecracker-vm/src/firecracker.rs
··· 58 58 Ok(()) 59 59 } 60 60 61 - fn setup_boot_source(kernel: &str, arch: &str, is_nixos: bool, options: &VmOptions) -> Result<()> { 61 + fn setup_boot_source( 62 + kernel: &str, 63 + arch: &str, 64 + is_nixos: bool, 65 + options: &VmOptions, 66 + ) -> Result<String> { 62 67 println!("[+] Setting boot source..."); 63 68 let mut boot_args = "console=ttyS0 reboot=k panic=1 pci=off ip=dhcp".to_string(); 64 69 if arch == "aarch64" { ··· 95 100 ], 96 101 true, 97 102 )?; 98 - Ok(()) 103 + Ok(boot_args) 99 104 } 100 105 101 106 fn setup_rootfs(rootfs: &str, options: &VmOptions) -> Result<()> {
+3 -6
crates/firecracker-vm/src/guest.rs
··· 1 - use crate::{ 2 - command::run_command, 3 - constants::{BRIDGE_IP, GUEST_IP}, 4 - }; 1 + use crate::{command::run_command, constants::BRIDGE_IP}; 5 2 use anyhow::Result; 6 3 7 - pub fn configure_guest_network(key_name: &str) -> Result<()> { 4 + pub fn configure_guest_network(key_name: &str, guest_ip: &str) -> Result<()> { 8 5 println!("[+] Configuring network in guest..."); 9 6 const MAX_RETRIES: u32 = 20; 10 7 let mut retries = 0; ··· 16 13 key_name, 17 14 "-o", 18 15 "StrictHostKeyChecking=no", 19 - &format!("root@{}", GUEST_IP), 16 + &format!("root@{}", guest_ip), 20 17 &format!("echo 'nameserver {}' > /etc/resolv.conf", BRIDGE_IP), 21 18 ], 22 19 false,
+115 -5
crates/firecracker-vm/src/lib.rs
··· 1 1 use anyhow::{anyhow, Context, Result}; 2 2 use firecracker_prepare::Distro; 3 + use firecracker_state::{entity::virtual_machine::VirtualMachine, repo}; 3 4 use owo_colors::OwoColorize; 4 5 use std::fs; 5 6 ··· 8 9 mod command; 9 10 mod config; 10 11 pub mod constants; 11 - mod dnsmasq; 12 + mod coredns; 12 13 mod firecracker; 13 14 mod guest; 15 + pub mod mac; 16 + mod mosquitto; 17 + mod mqttc; 14 18 mod network; 19 + mod nextdhcp; 15 20 pub mod types; 16 21 17 - pub fn setup(options: &VmOptions) -> Result<()> { 22 + pub async fn setup(options: &VmOptions, pid: u32, vm_id: Option<String>) -> Result<()> { 18 23 let distro: Distro = options.clone().into(); 19 24 let app_dir = get_config_dir().with_context(|| "Failed to get configuration directory")?; 20 25 21 - let logfile = format!("{}/firecracker.log", app_dir); 26 + let name = options 27 + .api_socket 28 + .split('/') 29 + .last() 30 + .ok_or_else(|| anyhow!("Failed to extract VM name from API socket path"))? 31 + .replace("firecracker-", "") 32 + .replace(".sock", "") 33 + .to_string(); 34 + let name = match name.is_empty() { 35 + true => names::Generator::default().next().unwrap(), 36 + false => name, 37 + }; 38 + 39 + fs::create_dir_all(format!("{}/logs", app_dir)) 40 + .with_context(|| format!("Failed to create logs directory: {}", app_dir))?; 41 + 42 + let logfile = format!("{}/logs/firecracker-{}.log", app_dir, name); 22 43 fs::File::create(&logfile) 23 44 .with_context(|| format!("Failed to create log file: {}", logfile))?; 24 45 ··· 76 97 let arch = command::run_command("uname", &["-m"], false)?.stdout; 77 98 let arch = String::from_utf8_lossy(&arch).trim().to_string(); 78 99 network::setup_network(options)?; 100 + mosquitto::setup_mosquitto(options)?; 101 + coredns::setup_coredns(options)?; 102 + nextdhcp::setup_nextdhcp(options)?; 79 103 80 104 firecracker::configure(&logfile, &kernel, &rootfs, &arch, &options, distro)?; 81 105 82 106 if distro != Distro::NixOS { 83 - guest::configure_guest_network(&key_name)?; 107 + let guest_ip = format!("{}.firecracker", name); 108 + guest::configure_guest_network(&key_name, &guest_ip)?; 109 + } 110 + let pool = firecracker_state::create_connection_pool().await?; 111 + let distro = match distro { 112 + Distro::Debian => "debian".into(), 113 + Distro::Alpine => "alpine".into(), 114 + Distro::NixOS => "nixos".into(), 115 + Distro::Ubuntu => "ubuntu".into(), 116 + }; 117 + 118 + let ip_file = format!("/tmp/firecracker-{}.ip", name); 119 + 120 + // loop until the IP file is created 121 + let mut attempts = 0; 122 + while attempts < 30 { 123 + println!("[*] Waiting for VM to obtain an IP address..."); 124 + if fs::metadata(&ip_file).is_ok() { 125 + break; 126 + } 127 + std::thread::sleep(std::time::Duration::from_millis(500)); 128 + attempts += 1; 129 + } 130 + 131 + let ip_addr = fs::read_to_string(&ip_file) 132 + .with_context(|| format!("Failed to read IP address from file: {}", ip_file))? 133 + .trim() 134 + .to_string(); 135 + 136 + fs::remove_file(&ip_file) 137 + .with_context(|| format!("Failed to remove IP address file: {}", ip_file))?; 138 + 139 + let project_dir = match fs::metadata("fire.toml").is_ok() { 140 + true => Some(std::env::current_dir()?.display().to_string()), 141 + false => None, 142 + }; 143 + 144 + match vm_id { 145 + Some(id) => { 146 + repo::virtual_machine::update( 147 + &pool, 148 + &id, 149 + VirtualMachine { 150 + vcpu: options.vcpu, 151 + memory: options.memory, 152 + api_socket: options.api_socket.clone(), 153 + bridge: options.bridge.clone(), 154 + tap: options.tap.clone(), 155 + mac_address: options.mac_address.clone(), 156 + name: name.clone(), 157 + pid: Some(pid), 158 + distro, 159 + ip_address: Some(ip_addr.clone()), 160 + status: "RUNNING".into(), 161 + project_dir, 162 + vmlinux: Some(kernel), 163 + rootfs: Some(rootfs), 164 + bootargs: options.bootargs.clone(), 165 + ..Default::default() 166 + }, 167 + ) 168 + .await?; 169 + } 170 + None => { 171 + repo::virtual_machine::create( 172 + &pool, 173 + VirtualMachine { 174 + vcpu: options.vcpu, 175 + memory: options.memory, 176 + api_socket: options.api_socket.clone(), 177 + bridge: options.bridge.clone(), 178 + tap: options.tap.clone(), 179 + mac_address: options.mac_address.clone(), 180 + name: name.clone(), 181 + pid: Some(pid), 182 + distro, 183 + ip_address: Some(ip_addr.clone()), 184 + status: "RUNNING".into(), 185 + project_dir, 186 + vmlinux: Some(kernel), 187 + rootfs: Some(rootfs), 188 + bootargs: options.bootargs.clone(), 189 + ..Default::default() 190 + }, 191 + ) 192 + .await?; 193 + } 84 194 } 85 195 86 196 println!("[✓] MicroVM booted and network is configured 🎉"); 87 197 88 198 println!("SSH into the VM using the following command:"); 89 - println!("{}", "fireup ssh".bright_green()); 199 + println!("{} {}", "fireup ssh".bright_green(), name.bright_green()); 90 200 91 201 Ok(()) 92 202 }
+45
crates/firecracker-vm/src/mac.rs
··· 1 + use rand::Rng; 2 + 3 + pub fn generate_unique_mac() -> String { 4 + let mut rng = rand::thread_rng(); 5 + 6 + // First byte must have the least significant bit set to 0 (unicast) 7 + // and the second least significant bit set to 0 (globally unique) 8 + let first_byte = (rng.gen::<u8>() & 0xFC) | 0x02; // Set locally administered bit 9 + 10 + // Generate the remaining 5 bytes 11 + let mut mac_bytes = [0u8; 6]; 12 + mac_bytes[0] = first_byte; 13 + for i in 1..6 { 14 + mac_bytes[i] = rng.gen::<u8>(); 15 + } 16 + 17 + // Format as a MAC address (XX:XX:XX:XX:XX:XX) 18 + format!( 19 + "{:02X}:{:02X}:{:02X}:{:02X}:{:02X}:{:02X}", 20 + mac_bytes[0], mac_bytes[1], mac_bytes[2], mac_bytes[3], mac_bytes[4], mac_bytes[5] 21 + ) 22 + } 23 + 24 + #[cfg(test)] 25 + mod tests { 26 + use super::*; 27 + 28 + #[test] 29 + fn test_generate_unique_mac() { 30 + let mac1 = generate_unique_mac(); 31 + let mac2 = generate_unique_mac(); 32 + 33 + // Check format (6 pairs of 2 hex digits separated by colons) 34 + assert!(mac1.chars().count() == 17); 35 + assert!(mac1.split(':').count() == 6); 36 + 37 + // Check that the MAC is locally administered (second bit of first byte is 1) 38 + let first_byte = u8::from_str_radix(&mac1[0..2], 16).unwrap(); 39 + assert_eq!(first_byte & 0x02, 0x02); 40 + assert_eq!(first_byte & 0x01, 0x00); // Unicast 41 + 42 + // Check uniqueness 43 + assert_ne!(mac1, mac2); 44 + } 45 + }
+31
crates/firecracker-vm/src/mosquitto.rs
··· 1 + use anyhow::Error; 2 + 3 + use crate::{command::run_command, types::VmOptions}; 4 + 5 + pub fn setup_mosquitto(_config: &VmOptions) -> Result<(), Error> { 6 + println!("[+] Checking if Mosquitto is installed..."); 7 + if !mosquitto_is_installed()? { 8 + run_command( 9 + "apt-get", 10 + &["install", "-y", "mosquitto", "mosquitto-clients"], 11 + true, 12 + )?; 13 + } 14 + 15 + restart_mosquitto()?; 16 + println!("[✓] Mosquitto is set up successfully."); 17 + Ok(()) 18 + } 19 + 20 + pub fn restart_mosquitto() -> Result<(), Error> { 21 + println!("[+] Starting mosquitto..."); 22 + run_command("systemctl", &["enable", "mosquitto"], true)?; 23 + run_command("systemctl", &["restart", "mosquitto"], true)?; 24 + println!("[✓] Mosquitto started successfully."); 25 + Ok(()) 26 + } 27 + 28 + pub fn mosquitto_is_installed() -> Result<bool, Error> { 29 + let output = run_command("which", &["mosquitto"], false)?; 30 + Ok(output.status.success()) 31 + }
+39
crates/firecracker-vm/src/mqttc.rs
··· 1 + use std::time::Duration; 2 + 3 + use anyhow::Error; 4 + use rumqttc::{AsyncClient, MqttOptions, QoS}; 5 + 6 + use crate::command::run_command; 7 + 8 + pub async fn wait_for_mqtt_message(msgtype: &str) -> Result<String, Error> { 9 + println!("[+] Waiting for MQTT message..."); 10 + let mut mqttoptions = MqttOptions::new("fireup", "localhost", 1883); 11 + mqttoptions.set_keep_alive(Duration::from_secs(5)); 12 + 13 + let (client, mut eventloop) = AsyncClient::new(mqttoptions, 10); 14 + client.subscribe("/dhcp/#", QoS::AtMostOnce).await?; 15 + 16 + while let Ok(notification) = eventloop.poll().await { 17 + if let rumqttc::Event::Incoming(rumqttc::Packet::Publish(publish)) = notification { 18 + let payload_str = String::from_utf8_lossy(&publish.payload).to_string(); 19 + println!("[+] Received MQTT message: {}", payload_str); 20 + if payload_str.starts_with(msgtype) { 21 + let ip_addr = payload_str.split_whitespace().nth(2).ok_or_else(|| { 22 + anyhow::anyhow!("Failed to extract IP address from MQTT message") 23 + })?; 24 + 25 + if !ip_addr.is_empty() { 26 + println!("[+] Pinging IP address: {}", ip_addr); 27 + if run_command("sh", &["-c", &format!("ping -c 1 {}", ip_addr)], false).is_ok() 28 + { 29 + println!("[+] IP address {} is reachable.", ip_addr); 30 + return Ok(payload_str); 31 + } 32 + println!("[-] IP address {} is not reachable yet.", ip_addr); 33 + } 34 + } 35 + } 36 + } 37 + 38 + Err(Error::msg("Failed to receive MQTT message")) 39 + }
+20 -18
crates/firecracker-vm/src/network.rs
··· 1 1 use crate::{ 2 2 constants::{BRIDGE_IP, MASK_SHORT}, 3 - dnsmasq::setup_dnsmasq, 4 3 types::VmOptions, 5 4 }; 6 5 use anyhow::{anyhow, Context, Result}; ··· 20 19 .unwrap_or(false) 21 20 } 22 21 22 + fn create_new_tap(config: &VmOptions) -> Result<()> { 23 + run_command( 24 + "ip", 25 + &["tuntap", "add", "dev", &config.tap, "mode", "tap"], 26 + true, 27 + )?; 28 + run_command("ip", &["link", "set", "dev", &config.tap, "up"], true)?; 29 + run_command( 30 + "ip", 31 + &["link", "set", &config.tap, "master", &config.bridge], 32 + true, 33 + )?; 34 + Ok(()) 35 + } 36 + 23 37 pub fn setup_network(config: &VmOptions) -> Result<()> { 24 38 if check_tap_exists(config) { 25 39 run_command("ip", &["addr", "flush", "dev", &config.tap], true)?; ··· 30 44 return Ok(()); 31 45 } 32 46 33 - if !check_tap_exists(config) { 34 - println!("[+] Configuring {}...", &config.tap); 35 - run_command( 36 - "ip", 37 - &["tuntap", "add", "dev", &config.tap, "mode", "tap"], 38 - true, 39 - )?; 40 - run_command("ip", &["link", "set", "dev", &config.tap, "up"], true)?; 41 - } 42 - 43 47 if !check_bridge_exists(config) { 44 48 println!("[+] Configuring {}...", config.bridge); 45 49 run_command( ··· 50 54 run_command("ip", &["link", "set", &config.bridge, "up"], true)?; 51 55 run_command( 52 56 "ip", 53 - &["link", "set", &config.tap, "master", &config.bridge], 54 - true, 55 - )?; 56 - run_command( 57 - "ip", 58 57 &[ 59 58 "addr", 60 59 "add", ··· 64 63 ], 65 64 true, 66 65 )?; 66 + } 67 + 68 + if !check_tap_exists(config) { 69 + println!("[+] Configuring {}...", &config.tap); 70 + create_new_tap(config)?; 67 71 } 68 72 69 73 let ip_forward = run_command("cat", &["/proc/sys/net/ipv4/ip_forward"], false)?.stdout; ··· 116 120 } 117 121 118 122 run_command("iptables", &["-P", "FORWARD", "ACCEPT"], true)?; 119 - 120 - setup_dnsmasq(config)?; 121 123 122 124 Ok(()) 123 125 }
+79
crates/firecracker-vm/src/nextdhcp.rs
··· 1 + use std::process; 2 + 3 + use anyhow::Error; 4 + 5 + use crate::{command::run_command, types::VmOptions}; 6 + 7 + pub const NEXTDHCP_CONFIG_PATH: &str = "/etc/nextdhcp/Dhcpfile"; 8 + pub const NEXTDHCP_SERVICE_TEMPLATE: &str = include_str!("./systemd/nextdhcp.service"); 9 + 10 + pub fn setup_nextdhcp(_config: &VmOptions) -> Result<(), Error> { 11 + println!("[+] Checking if NextDHCP is installed..."); 12 + if !nextdhcp_is_installed()? { 13 + // TODO: install it automatically 14 + println!("[✗] NextDHCP is not installed. Please install it first to /usr/sbin."); 15 + process::exit(1); 16 + } 17 + 18 + let nextdhcp_config: &str = r#" 19 + 172.16.0.1/24 { 20 + lease 1h 21 + 22 + range 172.16.0.2 172.16.0.150 23 + 24 + mqtt { 25 + name default 26 + broker tcp://localhost:1883 27 + 28 + topic /dhcp/hwaddr/{hwaddr} 29 + payload "{msgtype} {hwaddr} {requestedip} {state}" 30 + qos 1 31 + } 32 + 33 + option { 34 + router 172.16.0.1 35 + nameserver 172.16.0.1 36 + } 37 + } 38 + "#; 39 + 40 + run_command( 41 + "sh", 42 + &[ 43 + "-c", 44 + &format!("echo '{}' > {}", nextdhcp_config, NEXTDHCP_CONFIG_PATH), 45 + ], 46 + true, 47 + )?; 48 + 49 + run_command( 50 + "sh", 51 + &[ 52 + "-c", 53 + &format!( 54 + "echo '{}' > /etc/systemd/system/nextdhcp.service", 55 + NEXTDHCP_SERVICE_TEMPLATE 56 + ), 57 + ], 58 + true, 59 + )?; 60 + restart_nextdhcp()?; 61 + 62 + Ok(()) 63 + } 64 + 65 + pub fn restart_nextdhcp() -> Result<(), Error> { 66 + println!("[+] Starting nextdhcp..."); 67 + 68 + run_command("systemctl", &["enable", "nextdhcp"], true)?; 69 + run_command("systemctl", &["daemon-reload"], true)?; 70 + run_command("systemctl", &["stop", "nextdhcp"], true)?; 71 + run_command("systemctl", &["start", "nextdhcp"], true)?; 72 + println!("[✓] Nextdhcp started successfully."); 73 + Ok(()) 74 + } 75 + 76 + pub fn nextdhcp_is_installed() -> Result<bool, Error> { 77 + let output = run_command("which", &["nextdhcp"], false)?; 78 + Ok(output.status.success()) 79 + }
+18
crates/firecracker-vm/src/systemd/coredns.service
··· 1 + [Unit] 2 + Description=CoreDNS DNS server 3 + Documentation=https://coredns.io 4 + After=network.target 5 + 6 + [Service] 7 + ExecStart=/usr/sbin/coredns -conf /etc/coredns/Corefile 8 + Restart=on-failure 9 + RestartSec=5 10 + LimitNOFILE=1048576 11 + LimitNPROC=512 12 + ProtectSystem=strict 13 + ReadWritePaths=/etc/coredns 14 + NoNewPrivileges=true 15 + AmbientCapabilities=CAP_NET_BIND_SERVICE 16 + 17 + [Install] 18 + WantedBy=multi-user.target
+18
crates/firecracker-vm/src/systemd/nextdhcp.service
··· 1 + [Unit] 2 + Description=NextDHCP Service 3 + After=network.target systemd-tmpfiles-setup.service 4 + 5 + [Service] 6 + ExecStart=/usr/sbin/nextdhcp -conf /etc/nextdhcp/Dhcpfile 7 + Restart=on-failure 8 + RestartSec=5 9 + LimitNOFILE=65535 10 + LimitNPROC=512 11 + ProtectSystem=strict 12 + ReadWritePaths=/etc/nextdhcp 13 + NoNewPrivileges=true 14 + AmbientCapabilities=CAP_NET_ADMIN CAP_NET_RAW CAP_NET_BIND_SERVICE 15 + WorkingDirectory=/etc/nextdhcp 16 + 17 + [Install] 18 + WantedBy=multi-user.target
+2 -2
crates/firecracker-vm/src/types.rs
··· 1 1 use fire_config::FireConfig; 2 2 use firecracker_prepare::Distro; 3 3 4 - use crate::constants::{BRIDGE_DEV, FC_MAC, FIRECRACKER_SOCKET, TAP_DEV}; 4 + use crate::constants::{BRIDGE_DEV, FC_MAC, FIRECRACKER_SOCKET}; 5 5 6 6 #[derive(Default, Clone)] 7 7 pub struct VmOptions { ··· 34 34 rootfs: vm.rootfs, 35 35 bootargs: vm.boot_args, 36 36 bridge: vm.bridge.unwrap_or(BRIDGE_DEV.into()), 37 - tap: vm.tap.unwrap_or(TAP_DEV.into()), 37 + tap: vm.tap.unwrap_or("".into()), 38 38 api_socket: vm.api_socket.unwrap_or(FIRECRACKER_SOCKET.into()), 39 39 mac_address: vm.mac.unwrap_or(FC_MAC.into()), 40 40 }