feat: multi-distro support and tagged golden snapshots

Add Alpine, Debian, and Ubuntu rootfs support to `init [distro]`.
Golden snapshots are now namespaced under `golden/<tag>/` so multiple
baselines can coexist. `spawn [tag] [N]` selects which snapshot to
clone from. Systemd-based distros (Debian, Ubuntu) get a fc-net-init
systemd unit; Alpine keeps its inittab-based init.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-04-14 20:48:43 +00:00
parent bfc1f47287
commit fb1db7c9ea
10 changed files with 576 additions and 102 deletions

38
main.go
View File

@@ -21,6 +21,7 @@ import (
"os"
"path/filepath"
"runtime"
"strconv"
log "github.com/sirupsen/logrus"
@@ -65,15 +66,32 @@ func main() {
switch os.Args[1] {
case "init":
fatal(orch.Init())
distro := "alpine"
if len(os.Args) > 2 {
distro = os.Args[2]
}
fatal(orch.Init(distro))
case "golden":
fatal(orch.Golden())
tag := "default"
distro := "alpine"
if len(os.Args) > 2 {
tag = os.Args[2]
}
if len(os.Args) > 3 {
distro = os.Args[3]
}
fatal(orch.Golden(tag, distro))
case "spawn":
n := 1
if len(os.Args) > 2 {
fmt.Sscanf(os.Args[2], "%d", &n)
tag := "default"
for _, arg := range os.Args[2:] {
if parsed, err := strconv.Atoi(arg); err == nil {
n = parsed
} else {
tag = arg
}
}
fatal(orch.Spawn(n))
fatal(orch.Spawn(n, tag))
case "status":
orch.Status()
case "kill":
@@ -98,14 +116,16 @@ func main() {
// Internal subcommand: started by spawnOne, runs as a background daemon.
fs := flag.NewFlagSet("_console-proxy", flag.ContinueOnError)
var id int
var tag string
var tap string
fs.IntVar(&id, "id", 0, "clone ID")
fs.StringVar(&tag, "tag", "default", "Golden VM tag")
fs.StringVar(&tap, "tap", "", "TAP device name")
if err := fs.Parse(os.Args[2:]); err != nil {
fmt.Fprintf(os.Stderr, "console-proxy: %v\n", err)
os.Exit(1)
}
fatal(orchestrator.RunConsoleProxy(orchestrator.DefaultConfig(), id, tap))
fatal(orchestrator.RunConsoleProxy(orchestrator.DefaultConfig(), id, tap, tag))
default:
usage()
os.Exit(1)
@@ -119,9 +139,9 @@ Flags:
--dev log format with source file:line (e.g. file="orchestrator.go:123")
Commands:
init Download kernel + create Alpine rootfs
golden Boot golden VM → pause → snapshot
spawn [N] Restore N clones from golden snapshot (default: 1)
init [distro] Download kernel + create distro rootfs (default: alpine, options: alpine, debian, ubuntu)
golden [tag] [distro] Boot golden VM → pause → snapshot (default tag: default, default distro: alpine)
spawn [tag] [N] Restore N clones from golden snapshot (default tag: default, default N: 1)
serve [addr] Start terminal web UI (default: :8080)
console <id> Attach to the serial console of a running clone (Ctrl+] to detach)
status Show running clones