fix(supervise): single migrated DB for firecracker — orchestrator owns supervise tables
The firecracker supervise MCP daemon 500'd (-32603) on egress-allow/block: it ran with no BOT_BOTTLE_ROOT/SUPERVISE_DB_PATH, so it targeted a stray, unmigrated SQLite file and `write_proposal` hit "no such table: supervise_proposals". Meanwhile the in-VM control plane migrated only the registry table (orchestrator_bottles) into its own DB, and the host operator reads a third, disconnected DB — three files, none shared. Consolidate to one DB per host, owned by the control plane on the persisted registry volume (/var/lib/bot-bottle/db/bot-bottle.db): - orchestrator startup now migrates the supervise queue + audit tables into the same file it migrates the registry into (StoreManager), so the control-plane DB carries every table. - the in-VM supervise daemon is pointed at that same file via SUPERVISE_DB_PATH, so daemon and control plane share one queue. `list-egress-routes` already worked (no DB); egress-allow now queues + waits on the single persisted DB instead of erroring. Validated against a live infra VM: migrate + write_proposal succeeds and the proposal is queued. The host-operator HTTP bridge (so approvals complete from the host, unifying docker onto the same path) is the follow-up. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01WBMWTEtQdJ4W5UrWuLHCck
This commit is contained in:
@@ -411,6 +411,7 @@ BOT_BOTTLE_ROOT=/var/lib/bot-bottle python3 -m bot_bottle.orchestrator \\
|
|||||||
# entrypoint the consolidated model doesn't use) is left out.
|
# entrypoint the consolidated model doesn't use) is left out.
|
||||||
BOT_BOTTLE_GATEWAY_DAEMONS=egress,git-http,supervise \\
|
BOT_BOTTLE_GATEWAY_DAEMONS=egress,git-http,supervise \\
|
||||||
BOT_BOTTLE_ORCHESTRATOR_URL=http://127.0.0.1:{CONTROL_PLANE_PORT} \\
|
BOT_BOTTLE_ORCHESTRATOR_URL=http://127.0.0.1:{CONTROL_PLANE_PORT} \\
|
||||||
|
SUPERVISE_DB_PATH=/var/lib/bot-bottle/db/bot-bottle.db \\
|
||||||
python3 /app/gateway_init.py &
|
python3 /app/gateway_init.py &
|
||||||
|
|
||||||
# Reap as PID 1; children are backgrounded, so `wait` blocks.
|
# Reap as PID 1; children are backgrounded, so `wait` blocks.
|
||||||
|
|||||||
@@ -16,6 +16,7 @@ import secrets
|
|||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
|
||||||
from .. import log
|
from .. import log
|
||||||
|
from ..store_manager import StoreManager
|
||||||
from .broker import LaunchBroker, StubBroker
|
from .broker import LaunchBroker, StubBroker
|
||||||
from .control_plane import make_server
|
from .control_plane import make_server
|
||||||
from .docker_broker import DockerBroker
|
from .docker_broker import DockerBroker
|
||||||
@@ -45,6 +46,11 @@ def main(argv: list[str] | None = None) -> int:
|
|||||||
|
|
||||||
registry = RegistryStore(args.db)
|
registry = RegistryStore(args.db)
|
||||||
registry.migrate()
|
registry.migrate()
|
||||||
|
# One DB per host: the supervise queue + audit tables live in the SAME
|
||||||
|
# SQLite file the registry owns, so the control plane is the single
|
||||||
|
# source of truth. The in-VM supervise daemon writes here; the host
|
||||||
|
# operator reaches it over HTTP (never a second, disconnected DB).
|
||||||
|
StoreManager(registry.db_path).migrate()
|
||||||
|
|
||||||
# An ephemeral signing secret ties the orchestrator (signer) to its
|
# An ephemeral signing secret ties the orchestrator (signer) to its
|
||||||
# broker (verifier). 'stub' records launches instead of starting
|
# broker (verifier). 'stub' records launches instead of starting
|
||||||
|
|||||||
Reference in New Issue
Block a user