package daemon import ( "context" "strings" "banger/internal/model" "banger/internal/system" ) // defaultVsockHostDevice is the vhost-vsock device file every // Firecracker guest relies on to talk to the host via vsock. Tests // point at a tempfile by setting VMService.vsockHostDevice; production // wiring defaults the field to this path in wireServices. const defaultVsockHostDevice = "/dev/vhost-vsock" func (s *VMService) validateStartPrereqs(ctx context.Context, vm model.VMRecord, image model.Image) error { checks := system.NewPreflight() s.addBaseStartPrereqs(checks, image) s.capHooks.addStartPrereqs(ctx, checks, vm, image) return checks.Err("vm start preflight failed") } func (s *VMService) 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 (s *VMService) addBaseStartPrereqs(checks *system.Preflight, image model.Image) { s.addBaseStartCommandPrereqs(checks) checks.RequireExecutable(s.config.FirecrackerBin, "firecracker binary", `install firecracker or set "firecracker_bin"`) if helper, err := vsockAgentBinary(s.layout); err == nil { checks.RequireExecutable(helper, "vsock agent helper", `run 'make build' or reinstall banger`) } else { checks.Addf("%v", err) } checks.RequireFile(s.vsockHostDevice, "vsock host device", "load the vhost_vsock kernel module on the host") checks.RequireFile(image.RootfsPath, "rootfs image", "select a valid registered image") checks.RequireFile(image.KernelPath, "kernel image", `re-register or rebuild the image with a valid kernel`) if strings.TrimSpace(image.InitrdPath) != "" { checks.RequireFile(image.InitrdPath, "initrd image", `re-register or rebuild the image with a valid initrd`) } } func (s *VMService) addBaseStartCommandPrereqs(checks *system.Preflight) { for _, command := range []string{"sudo", "ip", "dmsetup", "losetup", "blockdev", "truncate", "pgrep", "chown", "chmod", "kill", "e2cp", "e2rm", "debugfs"} { checks.RequireCommand(command, toolHint(command)) } } 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", "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 "sudo": return "install sudo" default: return "" } }