package plan import ( "fmt" "os/exec" "path/filepath" "metis/pkg/image" "metis/pkg/inventory" ) // Execute performs a burn if confirm is true. With confirm=false, it only downloads/verifies and returns the plan. func Execute(inv *inventory.Inventory, nodeName, device, cacheDir string, confirm bool) (*Plan, error) { p, err := Build(inv, nodeName, device, cacheDir) if err != nil { return nil, err } cacheImage := filepath.Join(cacheDir, filepath.Base(p.Image)) if err := image.Download(p.Image, cacheImage); err != nil { return p, fmt.Errorf("download image: %w", err) } if err := image.VerifyChecksum(cacheImage, checksumFromInventory(inv, nodeName)); err != nil { return p, err } if !confirm { return p, nil } if device == "" || device == "/dev/sdX" { return p, fmt.Errorf("refusing to write to placeholder device") } ddCmd := []string{"dd", fmt.Sprintf("if=%s", cacheImage), fmt.Sprintf("of=%s", device), "bs=4M", "status=progress", "conv=fsync"} cmd := exec.Command(ddCmd[0], ddCmd[1:]...) cmd.Stdout = nil cmd.Stderr = nil if err := cmd.Run(); err != nil { return p, fmt.Errorf("dd failed: %w", err) } return p, nil } func checksumFromInventory(inv *inventory.Inventory, node string) string { _, cls, err := inv.FindNode(node) if err != nil || cls == nil { return "" } return cls.Checksum }