feat(firecracker): port freeze/migrate off host Docker (PRD 0069 / #397)
The last host-Docker dependency in the Firecracker launch path. Freeze and resume no longer touch the docker daemon, so the backend needs firecracker + KVM only — completing #348. Freeze: stream the guest rootfs over SSH straight into a persistent committed-rootfs.tar (the resumable/migratable artifact) instead of round-tripping through `docker build` from a scratch image. Written to a .partial sibling and atomically renamed so a failed freeze leaves no truncated artifact. Resume: extract the snapshot tar into a cached base dir and feed it to the existing rootless `mke2fs -d` pipeline, replacing the `docker create` + `docker export | tar` path. Recreate the proc/sys/dev/run mount points the freezer excludes so the guest init can mount them. `util.build_base_rootfs_dir` / `docker_image_id` stay — they still back the opt-in BOT_BOTTLE_INFRA_BUILD=local dev path and off-host publish_infra, which are out of scope. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01UoEZHDjv84ChoZbozQERhJ
This commit is contained in:
@@ -44,6 +44,7 @@ from .paths import bot_bottle_root
|
||||
_STATE_SUBDIR = "state"
|
||||
_PER_BOTTLE_DOCKERFILE_NAME = "Dockerfile"
|
||||
_COMMITTED_IMAGE_NAME = "committed-image"
|
||||
_COMMITTED_ROOTFS_NAME = "committed-rootfs.tar"
|
||||
_TRANSCRIPT_SUBDIR = "transcript"
|
||||
# Per-daemon scratch subdirs. PRD 0018 chunk 2: bind-mount sources
|
||||
# live here so chunk 3's `docker compose up` can find them at stable
|
||||
@@ -200,6 +201,15 @@ def committed_image_path(identity: str) -> Path:
|
||||
return bottle_state_dir(identity) / _COMMITTED_IMAGE_NAME
|
||||
|
||||
|
||||
def committed_rootfs_path(identity: str) -> Path:
|
||||
"""Where the Firecracker freezer stores a snapshot of the bottle's
|
||||
guest rootfs (a plain tar). This is the resumable/migratable artifact
|
||||
the Firecracker backend boots from — no Docker image involved. The
|
||||
matching `committed-image` state file records that a snapshot exists
|
||||
(and its path); `resume` boots from this tar when both are present."""
|
||||
return bottle_state_dir(identity) / _COMMITTED_ROOTFS_NAME
|
||||
|
||||
|
||||
def write_committed_image(identity: str, image_tag: str) -> Path:
|
||||
"""Persist the committed image tag for `identity`. The next
|
||||
`cli.py resume <identity>` will boot from this image instead of
|
||||
@@ -354,6 +364,7 @@ __all__ = [
|
||||
"cleanup_state",
|
||||
"clear_preserve_marker",
|
||||
"committed_image_path",
|
||||
"committed_rootfs_path",
|
||||
"egress_state_dir",
|
||||
"git_gate_state_dir",
|
||||
"is_preserved",
|
||||
|
||||
Reference in New Issue
Block a user