banger/internal/daemon/preflight.go
Thales Maciel 0a0b0b617b
Replace mapdns with daemon DNS
Serve daemon-managed .vm names directly from bangerd on 127.0.0.1:42069 instead of shelling out to mapdns. This keeps DNS state tied to VM lifecycle and lets the daemon rebuild records from running VMs after startup or reconcile.

Add a small in-process authoritative DNS server, register and remove records from the VM start/stop/delete paths, and show the listener in daemon status. Remove the mapdns config and preflight surface, stop helper-flow DNS publishing in customize.sh and interactive.sh, drop dns.sh from the runtime bundle, and update docs/tests for the new local-resolver integration model.

Validated with GOCACHE=/tmp/banger-gocache go test ./..., GOCACHE=/tmp/banger-gocache make build, and bash -n customize.sh interactive.sh.
2026-03-17 15:49:35 -03:00

109 lines
3.8 KiB
Go

package daemon
import (
"context"
"strings"
"banger/internal/model"
"banger/internal/paths"
"banger/internal/system"
)
func (d *Daemon) validateStartPrereqs(ctx context.Context, vm model.VMRecord, image model.Image) error {
checks := system.NewPreflight()
hint := paths.RuntimeBundleHint()
for _, command := range []string{"sudo", "ip", "dmsetup", "losetup", "blockdev", "truncate", "pgrep", "ps", "chown", "chmod", "kill", "e2cp", "e2rm", "debugfs"} {
checks.RequireCommand(command, toolHint(command))
}
checks.RequireExecutable(d.config.FirecrackerBin, "firecracker binary", hint)
checks.RequireFile(image.RootfsPath, "rootfs image", "select a valid image or rebuild the runtime bundle")
checks.RequireFile(image.KernelPath, "kernel image", `set "default_kernel" or refresh the runtime bundle`)
if strings.TrimSpace(image.InitrdPath) != "" {
checks.RequireFile(image.InitrdPath, "initrd image", `set "default_initrd" or refresh the runtime bundle`)
}
if !exists(vm.Runtime.WorkDiskPath) {
for _, command := range []string{"mkfs.ext4", "mount", "umount", "cp"} {
checks.RequireCommand(command, toolHint(command))
}
}
if vm.Spec.NATEnabled {
d.addNATPrereqs(ctx, checks)
}
return checks.Err("vm start preflight failed")
}
func (d *Daemon) validateImageBuildPrereqs(ctx context.Context, baseRootfs, kernelPath, initrdPath, modulesDir string) error {
checks := system.NewPreflight()
hint := paths.RuntimeBundleHint()
for _, command := range []string{"bash", "sudo", "ip", "curl", "ssh", "jq", "sha256sum", "e2fsck", "resize2fs"} {
checks.RequireCommand(command, toolHint(command))
}
checks.RequireExecutable(d.config.CustomizeScript, "customize.sh helper", hint)
checks.RequireFile(baseRootfs, "base rootfs image", `pass --base-rootfs or set "default_base_rootfs"`)
checks.RequireFile(kernelPath, "kernel image", `pass --kernel or set "default_kernel"`)
if strings.TrimSpace(initrdPath) != "" {
checks.RequireFile(initrdPath, "initrd image", `pass --initrd or set "default_initrd"`)
}
if strings.TrimSpace(modulesDir) != "" {
checks.RequireDir(modulesDir, "modules directory", `pass --modules or set "default_modules_dir"`)
}
return checks.Err("image build preflight failed")
}
func (d *Daemon) validateWorkDiskResizePrereqs() error {
checks := system.NewPreflight()
checks.RequireCommand("truncate", toolHint("truncate"))
checks.RequireCommand("e2fsck", `install e2fsprogs`)
checks.RequireCommand("resize2fs", `install e2fsprogs`)
return checks.Err("work disk resize preflight failed")
}
func (d *Daemon) addNATPrereqs(ctx context.Context, checks *system.Preflight) {
checks.RequireCommand("iptables", toolHint("iptables"))
checks.RequireCommand("sysctl", toolHint("sysctl"))
out, err := d.runner.Run(ctx, "ip", "route", "show", "default")
if err != nil {
checks.Addf("failed to inspect the default route for NAT: %v", err)
return
}
if _, err := parseDefaultUplink(string(out)); err != nil {
checks.Addf("failed to detect the uplink interface for NAT: %v", err)
}
}
func toolHint(command string) string {
switch command {
case "ip":
return "install iproute2"
case "iptables":
return "install iptables"
case "sysctl", "losetup", "blockdev", "mount", "umount":
return "install util-linux"
case "dmsetup":
return "install device-mapper"
case "pgrep", "ps", "kill":
return "install procps"
case "chown", "chmod", "cp", "truncate":
return "install coreutils"
case "e2fsck", "resize2fs", "debugfs", "mkfs.ext4":
return "install e2fsprogs"
case "e2cp", "e2rm":
return "install e2tools"
case "curl":
return "install curl"
case "jq":
return "install jq"
case "sha256sum":
return "install coreutils"
case "ssh":
return "install openssh-client"
case "bash":
return "install bash"
case "sudo":
return "install sudo"
default:
return ""
}
}