refactor(firecracker): single-source the network-pool defaults
test / unit (pull_request) Successful in 54s
test / integration (pull_request) Successful in 15s
test / coverage (pull_request) Successful in 56s
lint / lint (push) Successful in 1m59s
test / unit (push) Successful in 53s
test / integration (push) Successful in 20s
test / coverage (push) Successful in 58s
Update Quality Badges / update-badges (push) Successful in 57s
test / unit (pull_request) Successful in 54s
test / integration (pull_request) Successful in 15s
test / coverage (pull_request) Successful in 56s
lint / lint (push) Successful in 1m59s
test / unit (push) Successful in 53s
test / integration (push) Successful in 20s
test / coverage (push) Successful in 58s
Update Quality Badges / update-badges (push) Successful in 57s
The pool params (size, IP base, iface prefix, nft table) were triplicated
— hardcoded in netpool.py, scripts/firecracker-netpool.sh, and
nix/firecracker-netpool.nix — plus the IP math (3x) and the nft ruleset
(2x). Nothing enforced agreement; changing the base (ce3fad9, off CGNAT)
forced a coordinated three-file edit, and a missed one would silently
provision a range the launcher doesn't expect.
Collapse to one source of truth:
* netpool.defaults.env — a plain KEY=VALUE file (bash-sourceable,
systemd EnvironmentFile-compatible, Python- and Nix-parseable) holding
the four defaults. A BOT_BOTTLE_FC_* env var still overrides any key.
* netpool.py reads it for the Python defaults (missing file = hard
error, not confusing empty defaults).
* the shell script falls back to it (no literal `:-8` / `10.243.0.0`),
and its `up` is now non-destructive/idempotent (only creates a
missing TAP), so re-running never cuts a live VM.
* the Nix module readFile-parses it for its option defaults and
delegates bring-up to the SAME shell script (dropping its duplicate
IP math, nft ruleset, and TAP loop) — passing every value as
Environment= so the store-detached script never needs the file.
Net: defaults 3x -> 1x, nft ruleset 2x -> 1x, TAP loop 2x -> 1x. The one
remaining IP-math dup (Python launch-addressing vs bash bring-up) is
justified — different runtimes. Tests now guard the invariant (Python
reads the shared file; the script/module hold no literals) instead of
pinning duplicated strings.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01WBMWTEtQdJ4W5UrWuLHCck
This commit was merged in pull request #350.
This commit is contained in:
@@ -33,24 +33,44 @@
|
||||
# sudo ./scripts/firecracker-netpool.sh down
|
||||
# ./scripts/firecracker-netpool.sh status
|
||||
#
|
||||
# Env overrides (must match the backend's util.py constants):
|
||||
# BOT_BOTTLE_FC_POOL_SIZE number of slots (default 8)
|
||||
# BOT_BOTTLE_FC_IP_BASE base IPv4 of the /31 pool (default 10.243.0.0)
|
||||
# BOT_BOTTLE_FC_IFACE_PREFIX TAP name prefix (default bbfc)
|
||||
# BOT_BOTTLE_FC_OWNER owning user (default $SUDO_USER or $USER)
|
||||
# BOT_BOTTLE_FC_GROUP owning group; if set, TAPs are group-owned
|
||||
# instead of user-owned, so any group member
|
||||
# (e.g. an interactive user + a CI runner
|
||||
# user) can open the pool. Overrides OWNER.
|
||||
# Pool params default to the shared single-source file
|
||||
# (bot_bottle/backend/firecracker/netpool.defaults.env); a matching
|
||||
# env var overrides its key:
|
||||
# BOT_BOTTLE_FC_POOL_SIZE number of slots
|
||||
# BOT_BOTTLE_FC_IP_BASE base IPv4 of the /31 pool
|
||||
# BOT_BOTTLE_FC_IFACE_PREFIX TAP name prefix
|
||||
# BOT_BOTTLE_FC_NFT_TABLE isolation table name
|
||||
# BOT_BOTTLE_FC_OWNER owning user (default $SUDO_USER or $USER)
|
||||
# BOT_BOTTLE_FC_GROUP owning group; if set, TAPs are group-owned
|
||||
# instead of user-owned, so any group member
|
||||
# (e.g. an interactive user + a CI runner
|
||||
# user) can open the pool. Overrides OWNER.
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
POOL_SIZE="${BOT_BOTTLE_FC_POOL_SIZE:-8}"
|
||||
IP_BASE="${BOT_BOTTLE_FC_IP_BASE:-10.243.0.0}"
|
||||
PREFIX="${BOT_BOTTLE_FC_IFACE_PREFIX:-bbfc}"
|
||||
# The single source of the pool defaults, shared with netpool.py and the
|
||||
# Nix module. The Nix path passes every value as env (the script runs
|
||||
# from the store, detached from this file), so this lookup only matters
|
||||
# on the direct/sudo path where the script sits in the repo tree.
|
||||
_SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
_DEFAULTS="$_SCRIPT_DIR/../bot_bottle/backend/firecracker/netpool.defaults.env"
|
||||
_default() { # value of KEY=... from the shared file; empty if unavailable
|
||||
[ -f "$_DEFAULTS" ] || return 0
|
||||
sed -n "s/^$1=//p" "$_DEFAULTS" | tail -1
|
||||
}
|
||||
|
||||
POOL_SIZE="${BOT_BOTTLE_FC_POOL_SIZE:-$(_default BOT_BOTTLE_FC_POOL_SIZE)}"
|
||||
IP_BASE="${BOT_BOTTLE_FC_IP_BASE:-$(_default BOT_BOTTLE_FC_IP_BASE)}"
|
||||
PREFIX="${BOT_BOTTLE_FC_IFACE_PREFIX:-$(_default BOT_BOTTLE_FC_IFACE_PREFIX)}"
|
||||
TABLE="${BOT_BOTTLE_FC_NFT_TABLE:-$(_default BOT_BOTTLE_FC_NFT_TABLE)}"
|
||||
OWNER="${BOT_BOTTLE_FC_OWNER:-${SUDO_USER:-$USER}}"
|
||||
GROUP="${BOT_BOTTLE_FC_GROUP:-}"
|
||||
TABLE="bot_bottle_fc"
|
||||
|
||||
# Fail loudly rather than provisioning a half/empty range if a value
|
||||
# resolved to nothing (env unset AND the shared file unreadable).
|
||||
for _v in POOL_SIZE IP_BASE PREFIX TABLE; do
|
||||
[ -n "${!_v}" ] || { echo "error: $_v unresolved (set BOT_BOTTLE_FC_* or fix $_DEFAULTS)" >&2; exit 1; }
|
||||
done
|
||||
|
||||
# Sidecar ports (must match the backend). egress=9099, supervise=9100,
|
||||
# git-http=9420. Reached by the VM at its host-side TAP IP.
|
||||
@@ -94,12 +114,13 @@ cmd_up() {
|
||||
for i in $(seq 0 $((POOL_SIZE-1))); do
|
||||
local dev host
|
||||
dev="$(iface "$i")" ; host="$(host_ip "$i")"
|
||||
if ip link show "$dev" >/dev/null 2>&1; then
|
||||
ip link set "$dev" down 2>/dev/null || true
|
||||
ip tuntap del dev "$dev" mode tap 2>/dev/null || true
|
||||
fi
|
||||
ip tuntap add dev "$dev" mode tap "${own_args[@]}"
|
||||
ip addr add "$host/31" dev "$dev"
|
||||
# Non-destructive + idempotent: only create a missing TAP (tearing
|
||||
# an existing one down would cut a running VM), and `addr replace`
|
||||
# is safe to re-run. Ownership is fixed at creation, so to change
|
||||
# owner/group run `down` then `up`.
|
||||
ip link show "$dev" >/dev/null 2>&1 \
|
||||
|| ip tuntap add dev "$dev" mode tap "${own_args[@]}"
|
||||
ip addr replace "$host/31" dev "$dev"
|
||||
ip link set "$dev" up
|
||||
echo " $dev host=$host guest=$(guest_ip "$i") $own_desc"
|
||||
done
|
||||
|
||||
Reference in New Issue
Block a user