Files
warewulf/internal/pkg/overlay/overlay.go

215 lines
5.7 KiB
Go

package overlay
import (
"bytes"
"fmt"
"github.com/hpcng/warewulf/internal/pkg/config"
"github.com/hpcng/warewulf/internal/pkg/node"
"github.com/hpcng/warewulf/internal/pkg/util"
"github.com/hpcng/warewulf/internal/pkg/vnfs"
"github.com/hpcng/warewulf/internal/pkg/wwlog"
"io"
"io/ioutil"
"os"
"os/exec"
"path"
"text/template"
)
func OverlayBuild(nodeList []node.NodeInfo, overlayType string) error {
config := config.New()
for _, n := range nodeList {
wwlog.Printf(wwlog.DEBUG, "Processing overlay for node: %s\n", n.Fqdn)
if util.IsDir(config.VnfsImage(vnfs.CleanName(n.Vnfs))) == false {
wwlog.Printf(wwlog.WARN, "'%s', VNFS not built: %s\n", n.Fqdn, n.Vnfs)
// continue
}
var files []node.OverlayEntry
tmpDir, err := ioutil.TempDir(os.TempDir(), ".wwctl-runtime-overlay-")
if err != nil {
continue
}
if overlayType == "system" {
wwlog.Printf(wwlog.VERBOSE, "Generating system overlay for node: %s\n", n.Fqdn)
files = n.SystemOverlay
} else if overlayType == "runtime" {
wwlog.Printf(wwlog.VERBOSE, "Generating runtime overlay for node: %s\n", n.Fqdn)
files = n.RuntimeOverlay
} else {
wwlog.Printf(wwlog.ERROR, "overlayType requested is not supported: %s\n", overlayType)
os.Exit(1)
}
for _, file := range files {
fullPath := path.Join(tmpDir, file.Path)
mode := file.Mode
if mode == 0 {
mode = 0755
}
if file.Dir == true {
wwlog.Printf(wwlog.DEBUG, "Creating overlay directory: %s\n", file.Path)
err := os.MkdirAll(fullPath, os.FileMode(mode))
if err != nil {
wwlog.Printf(wwlog.ERROR, "Could not create parent directory in overlay: %s\n", file.Path)
continue
}
} else if file.File == true {
wwlog.Printf(wwlog.DEBUG, "Creating overlay file: %s\n", file.Path)
err := os.MkdirAll(path.Dir(fullPath), 0755)
if err != nil {
wwlog.Printf(wwlog.ERROR, "Could not create parent directory for overlay file: %s\n", file.Dir)
continue
}
write, err := os.OpenFile(path.Join(tmpDir, file.Path), os.O_RDWR|os.O_CREATE, os.FileMode(mode))
if err != nil {
wwlog.Printf(wwlog.ERROR, "%s\n", err)
continue
}
if file.Source != "" {
tmpl, _ := template.New("string").Parse(file.Source)
var tpl bytes.Buffer
_ = tmpl.Execute(&tpl, n)
string := tpl.String()
source, err := os.Open(string)
if err != nil {
wwlog.Printf(wwlog.ERROR, "%s\n", err)
source.Close()
continue
}
_, err = io.Copy(write, source)
if err != nil {
wwlog.Printf(wwlog.ERROR, "%s\n", err)
source.Close()
continue
}
source.Close()
}
for _, s := range file.Sources {
tmpl, _ := template.New("string").Parse(s)
var tpl bytes.Buffer
_ = tmpl.Execute(&tpl, n)
string := tpl.String()
source, err := os.Open(string)
if err != nil {
wwlog.Printf(wwlog.WARN, "%s\n", err)
source.Close()
continue
}
_, err = io.Copy(write, source)
if err != nil {
wwlog.Printf(wwlog.WARN, "%s\n", err)
source.Close()
continue
}
source.Close()
}
write.Close()
} else if file.Link == true {
wwlog.Printf(wwlog.DEBUG, "Creating overlay link: %s\n", file.Path)
if file.Source != "" {
err := os.MkdirAll(path.Dir(fullPath), 0755)
if err != nil {
wwlog.Printf(wwlog.ERROR, "Could not create parent directory for overlay file: %s\n", file.Path)
continue
}
err = os.Symlink(file.Source, fullPath)
if err != nil {
wwlog.Printf(wwlog.WARN, "Could not create overlay symlink: %s\n", err)
continue
}
} else {
wwlog.Printf(wwlog.WARN, "Could not create link, no source defined: %s\n", file.Path)
continue
}
} else if file.Template == true {
wwlog.Printf(wwlog.DEBUG, "Creating overlay file from template: %s\n", file.Path)
err := os.MkdirAll(path.Dir(fullPath), 0755)
if err != nil {
wwlog.Printf(wwlog.ERROR, "Could not create parent directory for overlay file: %s\n", file.Path)
continue
}
if file.Source != "" {
tmpl, err := template.New(path.Base(file.Source)).Funcs(template.FuncMap{
"Include": templateFileInclude,
"IncludeFromVnfs": templateVnfsFileInclude,
}).ParseFiles(file.Source)
if err != nil {
wwlog.Printf(wwlog.ERROR, "%s\n", err)
continue
}
w, err := os.OpenFile(fullPath, os.O_RDWR|os.O_CREATE, os.FileMode(mode))
if err != nil {
w.Close()
wwlog.Printf(wwlog.ERROR, "%s\n", err)
continue
}
err = tmpl.Execute(w, n)
if err != nil {
w.Close()
wwlog.Printf(wwlog.ERROR, "%s\n", err)
continue
}
w.Close()
}
} else {
wwlog.Printf(wwlog.ERROR, "Overlay file type error: %s\n", file.Path)
}
}
var overlayFile string
if overlayType == "system" {
overlayFile = config.SystemOverlayImage(n.Fqdn)
} else if overlayType == "runtime" {
overlayFile = config.RuntimeOverlayImage(n.Fqdn)
}
err = os.MkdirAll(path.Dir(overlayFile), 0755)
if err != nil {
wwlog.Printf(wwlog.ERROR, "Could not create parent directory for overlay file: %s\n", overlayFile)
continue
}
wwlog.Printf(wwlog.VERBOSE, "Finished generating overlay directory for: %s\n", n.Fqdn)
os.Chmod(tmpDir, 0755)
cmd := fmt.Sprintf("cd \"%s\"; find . | cpio --quiet -o -H newc -F \"%s\"", tmpDir, overlayFile)
wwlog.Printf(wwlog.DEBUG, "RUNNING: %s\n", cmd)
err = exec.Command("/bin/sh", "-c", cmd).Run()
if err != nil {
wwlog.Printf(wwlog.ERROR, "Could not generate runtime image overlay: %s\n", err)
os.RemoveAll(tmpDir)
continue
}
wwlog.Printf(wwlog.INFO, "%-35s: Done\n", n.Fqdn)
wwlog.Printf(wwlog.DEBUG, "Removing temporary directory: %s\n", tmpDir)
os.RemoveAll(tmpDir)
}
return nil
}