Files
warewulf/cmd/wwbuild/wwbuild.go
2020-11-01 22:06:03 -08:00

133 lines
4.9 KiB
Go

package main
import (
"fmt"
"github.com/hpcng/warewulf/internal/pkg/assets"
"github.com/hpcng/warewulf/internal/pkg/util"
"os"
"os/exec"
"path"
"strings"
"time"
)
const LocalStateDir = "/var/warewulf"
func vnfsBuild(vnfsPath string) {
fmt.Printf("BUILDING VNFS: %s\n", vnfsPath)
if _, err := os.Stat(vnfsPath); err == nil {
// TODO: Build VNFS to temporary file and move to real location when complete atomically
// TODO: Check time stamps of sourcedir and build file to see if we need to rebuild or skip
cmd := fmt.Sprintf("cd %s; find . | cpio --quiet -o -H newc | gzip -c > \"%s/provision/bases/%s.img.gz\"", vnfsPath, LocalStateDir, path.Base(vnfsPath))
err := exec.Command("/bin/sh", "-c", cmd).Run()
if err != nil {
fmt.Printf("%s", err)
}
} else {
fmt.Printf("SKIPPING VNFS: (bad path) %s\n", vnfsPath)
}
}
func main(){
if len(os.Args) < 2 {
fmt.Printf("USAGE: %s [vnfs/kernel/overlays/all]\n", os.Args[0])
return
}
if os.Args[1] == "vnfs" {
if len(os.Args) >= 3 {
vnfsBuild(os.Args[3])
} else {
for _, vnfs := range assets.FindAllVnfs() {
vnfsBuild(vnfs)
}
}
} else if os.Args[1] == "kernel" {
for _, kernelVers := range assets.FindAllKernels() {
kernelSource := fmt.Sprintf("/boot/vmlinuz-%s", kernelVers)
// TODO: Check time stamps of source and dests to see if we need to rebuild or skip
if _, err := os.Stat(kernelSource); err == nil {
kernelDestination := fmt.Sprintf("%s/provision/kernels/vmlinuz-%s", LocalStateDir, kernelVers)
fmt.Printf("SETUP KERNEL: %s (%s)\n", kernelSource, kernelDestination)
err := exec.Command("cp", kernelSource, kernelDestination).Run()
if err != nil {
fmt.Printf("%s", err)
}
kernelMods := fmt.Sprintf("/lib/modules/%s", kernelVers)
if _, err := os.Stat(kernelMods); err == nil {
fmt.Printf("BUILDING MODS: %s\n", kernelMods)
cmd := fmt.Sprintf("find %s | cpio --quiet -o -H newc -F \"%s/provision/kernels/kmods-%s.img\"", kernelMods, LocalStateDir, kernelVers)
err := exec.Command("/bin/sh", "-c", cmd).Run()
if err != nil {
fmt.Printf("OUTPUT: %s", err)
}
}
}
}
} else if os.Args[1] == "overlay" {
//TODO: Move this all to warewulfd and generate on demand when needed
for _, node := range assets.FindAllNodes() {
overlayDir := fmt.Sprintf("/etc/warewulf/overlays/%s", node.Overlay)
//TODO: Move this all to the Asset package
replace := make(map[string]string)
replace["HOSTNAME"] = node.HostName
replace["FQDN"] = node.Fqdn
replace["VNFS"] = node.Vnfs
replace["KERNELVERSION"] = node.KernelVersion
replace["GROUPNAME"] = node.GroupName
replace["DOMAIN"] = node.DomainName
for key, dev := range node.NetDevs {
replace[fmt.Sprintf("%s:NAME", key)] = key
replace[fmt.Sprintf("%s:HWADDR", key)] = strings.ReplaceAll(dev.Hwaddr, "-", ":")
replace[fmt.Sprintf("%s:IPADDR", key)] = dev.Ipaddr
replace[fmt.Sprintf("%s:NETMASK", key)] = dev.Netmask
replace[fmt.Sprintf("%s:GATEWAY", key)] = dev.Gateway
}
destFile := fmt.Sprintf("%s/provision/overlays/%s.img", LocalStateDir, node.Fqdn)
destModTime := time.Time{}
destMod, err := os.Stat(destFile)
if err == nil {
destModTime = destMod.ModTime()
}
configMod, err := os.Stat("/etc/warewulf/nodes.yaml")
if err != nil {
fmt.Printf("ERROR: could not find node file: /etc/warewulf/nodes.yaml")
os.Exit(1)
}
configModTime := configMod.ModTime()
sourceModTime, _ := util.DirModTime(overlayDir)
if sourceModTime.After(destModTime) || configModTime.After(destModTime) {
fmt.Printf("BUILDING OVERLAY: %s\n", node.Fqdn)
overlayDest := "/tmp/.overlay-" + util.RandomString(16)
BuildOverlayDir(overlayDir, overlayDest, replace)
cmd := fmt.Sprintf("cd %s; find . | cpio --quiet -o -H newc -F \"%s\"", overlayDest, destFile)
err := exec.Command("/bin/sh", "-c", cmd).Run()
if err != nil {
fmt.Printf("%s", err)
}
os.RemoveAll(overlayDest)
} else {
fmt.Printf("Skipping overlay (nothing changed): %s\n", node.Fqdn)
}
}
}
}