feat(firecracker): portable systemd-unit install for the network pool
lint / lint (push) Failing after 2m5s
test / unit (pull_request) Successful in 1m5s
test / integration (pull_request) Successful in 22s
test / coverage (pull_request) Failing after 1m5s

Make the network pool a persistent, distro-uniform resource instead of a
non-persistent per-distro shell command. systemd is the common
denominator across Debian/Ubuntu/Fedora/RHEL/Arch/… (and NixOS), so
`backend setup` on any systemd host now installs one bot-bottle-owned
oneshot unit (bot-bottle-firecracker-netpool.service): params pinned via
Environment= (so it doesn't depend on $SUDO_USER at boot), ExecStart/Stop
delegating to the bundled bring-up script (single source of logic).

- render_systemd_unit() in netpool.py (derived from the same constants
  as the shell script + nix module).
- backend setup: install + enable the unit directly when run as root,
  else print a self-contained copy-paste block. NixOS keeps its
  declarative module (which produces the same-named unit); non-systemd
  hosts fall back to the raw imperative script.
- backend teardown: symmetric — disable + remove the unit.
- backend status: report the unit's active/inactive state so you can
  tell a persistent install from an imperative one.

Net: one install path (`backend setup`), persistent, identical across
distros; per-distro variance shrinks to installing nft + iproute2.

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 18:33:42 -04:00
parent 3d7c508dc4
commit a80356af75
3 changed files with 155 additions and 9 deletions
+15
View File
@@ -73,6 +73,21 @@ class TestNetpoolRenderers(unittest.TestCase):
self.assertIn("BOT_BOTTLE_FC_POOL_SIZE=3", out)
self.assertIn("firecracker-netpool.sh up", out)
def test_systemd_unit_pins_params_and_calls_script(self):
# The portable install: one oneshot unit, params pinned via
# Environment= (must not depend on $SUDO_USER at boot), delegating
# bring-up/teardown to the bundled script.
script = "/opt/bb/scripts/firecracker-netpool.sh"
with patch.dict(os.environ, {"BOT_BOTTLE_FC_POOL_SIZE": "4"}):
unit = netpool.render_systemd_unit("alice", script)
self.assertIn("Type=oneshot", unit)
self.assertIn("BOT_BOTTLE_FC_POOL_SIZE=4", unit)
self.assertIn("BOT_BOTTLE_FC_OWNER=alice", unit)
self.assertIn(f"BOT_BOTTLE_FC_IP_BASE={netpool.ip_base()}", unit)
self.assertIn(f"ExecStart={script} up", unit)
self.assertIn(f"ExecStop={script} down", unit)
self.assertIn("WantedBy=multi-user.target", unit)
class TestFirecrackerStatus(unittest.TestCase):
"""`status()` gates launch: ready == TAP pool present + no overlap.