Introduces optional per-clone IP assignment using the Firecracker Microvm
Metadata Service (MMDS). A background daemon (fc-net-init) is baked into
the rootfs during init and captured in the golden snapshot — on clone
resume it polls 169.254.169.254 and applies the IP/GW/DNS config injected
by the orchestrator immediately after snapshot restore.
- config.go: add AutoNetConfig bool (FC_AUTO_NET_CONFIG=1)
- orchestrator.go: embed fc-net-init daemon + MMDS link-local route in
init script; set AllowMMDS: true on golden NIC; spawnOne/SpawnSingle
accept net bool and propagate it via FC_AUTO_NET_CONFIG in proxy env
- console.go: set AllowMMDS: true on clone NIC; call configureMmds()
after m.Start() when AutoNetConfig is enabled
- network.go: add configureMmds() — PUT /mmds with ip/gw/dns over the
clone's Firecracker Unix socket
- serve.go: POST /clones accepts optional {"net": bool} body to override
the global AutoNetConfig default per-request
- web/terminal.html: spawn button always sends {"net": true}
- docs/commands.md: document manual config + MMDS autoconfiguration
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
60 lines
1.8 KiB
Go
60 lines
1.8 KiB
Go
package orchestrator
|
|
|
|
import (
|
|
"os"
|
|
"strconv"
|
|
)
|
|
|
|
// Config holds all tunables for the orchestrator.
|
|
type Config struct {
|
|
FCBin string // path to firecracker binary
|
|
BaseDir string // working directory for all state
|
|
Kernel string // path to vmlinux
|
|
KernelURL string // URL to download vmlinux if Kernel file is missing
|
|
Rootfs string // path to base rootfs.ext4
|
|
VCPUs int64
|
|
MemMiB int64
|
|
Bridge string // host bridge name, or "none" to skip networking
|
|
BridgeCIDR string // e.g. "172.30.0.1/24"
|
|
GuestPrefix string // e.g. "172.30.0" — clones get .11, .12, ...
|
|
GuestGW string // default gateway for guest VMs
|
|
AutoNetConfig bool // inject guest IP/GW/DNS via MMDS on clone start
|
|
BootArgs string
|
|
}
|
|
|
|
func DefaultConfig() Config {
|
|
c := Config{
|
|
FCBin: envOr("FC_BIN", "firecracker"),
|
|
BaseDir: envOr("FC_BASE_DIR", "/tmp/fc-orch"),
|
|
VCPUs: envOrInt("FC_VCPUS", 1),
|
|
MemMiB: envOrInt("FC_MEM_MIB", 128),
|
|
Bridge: envOr("FC_BRIDGE", "fcbr0"),
|
|
BridgeCIDR: envOr("FC_BRIDGE_CIDR", "172.30.0.1/24"),
|
|
GuestPrefix: envOr("FC_GUEST_PREFIX", "172.30.0"),
|
|
GuestGW: envOr("FC_GUEST_GW", "172.30.0.1"),
|
|
AutoNetConfig: envOr("FC_AUTO_NET_CONFIG", "") == "1",
|
|
BootArgs: "console=ttyS0 reboot=k panic=1 pci=off i8042.noaux quiet loglevel=0",
|
|
}
|
|
c.Kernel = envOr("FC_KERNEL", c.BaseDir+"/vmlinux")
|
|
c.KernelURL = envOr("FC_KERNEL_URL",
|
|
"https://s3.amazonaws.com/spec.ccfc.min/firecracker-ci/20260408-ce2a467895c1-0/x86_64/vmlinux-6.1.166")
|
|
c.Rootfs = envOr("FC_ROOTFS", c.BaseDir+"/rootfs.ext4")
|
|
return c
|
|
}
|
|
|
|
func envOr(key, fallback string) string {
|
|
if v := os.Getenv(key); v != "" {
|
|
return v
|
|
}
|
|
return fallback
|
|
}
|
|
|
|
func envOrInt(key string, fallback int64) int64 {
|
|
if v := os.Getenv(key); v != "" {
|
|
if n, err := strconv.ParseInt(v, 10, 64); err == nil {
|
|
return n
|
|
}
|
|
}
|
|
return fallback
|
|
}
|