Move avoidable daemon shell-outs into Go
Reduce the control plane's dependency on helper scripts while keeping the hard Linux integration points in the approved shell-out layer. Replace the bash-driven image build path with a native Go builder that clones and optionally resizes the rootfs, boots a temporary Firecracker VM, provisions the guest over SSH, installs packages and modules, and preserves the package-manifest sidecar. Also replace a few small convenience shell-outs with Go helpers: read process stats from /proc, use os.Truncate for ext4 image growth, add file-clone and normalized-line helpers, drop the sh -c work-disk flattening path, and launch Firecracker via a direct sudo command. Add tests for the new SSH/archive and system helpers, plus a policy test that keeps os/exec imports confined to cli/firecracker/system. Update the docs to describe customize.sh as a manual helper rather than the daemon's image-build backend. Validated with go mod tidy, go test ./..., and make build.
This commit is contained in:
parent
0a0b0b617b
commit
942d242c03
17 changed files with 936 additions and 145 deletions
|
|
@ -13,7 +13,7 @@ func (d *Daemon) validateStartPrereqs(ctx context.Context, vm model.VMRecord, im
|
|||
checks := system.NewPreflight()
|
||||
hint := paths.RuntimeBundleHint()
|
||||
|
||||
for _, command := range []string{"sudo", "ip", "dmsetup", "losetup", "blockdev", "truncate", "pgrep", "ps", "chown", "chmod", "kill", "e2cp", "e2rm", "debugfs"} {
|
||||
for _, command := range []string{"sudo", "ip", "dmsetup", "losetup", "blockdev", "truncate", "pgrep", "chown", "chmod", "kill", "e2cp", "e2rm", "debugfs"} {
|
||||
checks.RequireCommand(command, toolHint(command))
|
||||
}
|
||||
checks.RequireExecutable(d.config.FirecrackerBin, "firecracker binary", hint)
|
||||
|
|
@ -33,22 +33,34 @@ func (d *Daemon) validateStartPrereqs(ctx context.Context, vm model.VMRecord, im
|
|||
return checks.Err("vm start preflight failed")
|
||||
}
|
||||
|
||||
func (d *Daemon) validateImageBuildPrereqs(ctx context.Context, baseRootfs, kernelPath, initrdPath, modulesDir string) error {
|
||||
func (d *Daemon) validateImageBuildPrereqs(ctx context.Context, baseRootfs, kernelPath, initrdPath, modulesDir, sizeSpec string) error {
|
||||
checks := system.NewPreflight()
|
||||
hint := paths.RuntimeBundleHint()
|
||||
|
||||
for _, command := range []string{"bash", "sudo", "ip", "curl", "ssh", "jq", "sha256sum", "e2fsck", "resize2fs"} {
|
||||
for _, command := range []string{"sudo", "ip", "pgrep", "chown", "chmod", "kill"} {
|
||||
checks.RequireCommand(command, toolHint(command))
|
||||
}
|
||||
checks.RequireExecutable(d.config.CustomizeScript, "customize.sh helper", hint)
|
||||
checks.RequireExecutable(d.config.FirecrackerBin, "firecracker binary", hint)
|
||||
checks.RequireFile(d.config.SSHKeyPath, "ssh private key", `set "ssh_key_path" or refresh the runtime bundle`)
|
||||
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"`)
|
||||
checks.RequireFile(d.config.DefaultPackagesFile, "package manifest", `set "default_packages_file" or refresh the runtime bundle`)
|
||||
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"`)
|
||||
}
|
||||
if strings.TrimSpace(d.config.DefaultPackagesFile) != "" {
|
||||
if _, err := system.ReadNormalizedLines(d.config.DefaultPackagesFile); err != nil {
|
||||
checks.Addf("package manifest at %s is invalid: %v", d.config.DefaultPackagesFile, err)
|
||||
}
|
||||
}
|
||||
if strings.TrimSpace(sizeSpec) != "" {
|
||||
checks.RequireCommand("e2fsck", toolHint("e2fsck"))
|
||||
checks.RequireCommand("resize2fs", toolHint("resize2fs"))
|
||||
}
|
||||
d.addNATPrereqs(ctx, checks)
|
||||
return checks.Err("image build preflight failed")
|
||||
}
|
||||
|
||||
|
|
@ -63,7 +75,11 @@ func (d *Daemon) validateWorkDiskResizePrereqs() error {
|
|||
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")
|
||||
runner := d.runner
|
||||
if runner == nil {
|
||||
runner = system.NewRunner()
|
||||
}
|
||||
out, err := runner.Run(ctx, "ip", "route", "show", "default")
|
||||
if err != nil {
|
||||
checks.Addf("failed to inspect the default route for NAT: %v", err)
|
||||
return
|
||||
|
|
@ -83,7 +99,7 @@ func toolHint(command string) string {
|
|||
return "install util-linux"
|
||||
case "dmsetup":
|
||||
return "install device-mapper"
|
||||
case "pgrep", "ps", "kill":
|
||||
case "pgrep", "kill":
|
||||
return "install procps"
|
||||
case "chown", "chmod", "cp", "truncate":
|
||||
return "install coreutils"
|
||||
|
|
@ -91,16 +107,6 @@ func toolHint(command string) string {
|
|||
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:
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue