Fleshed out the framework of most of the wwctl overlay command group.

This commit is contained in:
Gregory Kurtzer
2020-11-17 21:50:27 -08:00
parent 108174d35c
commit ed7dbdaf32
18 changed files with 806 additions and 39 deletions

View File

@@ -0,0 +1,58 @@
package build
import (
"github.com/hpcng/warewulf/internal/pkg/assets"
"github.com/hpcng/warewulf/internal/pkg/overlay"
"github.com/hpcng/warewulf/internal/pkg/wwlog"
"github.com/spf13/cobra"
"os"
)
func CobraRunE(cmd *cobra.Command, args []string) error {
var updateNodes []assets.NodeInfo
if len(args) > 0 && BuildAll == false {
nodes, err := assets.FindAllNodes()
if err != nil {
wwlog.Printf(wwlog.ERROR, "Cloud not get nodeList: %s\n", err)
os.Exit(1)
}
for _, node := range nodes {
if SystemOverlay == true && node.SystemOverlay == args[0] {
updateNodes = append(updateNodes, node)
} else if node.RuntimeOverlay == args[0] {
updateNodes = append(updateNodes, node)
}
}
} else {
var err error
updateNodes, err = assets.FindAllNodes()
if err != nil {
wwlog.Printf(wwlog.ERROR, "Cloud not get nodeList: %s\n", err)
os.Exit(1)
}
}
wwlog.Printf(wwlog.DEBUG, "Checking on system overlay update\n")
if SystemOverlay == true || BuildAll == true {
wwlog.Printf(wwlog.INFO, "Updating System Overlays...\n")
err := overlay.SystemBuild(updateNodes, true)
if err != nil {
wwlog.Printf(wwlog.WARN, "Some system overlays failed to be generated\n")
}
}
wwlog.Printf(wwlog.DEBUG, "Checking on system overlay update\n")
if SystemOverlay == false || BuildAll == true {
wwlog.Printf(wwlog.INFO, "Updating Runtime Overlays...\n")
err := overlay.RuntimeBuild(updateNodes, true)
if err != nil {
wwlog.Printf(wwlog.WARN, "Some runtime overlays failed to be generated\n")
}
}
return nil
}

View File

@@ -0,0 +1,25 @@
package build
import "github.com/spf13/cobra"
var (
baseCmd = &cobra.Command{
Use: "build [overlay name]",
Short: "Build/Rebuild an overlay",
Long: "Build or rebuild a Warewulf overlay ",
RunE: CobraRunE,
}
SystemOverlay bool
BuildAll bool
)
func init() {
baseCmd.PersistentFlags().BoolVarP(&SystemOverlay, "system", "s", false, "Show System Overlays as well")
baseCmd.PersistentFlags().BoolVarP(&BuildAll, "all", "a", false, "Build all overlays (runtime and system)")
}
// GetRootCommand returns the root cobra.Command for the application.
func GetCommand() *cobra.Command {
return baseCmd
}

View File

@@ -0,0 +1,13 @@
package copy
import (
"fmt"
"github.com/spf13/cobra"
)
func CobraRunE(cmd *cobra.Command, args []string) error {
fmt.Printf("This will copy '%s' to overlay '%s'\n", args[1], args[0])
return nil
}

View File

@@ -0,0 +1,25 @@
package copy
import "github.com/spf13/cobra"
var (
baseCmd = &cobra.Command{
Use: "copy [overlay name] [source file] (dest location)",
Short: "Copy Warewulf Overlay files",
Long: "Warewulf Copy overlay files",
RunE: CobraRunE,
Args: cobra.RangeArgs(2, 3),
Aliases: []string{"import"},
}
SystemOverlay bool
)
func init() {
baseCmd.PersistentFlags().BoolVarP(&SystemOverlay, "system", "s", false, "Show system overlays instead of runtime")
}
// GetRootCommand returns the root cobra.Command for the application.
func GetCommand() *cobra.Command {
return baseCmd
}

View File

@@ -2,11 +2,117 @@ package delete
import (
"fmt"
"github.com/hpcng/warewulf/internal/pkg/assets"
"github.com/hpcng/warewulf/internal/pkg/config"
"github.com/hpcng/warewulf/internal/pkg/overlay"
"github.com/hpcng/warewulf/internal/pkg/util"
"github.com/hpcng/warewulf/internal/pkg/wwlog"
"github.com/spf13/cobra"
"os"
"path"
)
func CobraRunE(cmd *cobra.Command, args []string) error {
fmt.Printf("Delete: Hello World\n")
var overlayPath string
config := config.New()
if SystemOverlay == true {
overlayPath = config.SystemOverlaySource(args[0])
} else {
overlayPath = config.RuntimeOverlaySource(args[0])
}
if overlayPath == "" {
wwlog.Printf(wwlog.ERROR, "Overlay name did not render: '%s'\n", args[0])
os.Exit(1)
}
if util.IsDir(overlayPath) == false {
wwlog.Printf(wwlog.ERROR, "Overlay name does not exist: '%s'\n", args[0])
os.Exit(1)
}
if len(args) == 1 {
if Force == true {
err := os.RemoveAll(overlayPath)
if err != nil {
wwlog.Printf(wwlog.ERROR, "Failed deleting overlay: %s\n", args[0])
wwlog.Printf(wwlog.ERROR, "%s\n", err)
os.Exit(1)
}
} else {
err := os.Remove(overlayPath)
if err != nil {
wwlog.Printf(wwlog.ERROR, "Failed deleting overlay: %s\n", args[0])
wwlog.Printf(wwlog.ERROR, "%s\n", err)
os.Exit(1)
}
}
} else if len(args) > 1 {
for i := 1; i < len(args); i++ {
removePath := path.Join(overlayPath, args[i])
if Force == true {
err := os.RemoveAll(removePath)
if err != nil {
wwlog.Printf(wwlog.ERROR, "Failed deleting file from overlay: %s:%s\n", args[0], args[i])
wwlog.Printf(wwlog.ERROR, "%s\n", err)
os.Exit(1)
}
} else {
err := os.Remove(removePath)
if err != nil {
wwlog.Printf(wwlog.ERROR, "Failed deleting overlay: %s:%s\n", args[0], args[i])
wwlog.Printf(wwlog.ERROR, "%s\n", err)
os.Exit(1)
}
}
if RmEmptyDirs == true {
// Cleanup any empty directories left behind...
i := path.Dir(removePath)
for i != overlayPath {
wwlog.Printf(wwlog.DEBUG, "Evaluating directory to remove: %s\n", i)
err := os.Remove(i)
if err != nil {
break
}
wwlog.Printf(wwlog.VERBOSE, "Removed empty directory: %s\n", i)
i = path.Dir(i)
}
}
}
}
fmt.Printf("Deleted from overlay: %s:%s\n", args[0], args[1])
// Everything below this point is to update the relevant overlays
nodes, err := assets.FindAllNodes()
if err != nil {
wwlog.Printf(wwlog.ERROR, "Cloud not get nodeList: %s\n", err)
os.Exit(1)
}
var updateNodes []assets.NodeInfo
for _, node := range nodes {
if SystemOverlay == true && node.SystemOverlay == args[0] {
updateNodes = append(updateNodes, node)
} else if node.RuntimeOverlay == args[0] {
updateNodes = append(updateNodes, node)
}
}
if SystemOverlay == true {
wwlog.Printf(wwlog.INFO, "Updating System Overlays...\n")
return overlay.SystemBuild(updateNodes, true)
} else {
wwlog.Printf(wwlog.INFO, "Updating Runtime Overlays...\n")
return overlay.RuntimeBuild(updateNodes, true)
}
return nil
}

View File

@@ -10,17 +10,18 @@ var (
Short: "Delete Warewulf Overlay files",
Long: "Warewulf Delete overlay files",
RunE: CobraRunE,
Args: cobra.ExactArgs(1),
Args: cobra.MinimumNArgs(1),
Aliases: []string{"rm", "del"},
}
SystemOverlay bool
Force bool
RmEmptyDirs bool
)
func init() {
baseCmd.PersistentFlags().BoolVarP(&SystemOverlay, "system", "s", false, "Show system overlays instead of runtime")
baseCmd.PersistentFlags().BoolVar(&Force, "force", false, "Force deletion of a non-empty overlay")
baseCmd.PersistentFlags().BoolVarP(&Force, "force", "f", false, "Force deletion of a non-empty overlay")
baseCmd.PersistentFlags().BoolVarP(&RmEmptyDirs, "empty", "e", false, "Remove empty directories")
}

View File

@@ -2,12 +2,15 @@ package edit
import (
"fmt"
"github.com/hpcng/warewulf/internal/pkg/assets"
"github.com/hpcng/warewulf/internal/pkg/config"
"github.com/hpcng/warewulf/internal/pkg/overlay"
"github.com/hpcng/warewulf/internal/pkg/util"
"github.com/hpcng/warewulf/internal/pkg/wwlog"
"github.com/spf13/cobra"
"os"
"path"
"path/filepath"
)
func CobraRunE(cmd *cobra.Command, args []string) error {
@@ -16,12 +19,6 @@ func CobraRunE(cmd *cobra.Command, args []string) error {
var overlaySourceDir string
if len(args) < 2 {
fmt.Printf("wwctl overlay edit [overlay name] [overlay file]\n")
cmd.Help()
os.Exit(1)
}
if SystemOverlay == true {
overlaySourceDir = config.SystemOverlaySource(args[0])
} else {
@@ -37,18 +34,75 @@ func CobraRunE(cmd *cobra.Command, args []string) error {
wwlog.Printf(wwlog.DEBUG, "Will edit overlay file: %s\n", overlayFile)
err := os.MkdirAll(path.Dir(overlayFile), 0755)
if CreateDirs == true {
err := os.MkdirAll(path.Dir(overlayFile), 0755)
if err != nil {
wwlog.Printf(wwlog.ERROR, "Could not create directory: %s\n", path.Dir(overlayFile))
os.Exit(1)
}
} else {
if util.IsDir(path.Dir(overlayFile)) == false {
wwlog.Printf(wwlog.ERROR, "Can not create file, parent directory does not exist, try adding the\n")
wwlog.Printf(wwlog.ERROR, "'--parents' option to create the directory.\n")
os.Exit(1)
}
}
if util.IsFile(overlayFile) == false && filepath.Ext(overlayFile) == ".ww" {
wwlog.Printf(wwlog.WARN, "This is a new file, creating some default content\n")
w, err := os.OpenFile(overlayFile, os.O_RDWR|os.O_CREATE, 0644)
if err != nil {
wwlog.Printf(wwlog.WARN, "Could not create file for writing: %s\n", err)
}
fmt.Fprintf(w, "# This is a Warewulf Template file.\n")
fmt.Fprintf(w, "#\n")
fmt.Fprintf(w, "# This file (suffix '.ww') will be automatically rewritten without the suffix\n")
fmt.Fprintf(w, "# when the overlay is rendered for the individual nodes. Here are some examples\n")
fmt.Fprintf(w, "# of macros and logic which can be used within this file:\n")
fmt.Fprintf(w, "#\n")
fmt.Fprintf(w, "# Node FQDN = {{.Fqdn}}\n")
fmt.Fprintf(w, "# Node Group = {{.GroupName}}\n")
fmt.Fprintf(w, "# Network Config = {{.NetDevs.eth0.Ipaddr}}, {{.NetDevs.eth0.Hwaddr}}, etc.\n")
fmt.Fprintf(w, "#\n")
fmt.Fprintf(w, "# Goto the documentation pages for more information: http://www.hpcng.org/...\n")
fmt.Fprintf(w, "\n")
}
err := util.ExecInteractive(editor, overlayFile)
if err != nil {
wwlog.Printf(wwlog.ERROR, "Could not create directory: %s\n", path.Dir(overlayFile))
wwlog.Printf(wwlog.ERROR, "Editor process existed with non-zero\n")
os.Exit(1)
}
if editor == "" {
wwlog.Printf(wwlog.WARN, "No default editor provided, will use `nano`.")
editor = "nano"
// Everything below this point is to update the relevant overlays
nodes, err := assets.FindAllNodes()
if err != nil {
wwlog.Printf(wwlog.ERROR, "Cloud not get nodeList: %s\n", err)
os.Exit(1)
}
return util.ExecInteractive(editor, overlayFile)
var updateNodes []assets.NodeInfo
for _, node := range nodes {
if SystemOverlay == true && node.SystemOverlay == args[0] {
updateNodes = append(updateNodes, node)
} else if node.RuntimeOverlay == args[0] {
updateNodes = append(updateNodes, node)
}
}
if SystemOverlay == true {
wwlog.Printf(wwlog.INFO, "Updating System Overlays...\n")
return overlay.SystemBuild(updateNodes, true)
} else {
wwlog.Printf(wwlog.INFO, "Updating Runtime Overlays...\n")
return overlay.RuntimeBuild(updateNodes, true)
}
return nil
}

View File

@@ -15,12 +15,13 @@ var (
}
SystemOverlay bool
ListFiles bool
CreateDirs bool
)
func init() {
baseCmd.PersistentFlags().BoolVarP(&SystemOverlay, "system", "s", false, "Show system overlays instead of runtime")
baseCmd.PersistentFlags().BoolVarP(&ListFiles, "files", "f", false, "List files contained within a given overlay")
baseCmd.PersistentFlags().BoolVarP(&CreateDirs, "parents", "p", false, "Create any necessary parent directories")
}

View File

@@ -8,6 +8,8 @@ import (
"github.com/hpcng/warewulf/internal/pkg/util"
"github.com/hpcng/warewulf/internal/pkg/wwlog"
"github.com/spf13/cobra"
"os"
"syscall"
)
func CobraRunE(cmd *cobra.Command, args []string) error {
@@ -18,10 +20,18 @@ func CobraRunE(cmd *cobra.Command, args []string) error {
var nodeList []assets.NodeInfo
if SystemOverlay == true {
fmt.Printf("%-25s %-8s %-8s\n", "SYSTEM OVERLAY NAME", "NODES", "FILES")
if ListLong == false {
fmt.Printf("%-30s %-12s %-12s\n", "SYSTEM OVERLAY NAME", "NODES", "FILES/DIRS")
} else {
fmt.Printf("%-10s %5s %-5s %-18s %s\n", "PERM MODE", "UID", "GID", "SYSTEM-OVERLAY", "FILE PATH")
}
o, err = overlay.FindAllSystemOverlays()
} else {
fmt.Printf("%-25s %-8s %-8s\n", "RUNTIME OVERLAY NAME", "NODES", "FILES")
if ListLong == false {
fmt.Printf("%-30s %-12s %-12s\n", "RUNTIME OVERLAY NAME", "NODES", "FILES/DIRS")
} else {
fmt.Printf("%-10s %5s %-5s %-18s %s\n", "PERM MODE", "UID", "GID", "RUNTIME-OVERLAY", "FILE PATH")
}
o, err = overlay.FindAllRuntimeOverlays()
}
if err != nil {
@@ -67,17 +77,32 @@ func CobraRunE(cmd *cobra.Command, args []string) error {
files := util.FindFiles(path)
wwlog.Printf(wwlog.DEBUG, "Iterating overlay path: %s\n", path)
if ListFiles == true {
if ListContents == true {
var fileCount int
for file := range files {
fmt.Printf("%-25s %-8d /%s\n", name, set[name], files[file])
fileCount ++
fmt.Printf("%-30s %-12d /%-12s\n", name, set[name], files[file])
fileCount++
}
if fileCount == 0 {
fmt.Printf("%-25s %-8d %-8d\n", name, set[name], 0)
fmt.Printf("%-30s %-12d %-12d\n", name, set[name], 0)
}
} else if ListLong == true {
for file := range files {
s, err := os.Stat(files[file])
if err != nil {
continue
}
fileMode := s.Mode()
perms := fileMode & os.ModePerm
sys := s.Sys()
fmt.Printf("%v %5d %-5d %-18s /%s\n", perms, sys.(*syscall.Stat_t).Uid, sys.(*syscall.Stat_t).Gid, o[overlay], files[file])
}
} else {
fmt.Printf("%-25s %-8d %-8d\n", name, set[name], len(files))
fmt.Printf("%-30s %-12d %-12d\n", name, set[name], len(files))
}
} else {

View File

@@ -10,14 +10,17 @@ var (
Short: "List Warewulf Overlays",
Long: "Warewulf List overlay",
RunE: CobraRunE,
Aliases: []string{"ls"},
}
SystemOverlay bool
ListFiles bool
ListContents bool
ListLong bool
)
func init() {
baseCmd.PersistentFlags().BoolVarP(&SystemOverlay, "system", "s", false, "Show system overlays instead of runtime")
baseCmd.PersistentFlags().BoolVarP(&ListFiles, "files", "f", false, "List files contained within a given overlay")
baseCmd.PersistentFlags().BoolVarP(&ListContents, "all", "a", false, "List the contents of overlays")
baseCmd.PersistentFlags().BoolVarP(&ListLong, "long", "l", false, "List 'long' of all overlay contents")
}

View File

@@ -0,0 +1,71 @@
package mkdir
import (
"fmt"
"github.com/hpcng/warewulf/internal/pkg/assets"
"github.com/hpcng/warewulf/internal/pkg/config"
"github.com/hpcng/warewulf/internal/pkg/overlay"
"github.com/hpcng/warewulf/internal/pkg/util"
"github.com/hpcng/warewulf/internal/pkg/wwlog"
"github.com/spf13/cobra"
"os"
"path"
)
func CobraRunE(cmd *cobra.Command, args []string) error {
config := config.New()
var overlaySourceDir string
// mode := uint32(strconv.ParseUint(PermMode, 8, 32))
if SystemOverlay == true {
overlaySourceDir = config.SystemOverlaySource(args[0])
} else {
overlaySourceDir = config.RuntimeOverlaySource(args[0])
}
if util.IsDir(overlaySourceDir) == false {
wwlog.Printf(wwlog.ERROR, "Overlay does not exist: %s\n", args[0])
os.Exit(1)
}
overlayDir := path.Join(overlaySourceDir, args[1])
wwlog.Printf(wwlog.DEBUG, "Will create directory in overlay: %s:%s\n", args[0], overlayDir)
err := os.MkdirAll(overlayDir, 0755)
if err != nil {
wwlog.Printf(wwlog.ERROR, "Could not create directory: %s\n", path.Dir(overlayDir))
os.Exit(1)
}
fmt.Printf("Created directory within overlay: %s:%s\n", args[0], args[1])
// Everything below this point is to update the relevant overlays
nodes, err := assets.FindAllNodes()
if err != nil {
wwlog.Printf(wwlog.ERROR, "Cloud not get nodeList: %s\n", err)
os.Exit(1)
}
var updateNodes []assets.NodeInfo
for _, node := range nodes {
if SystemOverlay == true && node.SystemOverlay == args[0] {
updateNodes = append(updateNodes, node)
} else if node.RuntimeOverlay == args[0] {
updateNodes = append(updateNodes, node)
}
}
if SystemOverlay == true {
wwlog.Printf(wwlog.INFO, "Updating System Overlays...\n")
return overlay.SystemBuild(updateNodes, true)
} else {
wwlog.Printf(wwlog.INFO, "Updating Runtime Overlays...\n")
return overlay.RuntimeBuild(updateNodes, true)
}
return nil
}

View File

@@ -0,0 +1,28 @@
package mkdir
import (
"github.com/spf13/cobra"
)
var (
baseCmd = &cobra.Command{
Use: "mkdir [overlay name] [directory path]",
Short: "Create a new directory",
Long: "Create a new directory within a Warewulf overlay",
RunE: CobraRunE,
Args: cobra.MinimumNArgs(2),
}
SystemOverlay bool
// PermMode os.FileMode
)
func init() {
baseCmd.PersistentFlags().BoolVarP(&SystemOverlay, "system", "s", false, "Show System Overlays as well")
// This will be added back as soon as I figure out how to properly handle the FileMode case
// baseCmd.PersistentFlags().Uint32VarP(&PermMode, "mode", "m", 0755, "Permission mode for directory")
}
// GetRootCommand returns the root cobra.Command for the application.
func GetCommand() *cobra.Command {
return baseCmd
}

View File

@@ -1,10 +1,13 @@
package overlay
import (
"github.com/hpcng/warewulf/internal/app/wwctl/overlay/build"
"github.com/hpcng/warewulf/internal/app/wwctl/overlay/copy"
"github.com/hpcng/warewulf/internal/app/wwctl/overlay/create"
"github.com/hpcng/warewulf/internal/app/wwctl/overlay/delete"
"github.com/hpcng/warewulf/internal/app/wwctl/overlay/edit"
"github.com/hpcng/warewulf/internal/app/wwctl/overlay/list"
"github.com/hpcng/warewulf/internal/app/wwctl/overlay/mkdir"
"github.com/hpcng/warewulf/internal/app/wwctl/overlay/show"
"github.com/spf13/cobra"
@@ -27,6 +30,9 @@ func init() {
baseCmd.AddCommand(create.GetCommand())
baseCmd.AddCommand(edit.GetCommand())
baseCmd.AddCommand(delete.GetCommand())
baseCmd.AddCommand(mkdir.GetCommand())
baseCmd.AddCommand(build.GetCommand())
baseCmd.AddCommand(copy.GetCommand())
}

View File

@@ -53,6 +53,9 @@ func init() {
if c.LocalStateDir == "" {
c.LocalStateDir = "/var/warewulf"
}
if c.Editor == "" {
c.Editor = "vi"
}
util.ValidateOrDie("warewulf.conf", "warewulfd ipaddr", c.Ipaddr, "^[0-9]+.[0-9]+.[0-9]+.[0-9]+$")
util.ValidateOrDie("warewulf.conf", "system config dir", c.SysConfDir, "^[a-zA-Z0-9-._:/]+$")
@@ -82,9 +85,14 @@ func (self *Config) RuntimeOverlayDir() string {
}
func (self *Config) SystemOverlaySource(overlayName string) string {
if overlayName == "" {
wwlog.Printf(wwlog.ERROR, "System overlay name is not defined\n")
return ""
}
if util.TaintCheck(overlayName, "^[a-zA-Z0-9-._]+$") == false {
wwlog.Printf(wwlog.ERROR, "System overlay name contains illegal characters: %s\n", overlayName)
os.Exit(1)
return ""
}
return path.Join(self.SystemOverlayDir(), overlayName)
@@ -92,63 +100,98 @@ func (self *Config) SystemOverlaySource(overlayName string) string {
func (self *Config) RuntimeOverlaySource(overlayName string) string {
if overlayName == "" {
wwlog.Printf(wwlog.ERROR, "Runtime overlay name is not defined\n")
return ""
}
if util.TaintCheck(overlayName, "^[a-zA-Z0-9-._]+$") == false {
wwlog.Printf(wwlog.ERROR, "Runtime overlay name contains illegal characters: %s\n", overlayName)
os.Exit(1)
return ""
}
return path.Join(self.RuntimeOverlayDir(), overlayName)
}
func (self *Config) KernelImage(kernelVersion string) string {
if kernelVersion == "" {
wwlog.Printf(wwlog.ERROR, "Kernel Version is not defined\n")
return ""
}
if util.TaintCheck(kernelVersion, "^[a-zA-Z0-9-._]+$") == false {
wwlog.Printf(wwlog.ERROR, "Runtime overlay name contains illegal characters: %s\n", kernelVersion)
os.Exit(1)
return ""
}
return fmt.Sprintf("%s/provision/kernel/vmlinuz-%s", self.LocalStateDir, kernelVersion)
}
func (self *Config) KmodsImage(kernelVersion string) string {
if kernelVersion == "" {
wwlog.Printf(wwlog.ERROR, "Kernel Version is not defined\n")
return ""
}
if util.TaintCheck(kernelVersion, "^[a-zA-Z0-9-._]+$") == false {
wwlog.Printf(wwlog.ERROR, "Runtime overlay name contains illegal characters: %s\n", kernelVersion)
os.Exit(1)
return ""
}
return fmt.Sprintf("%s/provision/kernel/kmods-%s.img", self.LocalStateDir, kernelVersion)
}
func (self *Config) VnfsImage(vnfsNameClean string) string {
if vnfsNameClean == "" {
wwlog.Printf(wwlog.ERROR, "VNFS name is not defined\n")
return ""
}
if util.TaintCheck(vnfsNameClean, "^[a-zA-Z0-9-._:]+$") == false {
wwlog.Printf(wwlog.ERROR, "Runtime overlay name contains illegal characters: %s\n", vnfsNameClean)
os.Exit(1)
return ""
}
return fmt.Sprintf("%s/provision/vnfs/%s.img.gz", self.LocalStateDir, vnfsNameClean)
}
func (self *Config) SystemOverlayImage(nodeName string) string {
if nodeName == "" {
wwlog.Printf(wwlog.ERROR, "Node name is not defined\n")
return ""
}
if util.TaintCheck(nodeName, "^[a-zA-Z0-9-._:]+$") == false {
wwlog.Printf(wwlog.ERROR, "System overlay name contains illegal characters: %s\n", nodeName)
os.Exit(1)
return ""
}
return fmt.Sprintf("%s/provision/overlays/system/%s.img", self.LocalStateDir, nodeName)
}
func (self *Config) RuntimeOverlayImage(nodeName string) string {
if nodeName == "" {
wwlog.Printf(wwlog.ERROR, "Node name is not defined\n")
return ""
}
if util.TaintCheck(nodeName, "^[a-zA-Z0-9-._:]+$") == false {
wwlog.Printf(wwlog.ERROR, "System overlay name contains illegal characters: %s\n", nodeName)
os.Exit(1)
return ""
}
return fmt.Sprintf("%s/provision/overlays/runtime/%s.img", self.LocalStateDir, nodeName)
}
func (self *Config) VnfsChroot(vnfsNameClean string) string {
if vnfsNameClean == "" {
wwlog.Printf(wwlog.ERROR, "VNFS name is not defined\n")
return ""
}
if util.TaintCheck(vnfsNameClean, "^[a-zA-Z0-9-._:]+$") == false {
wwlog.Printf(wwlog.ERROR, "Runtime overlay name contains illegal characters: %s\n", vnfsNameClean)
os.Exit(1)
return ""
}
return fmt.Sprintf("%s/chroot/%s.img", self.LocalStateDir, vnfsNameClean)

View File

@@ -1,3 +1,42 @@
package overlay
//Shared code will go here....
import (
"github.com/hpcng/warewulf/internal/pkg/config"
"github.com/hpcng/warewulf/internal/pkg/util"
"github.com/hpcng/warewulf/internal/pkg/wwlog"
"github.com/hpcng/warewulf/internal/pkg/vnfs"
"io/ioutil"
"path"
"strings"
)
func templateFileInclude(path string) string {
wwlog.Printf(wwlog.DEBUG, "Including file into template: %s\n", path)
content, err := ioutil.ReadFile(path)
if err != nil {
wwlog.Printf(wwlog.ERROR, "Template include: %s\n", err)
}
return strings.TrimSuffix(string(content), "\n")
}
func templateVnfsFileInclude(vnfsname string, filepath string) string {
wwlog.Printf(wwlog.DEBUG, "Including VNFS file into template: %s: %s\n", vnfsname, filepath)
config := config.New()
v := vnfs.New(vnfsname)
vnfsdir := config.VnfsChroot(v.NameClean())
if util.IsDir(vnfsdir) == false {
wwlog.Printf(wwlog.WARN, "Could not include file from non-existent VNFS cache: %s:%s\n", vnfsname, filepath)
return ""
}
wwlog.Printf(wwlog.DEBUG, "IncludeVnfs file from: %s/%s\n", vnfsdir, filepath)
content, err := ioutil.ReadFile(path.Join(vnfsdir, filepath))
if err != nil {
wwlog.Printf(wwlog.ERROR, "Template include: %s\n", err)
}
return strings.TrimSuffix(string(content), "\n")
}

View File

@@ -1,12 +1,20 @@
package overlay
import (
"fmt"
"github.com/hpcng/warewulf/internal/pkg/assets"
"github.com/hpcng/warewulf/internal/pkg/config"
"github.com/hpcng/warewulf/internal/pkg/errors"
"github.com/hpcng/warewulf/internal/pkg/util"
"github.com/hpcng/warewulf/internal/pkg/wwlog"
"io/ioutil"
"os"
"os/exec"
"path"
"path/filepath"
"regexp"
"strings"
"text/template"
)
func FindAllRuntimeOverlays() ([]string, error) {
@@ -42,4 +50,123 @@ func RuntimeOverlayInit(name string) error {
err := os.MkdirAll(path, 0755)
return err
}
}
func RuntimeBuild(nodeList []assets.NodeInfo, force bool) error {
config := config.New()
wwlog.SetIndent(4)
for _, node := range nodeList {
if node.RuntimeOverlay != "" {
OverlayDir := config.RuntimeOverlaySource(node.RuntimeOverlay)
OverlayFile := config.RuntimeOverlayImage(node.Fqdn)
wwlog.Printf(wwlog.VERBOSE, "Building Runtime Overlay for: %s\n", node.Fqdn)
tmpDir, err := ioutil.TempDir(os.TempDir(), ".wwctl-runtime-overlay-")
if err != nil {
return err
}
if util.IsDir(OverlayDir) == false {
wwlog.Printf(wwlog.WARN, "Skipping non-existent overlay source: %s\n", OverlayDir)
continue
}
err = os.MkdirAll(path.Dir(OverlayFile), 0755)
if err != nil {
return err
}
if force == false {
wwlog.Printf(wwlog.DEBUG, "Checking if overlay is required\n")
}
if util.PathIsNewer(OverlayDir, OverlayFile) {
if force == false {
wwlog.Printf(wwlog.INFO, "%-35s: Skipping, overlay is current\n", node.Fqdn)
continue
}
}
wwlog.Printf(wwlog.DEBUG, "Changing directory to OverlayDir: %s\n", OverlayDir)
err = os.Chdir(OverlayDir)
if err != nil {
wwlog.Printf(wwlog.ERROR, "Could not chdir() to OverlayDir: %s\n", OverlayDir)
continue
}
wwlog.Printf(wwlog.DEBUG, "Walking the file system: %s\n", OverlayDir)
err = filepath.Walk(".", func(location string, info os.FileInfo, err error) error {
if err != nil {
return err
}
if info.IsDir() {
wwlog.Printf(wwlog.DEBUG, "Found directory: %s\n", location)
err := os.MkdirAll(path.Join(tmpDir, location), info.Mode())
if err != nil {
wwlog.Printf(wwlog.ERROR, "%s\n", err)
return err
}
} else if filepath.Ext(location) == ".ww" {
wwlog.Printf(wwlog.DEBUG, "Found template file: %s\n", location)
destFile := strings.TrimSuffix(location, ".ww")
tmpl, err := template.New(path.Base(location)).Funcs(template.FuncMap{"Include": templateFileInclude, "IncludeVnfs": templateVnfsFileInclude}).ParseGlob(path.Join(OverlayDir, destFile + ".ww*"))
if err != nil {
wwlog.Printf(wwlog.ERROR, "%s\n", err)
return err
}
w, err := os.OpenFile(path.Join(tmpDir, destFile), os.O_RDWR|os.O_CREATE, info.Mode())
if err != nil {
wwlog.Printf(wwlog.ERROR, "%s\n", err)
return err
}
defer w.Close()
err = tmpl.Execute(w, node)
if err != nil {
wwlog.Printf(wwlog.ERROR, "%s\n", err)
return err
}
} else if b, _ := regexp.MatchString(`\.ww[a-zA-Z0-9\-\._]*$`, location); b == true {
wwlog.Printf(wwlog.DEBUG, "Ignoring WW template file: %s\n", location)
} else {
wwlog.Printf(wwlog.DEBUG, "Found file: %s\n", location)
err := util.CopyFile(path.Join(OverlayDir, location), path.Join(tmpDir, location))
if err != nil {
wwlog.Printf(wwlog.ERROR, "%s\n", err)
return err
}
}
return nil
})
wwlog.Printf(wwlog.VERBOSE, "Finished generating overlay directory for: %s\n", node.Fqdn)
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)
continue
}
wwlog.Printf(wwlog.INFO, "%-35s: Done\n", node.Fqdn)
wwlog.Printf(wwlog.DEBUG, "Removing temporary directory: %s\n", tmpDir)
os.RemoveAll(tmpDir)
}
}
wwlog.SetIndent(0)
return nil
}

View File

@@ -1,12 +1,20 @@
package overlay
import (
"fmt"
"github.com/hpcng/warewulf/internal/pkg/assets"
"github.com/hpcng/warewulf/internal/pkg/config"
"github.com/hpcng/warewulf/internal/pkg/errors"
"github.com/hpcng/warewulf/internal/pkg/util"
"github.com/hpcng/warewulf/internal/pkg/wwlog"
"io/ioutil"
"os"
"os/exec"
"path"
"path/filepath"
"regexp"
"strings"
"text/template"
)
func FindAllSystemOverlays() ([]string, error) {
@@ -42,4 +50,123 @@ func SystemOverlayInit(name string) error {
err := os.MkdirAll(path, 0755)
return err
}
func SystemBuild(nodeList []assets.NodeInfo, force bool) error {
config := config.New()
wwlog.SetIndent(4)
for _, node := range nodeList {
if node.SystemOverlay != "" {
OverlayDir := config.SystemOverlaySource(node.SystemOverlay)
OverlayFile := config.SystemOverlayImage(node.Fqdn)
wwlog.Printf(wwlog.VERBOSE, "Building System Overlay for: %s\n", node.Fqdn)
tmpDir, err := ioutil.TempDir(os.TempDir(), ".wwctl-system-overlay-")
if err != nil {
return err
}
if util.IsDir(OverlayDir) == false {
wwlog.Printf(wwlog.WARN, "Skipping non-existent overlay source: %s\n", OverlayDir)
continue
}
err = os.MkdirAll(path.Dir(OverlayFile), 0755)
if err != nil {
return err
}
if force == false {
wwlog.Printf(wwlog.DEBUG, "Checking if overlay is required\n")
}
if util.PathIsNewer(OverlayDir, OverlayFile) {
if force == false {
wwlog.Printf(wwlog.INFO, "%-35s: Skipping, overlay is current\n", node.Fqdn)
continue
}
}
wwlog.Printf(wwlog.DEBUG, "Changing directory to OverlayDir: %s\n", OverlayDir)
err = os.Chdir(OverlayDir)
if err != nil {
wwlog.Printf(wwlog.ERROR, "Could not chdir() to OverlayDir: %s\n", OverlayDir)
continue
}
wwlog.Printf(wwlog.DEBUG, "Walking the file system: %s\n", OverlayDir)
err = filepath.Walk(".", func(location string, info os.FileInfo, err error) error {
if err != nil {
return err
}
if info.IsDir() {
wwlog.Printf(wwlog.DEBUG, "Found directory: %s\n", location)
err := os.MkdirAll(path.Join(tmpDir, location), info.Mode())
if err != nil {
wwlog.Printf(wwlog.ERROR, "%s\n", err)
return err
}
} else if filepath.Ext(location) == ".ww" {
wwlog.Printf(wwlog.DEBUG, "Found template file: %s\n", location)
destFile := strings.TrimSuffix(location, ".ww")
tmpl, err := template.New(path.Base(location)).Funcs(template.FuncMap{"Include": templateFileInclude, "IncludeVnfs": templateVnfsFileInclude}).ParseGlob(path.Join(OverlayDir, destFile + ".ww*"))
if err != nil {
wwlog.Printf(wwlog.ERROR, "%s\n", err)
return err
}
w, err := os.OpenFile(path.Join(tmpDir, destFile), os.O_RDWR|os.O_CREATE, info.Mode())
if err != nil {
wwlog.Printf(wwlog.ERROR, "%s\n", err)
return err
}
defer w.Close()
err = tmpl.Execute(w, node)
if err != nil {
wwlog.Printf(wwlog.ERROR, "%s\n", err)
return err
}
} else if b, _ := regexp.MatchString(`\.ww[a-zA-Z0-9\-\._]*$`, location); b == true {
wwlog.Printf(wwlog.DEBUG, "Ignoring WW template file: %s\n", location)
} else {
wwlog.Printf(wwlog.DEBUG, "Found file: %s\n", location)
err := util.CopyFile(path.Join(OverlayDir, location), path.Join(tmpDir, location))
if err != nil {
wwlog.Printf(wwlog.ERROR, "%s\n", err)
return err
}
}
return nil
})
wwlog.Printf(wwlog.VERBOSE, "Finished generating overlay directory for: %s\n", node.Fqdn)
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 system image overlay: %s\n", err)
continue
}
wwlog.Printf(wwlog.INFO, "%-35s: Done\n", node.Fqdn)
wwlog.Printf(wwlog.DEBUG, "Removing temporary directory: %s\n", tmpDir)
os.RemoveAll(tmpDir)
}
}
wwlog.SetIndent(0)
return nil
}

View File

@@ -92,6 +92,13 @@ func IsDir(path string) (bool) {
return false
}
func IsFile(path string) (bool) {
if _, err := os.Stat(path); err == nil {
return true
}
return false
}
func TaintCheck(pattern string, expr string) bool {
if b, _ := regexp.MatchString(expr, pattern); b == true {
@@ -122,10 +129,18 @@ func FindFiles(path string) []string {
return err
}
if IsDir(location) == false {
wwlog.Printf(wwlog.DEBUG, "FindFiles() found: %s\n", location)
if location == "." {
return nil
}
if IsDir(location) == true {
wwlog.Printf(wwlog.DEBUG, "FindFiles() found directory: %s\n", location)
ret = append(ret, location +"/")
} else {
wwlog.Printf(wwlog.DEBUG, "FindFiles() found file: %s\n", location)
ret = append(ret, location)
}
return nil
})
if err != nil {