feat(firecracker): pull the infra rootfs as a prebuilt artifact (PRD 0069 Stage 2)
Stage 2 of the docker-free Firecracker backend (#348): stop building the fixed infra image on the launch host. The infra VM's rootfs is host- and bottle-agnostic (authorized_keys + guest IP ride the kernel cmdline, not the rootfs), so it's built once off-host and published as a versioned, ready-to- boot ext4; the launch host downloads + verifies + boots it — no Docker, no image tooling, just HTTP + gunzip. - infra_artifact.py: version = content hash of the rootfs inputs (the shipped bot_bottle package + the three Dockerfiles + the init), so a launch host pulls the artifact matching its code and a content change can't silently boot a stale rootfs. Pull + sha256-verify (fail-closed) + gunzip from a Gitea generic package; base/owner/token configurable, default this Gitea. - infra_vm.ensure_built/boot default to the pull path; BOT_BOTTLE_INFRA_BUILD= local keeps the docker build-from-source path for iterating on Dockerfiles. - publish_infra.py: the off-host half — builds the images with Docker, mke2fs the rootfs (with buildah slack), gzips, and PUTs it to the generic package. Rollout note: default=pull means a launch 404s until an artifact is published; until the Gitea packages endpoint is enabled + an artifact published, use BOT_BOTTLE_INFRA_BUILD=local. Freeze/migrate's remaining docker use is a separate PR. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01UoEZHDjv84ChoZbozQERhJ
This commit is contained in:
@@ -35,7 +35,7 @@ from typing import Generator
|
||||
from ...log import die, info
|
||||
from ..docker import util as docker_mod
|
||||
from ..docker.gateway_provision import GatewayProvisionError
|
||||
from . import firecracker_vm, netpool, util
|
||||
from . import firecracker_vm, infra_artifact, netpool, util
|
||||
|
||||
# The single infra-VM image: gateway data plane + baked control-plane source
|
||||
# (Dockerfile.infra FROM the gateway image). Built from source by default;
|
||||
@@ -109,10 +109,26 @@ class InfraVm:
|
||||
|
||||
|
||||
def ensure_built() -> None:
|
||||
"""Build the infra image from source (bootstrap via host docker). The
|
||||
infra image `COPY --from`s the orchestrator image and is `FROM` the
|
||||
gateway image, so both must exist first. A pull-from-registry mode
|
||||
replaces this later."""
|
||||
"""Ensure the infra rootfs is available before boot.
|
||||
|
||||
Default (docker-free, PRD 0069 Stage 2): download + verify the prebuilt
|
||||
rootfs artifact matching this code version (see `infra_artifact`); the
|
||||
launch host needs no Docker. `BOT_BOTTLE_INFRA_BUILD=local` instead builds
|
||||
the three fixed images from source with host Docker — the infra image
|
||||
`COPY --from`s the orchestrator image and is `FROM` the gateway image, so
|
||||
both must exist first — for iterating on the Dockerfiles."""
|
||||
if infra_artifact.local_build_requested():
|
||||
build_infra_images_with_docker()
|
||||
return
|
||||
infra_artifact.ensure_artifact_gz(
|
||||
infra_artifact.infra_artifact_version(_infra_init()))
|
||||
|
||||
|
||||
def build_infra_images_with_docker() -> None:
|
||||
"""Build the three fixed images from source with host Docker: orchestrator,
|
||||
gateway, then the combined infra image (`COPY --from` orchestrator, `FROM`
|
||||
gateway). The launch host uses this only in `BOT_BOTTLE_INFRA_BUILD=local`
|
||||
mode; `publish_infra` uses it off-host to produce the published artifact."""
|
||||
docker_mod.build_image(
|
||||
_ORCHESTRATOR_IMAGE, str(_REPO_ROOT), dockerfile="Dockerfile.orchestrator")
|
||||
docker_mod.build_image(
|
||||
@@ -190,10 +206,15 @@ def boot() -> InfraVm:
|
||||
die(f"orchestrator link {slot.iface} not present.\n"
|
||||
f" ./cli.py backend setup --backend=firecracker")
|
||||
|
||||
base = build_infra_rootfs_dir()
|
||||
run_dir = _infra_dir()
|
||||
rootfs = run_dir / "rootfs.ext4"
|
||||
util.build_rootfs_ext4(base, rootfs, slack_mib=8192)
|
||||
if infra_artifact.local_build_requested():
|
||||
util.build_rootfs_ext4(build_infra_rootfs_dir(), rootfs, slack_mib=8192)
|
||||
else:
|
||||
# Prebuilt artifact already carries the buildah build slack; expand it
|
||||
# to a fresh writable rootfs for this boot.
|
||||
infra_artifact.materialize_ext4(
|
||||
infra_artifact.infra_artifact_version(_infra_init()), rootfs)
|
||||
private_key, pubkey = _stable_keypair()
|
||||
|
||||
info(f"booting infra VM on {slot.iface} (guest {slot.guest_ip})")
|
||||
|
||||
Reference in New Issue
Block a user