feat(firecracker): show binary/KVM prerequisites in backend setup
lint / lint (push) Failing after 1m58s
test / unit (pull_request) Successful in 57s
test / integration (pull_request) Successful in 19s
test / coverage (pull_request) Failing after 1m6s

`backend setup --backend=firecracker` only covered the network pool. Lead
with the other prerequisites: the firecracker binary (with a release
install pointer when it's not on PATH, plus a NixOS note), a /dev/kvm
check, and a reminder about the cached guest kernel + static dropbear and
mke2fs. The network pool is now step 2.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01WBMWTEtQdJ4W5UrWuLHCck
This commit is contained in:
2026-07-11 17:03:04 -04:00
parent 656966c2c4
commit 949b001464
+40 -3
View File
@@ -14,16 +14,51 @@ generic `./cli.py backend {setup,status}` command dispatches to.
from __future__ import annotations from __future__ import annotations
import os import os
import shutil
import sys import sys
from pathlib import Path from pathlib import Path
from . import netpool from . import netpool
from . import util
_FC_RELEASES = "https://github.com/firecracker-microvm/firecracker/releases"
def _owner() -> str: def _owner() -> str:
return os.environ.get("USER", "youruser") return os.environ.get("USER", "youruser")
def _print_prereqs() -> None:
"""The firecracker binary + KVM + guest artifacts, shown before the
privileged network-pool step so operators see the full picture."""
fc = shutil.which("firecracker")
if fc:
sys.stderr.write(f"1) firecracker binary: found ({fc}).\n")
else:
sys.stderr.write(
"1) firecracker binary: NOT found on PATH. Install a release binary "
"and put it on PATH:\n"
f" {_FC_RELEASES}\n"
" e.g.: download firecracker-vX.Y.Z-$(uname -m).tgz, extract, and\n"
" install -m755 release-*/firecracker-* ~/.local/bin/firecracker\n"
" (NixOS: not packaged as a user binary — fetch the release, pin\n"
" the version, and add it to PATH.)\n"
)
if util.is_host_capable():
sys.stderr.write(" KVM: /dev/kvm present.\n")
else:
sys.stderr.write(
" KVM: /dev/kvm missing/unusable — load kvm-intel/kvm-amd, enable\n"
" virtualization in firmware, and add your user to the `kvm` group.\n"
)
sys.stderr.write(
" Guest artifacts: a kernel (BOT_BOTTLE_FC_KERNEL) and static dropbear\n"
" (BOT_BOTTLE_FC_DROPBEAR) must be cached, and `mke2fs` (e2fsprogs) is\n"
" needed to build the rootfs.\n\n"
)
def _is_nixos() -> bool: def _is_nixos() -> bool:
if Path("/etc/NIXOS").exists(): if Path("/etc/NIXOS").exists():
return True return True
@@ -50,11 +85,13 @@ def _warn_overlaps() -> None:
def setup() -> int: def setup() -> int:
sys.stderr.write("Firecracker backend — one-time host setup.\n\n")
_print_prereqs()
slots = netpool.all_slots() slots = netpool.all_slots()
sys.stderr.write( sys.stderr.write(
f"Firecracker network pool: {len(slots)} slots " f"2) network pool: {len(slots)} slots "
f"({slots[0].iface}..{slots[-1].iface}), base {netpool.ip_base()}.\n" f"({slots[0].iface}..{slots[-1].iface}), base {netpool.ip_base()}"
f"This is a one-time privileged setup (needs root once).\n\n" f"TAP devices + nft isolation table, privileged (needs root once).\n\n"
) )
_warn_overlaps() _warn_overlaps()
if _is_nixos(): if _is_nixos():