Remove runtime-bundle image dependencies
Hard-cut banger away from source-checkout runtime bundles as an implicit source of\nimage and host defaults. Managed images now own their full boot set,\nimage build starts from an existing registered image, and daemon startup\nno longer synthesizes a default image from host paths.\n\nResolve Firecracker from PATH or firecracker_bin, make SSH keys config-owned\nwith an auto-managed XDG default, replace the external name generator and\npackage manifests with Go code, and keep the vsock helper as a companion\nbinary instead of a user-managed runtime asset.\n\nUpdate the manual scripts, web/CLI forms, config surface, and docs around\nthe new build/manual flow and explicit image registration semantics.\n\nValidation: GOCACHE=/tmp/banger-gocache go test ./..., bash -n scripts/*.sh,\nand make build.
This commit is contained in:
parent
01c7cb5e65
commit
572bf32424
44 changed files with 1194 additions and 3456 deletions
|
|
@ -2,12 +2,13 @@ package daemon
|
|||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"database/sql"
|
||||
"strings"
|
||||
|
||||
"banger/internal/config"
|
||||
"banger/internal/model"
|
||||
"banger/internal/paths"
|
||||
"banger/internal/store"
|
||||
"banger/internal/system"
|
||||
)
|
||||
|
||||
|
|
@ -25,34 +26,49 @@ func Doctor(ctx context.Context) (system.Report, error) {
|
|||
config: cfg,
|
||||
runner: system.NewRunner(),
|
||||
}
|
||||
db, err := store.Open(layout.DBPath)
|
||||
if err == nil {
|
||||
defer db.Close()
|
||||
d.store = db
|
||||
}
|
||||
return d.doctorReport(ctx), nil
|
||||
}
|
||||
|
||||
func (d *Daemon) doctorReport(ctx context.Context) system.Report {
|
||||
report := system.Report{}
|
||||
|
||||
report.AddPreflight("runtime bundle", d.runtimeBundleChecks(), runtimeBundleStatus(d.config))
|
||||
report.AddPreflight("host runtime", d.runtimeChecks(), runtimeStatus(d.config))
|
||||
report.AddPreflight("core vm lifecycle", d.coreVMLifecycleChecks(), "required host tools available")
|
||||
report.AddPreflight("vsock guest agent", d.vsockChecks(), "vsock agent prerequisites available")
|
||||
report.AddPreflight("vsock guest agent", d.vsockChecks(), "vsock guest agent prerequisites available")
|
||||
d.addCapabilityDoctorChecks(ctx, &report)
|
||||
report.AddPreflight("image build", d.imageBuildChecks(ctx), "image build prerequisites available")
|
||||
|
||||
return report
|
||||
}
|
||||
|
||||
func (d *Daemon) runtimeBundleChecks() *system.Preflight {
|
||||
func (d *Daemon) runtimeChecks() *system.Preflight {
|
||||
checks := system.NewPreflight()
|
||||
hint := paths.RuntimeBundleHint()
|
||||
checks.RequireExecutable(d.config.FirecrackerBin, "firecracker binary", hint)
|
||||
checks.RequireFile(d.config.SSHKeyPath, "runtime ssh private key", `refresh the runtime bundle`)
|
||||
checks.RequireExecutable(d.config.VSockAgentPath, "vsock agent", `run 'make build' or refresh the runtime bundle`)
|
||||
checks.RequireFile(d.config.DefaultRootfs, "default rootfs image", `set "default_rootfs" or refresh the runtime bundle`)
|
||||
checks.RequireFile(d.config.DefaultKernel, "kernel image", `set "default_kernel" or refresh the runtime bundle`)
|
||||
if strings.TrimSpace(d.config.DefaultInitrd) != "" {
|
||||
checks.RequireFile(d.config.DefaultInitrd, "initrd image", `set "default_initrd" or refresh the runtime bundle`)
|
||||
checks.RequireExecutable(d.config.FirecrackerBin, "firecracker binary", `install firecracker or set "firecracker_bin"`)
|
||||
checks.RequireFile(d.config.SSHKeyPath, "ssh private key", `set "ssh_key_path" or let banger create its default key`)
|
||||
if helper, err := d.vsockAgentBinary(); err == nil {
|
||||
checks.RequireExecutable(helper, "vsock agent helper", `run 'make build' or reinstall banger`)
|
||||
} else {
|
||||
checks.Addf("%v", err)
|
||||
}
|
||||
if strings.TrimSpace(d.config.DefaultPackagesFile) != "" {
|
||||
checks.RequireFile(d.config.DefaultPackagesFile, "package manifest", `set "default_packages_file" or refresh the runtime bundle`)
|
||||
if d.store != nil && strings.TrimSpace(d.config.DefaultImageName) != "" {
|
||||
image, err := d.store.GetImageByName(context.Background(), d.config.DefaultImageName)
|
||||
switch {
|
||||
case err == nil:
|
||||
checks.RequireFile(image.RootfsPath, "default image rootfs", `re-register or rebuild the default image`)
|
||||
checks.RequireFile(image.KernelPath, "default image kernel", `re-register or rebuild the default image`)
|
||||
if strings.TrimSpace(image.InitrdPath) != "" {
|
||||
checks.RequireFile(image.InitrdPath, "default image initrd", `re-register or rebuild the default image`)
|
||||
}
|
||||
case err != nil && err != sql.ErrNoRows:
|
||||
checks.Addf("failed to inspect default image %q: %v", d.config.DefaultImageName, err)
|
||||
default:
|
||||
checks.Addf("default image %q is not registered", d.config.DefaultImageName)
|
||||
}
|
||||
}
|
||||
return checks
|
||||
}
|
||||
|
|
@ -65,37 +81,33 @@ func (d *Daemon) coreVMLifecycleChecks() *system.Preflight {
|
|||
|
||||
func (d *Daemon) imageBuildChecks(ctx context.Context) *system.Preflight {
|
||||
checks := system.NewPreflight()
|
||||
d.addImageBuildPrereqs(
|
||||
ctx,
|
||||
checks,
|
||||
firstNonEmpty(d.config.DefaultBaseRootfs, d.config.DefaultRootfs),
|
||||
d.config.DefaultKernel,
|
||||
d.config.DefaultInitrd,
|
||||
d.config.DefaultModulesDir,
|
||||
"",
|
||||
)
|
||||
if d.store == nil || strings.TrimSpace(d.config.DefaultImageName) == "" {
|
||||
checks.Addf("default image is not available for build inheritance")
|
||||
return checks
|
||||
}
|
||||
image, err := d.store.GetImageByName(ctx, d.config.DefaultImageName)
|
||||
if err != nil {
|
||||
checks.Addf("default image %q is not registered", d.config.DefaultImageName)
|
||||
return checks
|
||||
}
|
||||
d.addImageBuildPrereqs(ctx, checks, image.RootfsPath, image.KernelPath, image.InitrdPath, image.ModulesDir, "")
|
||||
return checks
|
||||
}
|
||||
|
||||
func (d *Daemon) vsockChecks() *system.Preflight {
|
||||
checks := system.NewPreflight()
|
||||
checks.RequireExecutable(d.config.VSockAgentPath, "vsock agent", `run 'make build' or refresh the runtime bundle`)
|
||||
if helper, err := d.vsockAgentBinary(); err == nil {
|
||||
checks.RequireExecutable(helper, "vsock agent helper", `run 'make build' or reinstall banger`)
|
||||
} else {
|
||||
checks.Addf("%v", err)
|
||||
}
|
||||
checks.RequireFile(vsockHostDevicePath, "vsock host device", "load the vhost_vsock kernel module on the host")
|
||||
return checks
|
||||
}
|
||||
|
||||
func runtimeBundleStatus(cfg model.DaemonConfig) string {
|
||||
if strings.TrimSpace(cfg.RuntimeDir) == "" {
|
||||
return "runtime dir not configured"
|
||||
func runtimeStatus(cfg model.DaemonConfig) string {
|
||||
if strings.TrimSpace(cfg.FirecrackerBin) == "" {
|
||||
return "firecracker not configured"
|
||||
}
|
||||
return fmt.Sprintf("runtime dir %s", cfg.RuntimeDir)
|
||||
}
|
||||
|
||||
func firstNonEmpty(values ...string) string {
|
||||
for _, value := range values {
|
||||
if strings.TrimSpace(value) != "" {
|
||||
return value
|
||||
}
|
||||
}
|
||||
return ""
|
||||
return "firecracker and ssh key resolved"
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue