215 lines
5.7 KiB
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
|
|
}
|