Merge pull request #467 from mslacken/single-Overlay
enable overlay rendering
This commit is contained in:
@@ -1,6 +1,7 @@
|
|||||||
package chmod
|
package chmod
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"github.com/hpcng/warewulf/internal/pkg/overlay"
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -13,6 +14,13 @@ var (
|
|||||||
Example: "wwctl overlay chmod default /etc/hostname.ww 0660",
|
Example: "wwctl overlay chmod default /etc/hostname.ww 0660",
|
||||||
RunE: CobraRunE,
|
RunE: CobraRunE,
|
||||||
Args: cobra.ExactArgs(3),
|
Args: cobra.ExactArgs(3),
|
||||||
|
ValidArgsFunction: func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) {
|
||||||
|
if len(args) != 0 {
|
||||||
|
return nil, cobra.ShellCompDirectiveNoFileComp
|
||||||
|
}
|
||||||
|
list, _ := overlay.FindOverlays()
|
||||||
|
return list, cobra.ShellCompDirectiveNoFileComp
|
||||||
|
},
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,9 @@
|
|||||||
package chown
|
package chown
|
||||||
|
|
||||||
import "github.com/spf13/cobra"
|
import (
|
||||||
|
"github.com/hpcng/warewulf/internal/pkg/overlay"
|
||||||
|
"github.com/spf13/cobra"
|
||||||
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
baseCmd = &cobra.Command{
|
baseCmd = &cobra.Command{
|
||||||
@@ -10,6 +13,13 @@ var (
|
|||||||
Long: "This command changes the ownership of a FILE within the system or runtime OVERLAY_NAME\nto the user specified by UID. Optionally, it will also change group ownership to GID.",
|
Long: "This command changes the ownership of a FILE within the system or runtime OVERLAY_NAME\nto the user specified by UID. Optionally, it will also change group ownership to GID.",
|
||||||
RunE: CobraRunE,
|
RunE: CobraRunE,
|
||||||
Args: cobra.RangeArgs(3, 4),
|
Args: cobra.RangeArgs(3, 4),
|
||||||
|
ValidArgsFunction: func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) {
|
||||||
|
if len(args) != 0 {
|
||||||
|
return nil, cobra.ShellCompDirectiveNoFileComp
|
||||||
|
}
|
||||||
|
list, _ := overlay.FindOverlays()
|
||||||
|
return list, cobra.ShellCompDirectiveNoFileComp
|
||||||
|
},
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
package delete
|
package delete
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"github.com/hpcng/warewulf/internal/pkg/overlay"
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -13,6 +14,13 @@ var (
|
|||||||
RunE: CobraRunE,
|
RunE: CobraRunE,
|
||||||
Args: cobra.RangeArgs(1, 2),
|
Args: cobra.RangeArgs(1, 2),
|
||||||
Aliases: []string{"rm", "del"},
|
Aliases: []string{"rm", "del"},
|
||||||
|
ValidArgsFunction: func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) {
|
||||||
|
if len(args) != 0 {
|
||||||
|
return nil, cobra.ShellCompDirectiveNoFileComp
|
||||||
|
}
|
||||||
|
list, _ := overlay.FindOverlays()
|
||||||
|
return list, cobra.ShellCompDirectiveNoFileComp
|
||||||
|
},
|
||||||
}
|
}
|
||||||
Force bool
|
Force bool
|
||||||
Parents bool
|
Parents bool
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
package edit
|
package edit
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"github.com/hpcng/warewulf/internal/pkg/overlay"
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -12,6 +13,13 @@ var (
|
|||||||
Long: "This command will open the FILE for editing or create a new file within the\nOVERLAY_NAME. Note: files created with a '.ww' suffix will always be\nparsed as Warewulf template files, and the suffix will be removed automatically.",
|
Long: "This command will open the FILE for editing or create a new file within the\nOVERLAY_NAME. Note: files created with a '.ww' suffix will always be\nparsed as Warewulf template files, and the suffix will be removed automatically.",
|
||||||
RunE: CobraRunE,
|
RunE: CobraRunE,
|
||||||
Args: cobra.ExactArgs(2),
|
Args: cobra.ExactArgs(2),
|
||||||
|
ValidArgsFunction: func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) {
|
||||||
|
if len(args) != 0 {
|
||||||
|
return nil, cobra.ShellCompDirectiveNoFileComp
|
||||||
|
}
|
||||||
|
list, _ := overlay.FindOverlays()
|
||||||
|
return list, cobra.ShellCompDirectiveNoFileComp
|
||||||
|
},
|
||||||
}
|
}
|
||||||
ListFiles bool
|
ListFiles bool
|
||||||
CreateDirs bool
|
CreateDirs bool
|
||||||
|
|||||||
@@ -1,6 +1,9 @@
|
|||||||
package imprt
|
package imprt
|
||||||
|
|
||||||
import "github.com/spf13/cobra"
|
import (
|
||||||
|
"github.com/hpcng/warewulf/internal/pkg/overlay"
|
||||||
|
"github.com/spf13/cobra"
|
||||||
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
baseCmd = &cobra.Command{
|
baseCmd = &cobra.Command{
|
||||||
@@ -11,6 +14,13 @@ var (
|
|||||||
RunE: CobraRunE,
|
RunE: CobraRunE,
|
||||||
Args: cobra.RangeArgs(2, 3),
|
Args: cobra.RangeArgs(2, 3),
|
||||||
Aliases: []string{"cp"},
|
Aliases: []string{"cp"},
|
||||||
|
ValidArgsFunction: func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) {
|
||||||
|
if len(args) != 0 {
|
||||||
|
return nil, cobra.ShellCompDirectiveNoFileComp
|
||||||
|
}
|
||||||
|
list, _ := overlay.FindOverlays()
|
||||||
|
return list, cobra.ShellCompDirectiveNoFileComp
|
||||||
|
},
|
||||||
}
|
}
|
||||||
PermMode int32
|
PermMode int32
|
||||||
NoOverlayUpdate bool
|
NoOverlayUpdate bool
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
package list
|
package list
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"github.com/hpcng/warewulf/internal/pkg/overlay"
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -14,6 +15,13 @@ var (
|
|||||||
Args: cobra.MinimumNArgs(0),
|
Args: cobra.MinimumNArgs(0),
|
||||||
Aliases: []string{"ls"},
|
Aliases: []string{"ls"},
|
||||||
ValidArgs: []string{"system", "runtime"},
|
ValidArgs: []string{"system", "runtime"},
|
||||||
|
ValidArgsFunction: func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) {
|
||||||
|
if len(args) != 0 {
|
||||||
|
return nil, cobra.ShellCompDirectiveNoFileComp
|
||||||
|
}
|
||||||
|
list, _ := overlay.FindOverlays()
|
||||||
|
return list, cobra.ShellCompDirectiveNoFileComp
|
||||||
|
},
|
||||||
}
|
}
|
||||||
ListContents bool
|
ListContents bool
|
||||||
ListLong bool
|
ListLong bool
|
||||||
|
|||||||
@@ -17,9 +17,9 @@ import (
|
|||||||
var (
|
var (
|
||||||
baseCmd = &cobra.Command{
|
baseCmd = &cobra.Command{
|
||||||
DisableFlagsInUseLine: true,
|
DisableFlagsInUseLine: true,
|
||||||
Use: "overlay COMMAND [OPTIONS]",
|
Use: "overlay COMMAND [OPTIONS]",
|
||||||
Short: "Warewulf Overlay Management",
|
Short: "Warewulf Overlay Management",
|
||||||
Long: "Management interface for Warewulf overlays",
|
Long: "Management interface for Warewulf overlays",
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -34,6 +34,7 @@ func init() {
|
|||||||
baseCmd.AddCommand(imprt.GetCommand())
|
baseCmd.AddCommand(imprt.GetCommand())
|
||||||
baseCmd.AddCommand(chmod.GetCommand())
|
baseCmd.AddCommand(chmod.GetCommand())
|
||||||
baseCmd.AddCommand(chown.GetCommand())
|
baseCmd.AddCommand(chown.GetCommand())
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetRootCommand returns the root cobra.Command for the application.
|
// GetRootCommand returns the root cobra.Command for the application.
|
||||||
|
|||||||
@@ -1,11 +1,17 @@
|
|||||||
package show
|
package show
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bufio"
|
||||||
|
"bytes"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"os"
|
"os"
|
||||||
"path"
|
"path"
|
||||||
|
"path/filepath"
|
||||||
|
"regexp"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/hpcng/warewulf/internal/pkg/node"
|
||||||
"github.com/hpcng/warewulf/internal/pkg/overlay"
|
"github.com/hpcng/warewulf/internal/pkg/overlay"
|
||||||
"github.com/hpcng/warewulf/internal/pkg/util"
|
"github.com/hpcng/warewulf/internal/pkg/util"
|
||||||
"github.com/hpcng/warewulf/internal/pkg/wwlog"
|
"github.com/hpcng/warewulf/internal/pkg/wwlog"
|
||||||
@@ -17,7 +23,6 @@ func CobraRunE(cmd *cobra.Command, args []string) error {
|
|||||||
|
|
||||||
overlayName := args[0]
|
overlayName := args[0]
|
||||||
fileName := args[1]
|
fileName := args[1]
|
||||||
|
|
||||||
overlaySourceDir = overlay.OverlaySourceDir(overlayName)
|
overlaySourceDir = overlay.OverlaySourceDir(overlayName)
|
||||||
|
|
||||||
if !util.IsDir(overlaySourceDir) {
|
if !util.IsDir(overlaySourceDir) {
|
||||||
@@ -32,13 +37,77 @@ func CobraRunE(cmd *cobra.Command, args []string) error {
|
|||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
}
|
}
|
||||||
|
|
||||||
f, err := ioutil.ReadFile(overlayFile)
|
if NodeName == "" {
|
||||||
if err != nil {
|
f, err := ioutil.ReadFile(overlayFile)
|
||||||
wwlog.Printf(wwlog.ERROR, "Could not read file: %s\n", err)
|
if err != nil {
|
||||||
os.Exit(1)
|
wwlog.Printf(wwlog.ERROR, "Could not read file: %s\n", err)
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Print(string(f))
|
||||||
|
} else {
|
||||||
|
var host node.NodeInfo
|
||||||
|
nodeDB, err := node.New()
|
||||||
|
if err != nil {
|
||||||
|
wwlog.Printf(wwlog.ERROR, "Could not open node configuration: %s\n", err)
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
nodes, err := nodeDB.FindAllNodes()
|
||||||
|
if err != nil {
|
||||||
|
wwlog.Printf(wwlog.ERROR, "Could not get node list: %s\n", err)
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
node := node.FilterByName(nodes, []string{NodeName})
|
||||||
|
if len(node) != 1 {
|
||||||
|
wwlog.Printf(wwlog.ERROR, "%v does not identify a single node\n", NodeName)
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
host = node[0]
|
||||||
|
|
||||||
|
if !util.IsFile(args[0]) {
|
||||||
|
wwlog.Printf(wwlog.ERROR, "%s is not a file\n", args[0])
|
||||||
|
}
|
||||||
|
tstruct := overlay.InitStruct(host)
|
||||||
|
tstruct.BuildSource = args[0]
|
||||||
|
buffer, backupFile, writeFile, err := overlay.RenderTemplateFile(overlayFile, tstruct)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if filepath.Ext(args[0]) != ".ww" {
|
||||||
|
wwlog.Printf(wwlog.WARN, "%s has not the '.ww' so wont be rendered if in overlay\n", args[0])
|
||||||
|
}
|
||||||
|
var outBuffer bytes.Buffer
|
||||||
|
// search for magic file name comment
|
||||||
|
bufferScanner := bufio.NewScanner(bytes.NewReader(buffer.Bytes()))
|
||||||
|
bufferScanner.Split(overlay.ScanLines)
|
||||||
|
reg := regexp.MustCompile(`.*{{\s*/\*\s*file\s*["'](.*)["']\s*\*/\s*}}.*`)
|
||||||
|
foundFileComment := false
|
||||||
|
destFileName := strings.TrimSuffix(args[0], ".ww")
|
||||||
|
for bufferScanner.Scan() {
|
||||||
|
line := bufferScanner.Text()
|
||||||
|
filenameFromTemplate := reg.FindAllStringSubmatch(line, -1)
|
||||||
|
if len(filenameFromTemplate) != 0 {
|
||||||
|
wwlog.Printf(wwlog.DEBUG, "Found multifile comment, new filename %s\n", filenameFromTemplate[0][1])
|
||||||
|
if foundFileComment {
|
||||||
|
if !Quiet {
|
||||||
|
wwlog.Printf(wwlog.INFO, "backupFile: %v\nwriteFile: %v\n", backupFile, writeFile)
|
||||||
|
wwlog.Printf(wwlog.INFO, "Filename: %s\n\n", destFileName)
|
||||||
|
}
|
||||||
|
wwlog.Printf(wwlog.INFO, "%s", outBuffer.String())
|
||||||
|
outBuffer.Reset()
|
||||||
|
}
|
||||||
|
destFileName = filenameFromTemplate[0][1]
|
||||||
|
foundFileComment = true
|
||||||
|
} else {
|
||||||
|
_, _ = outBuffer.WriteString(line)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if !Quiet {
|
||||||
|
wwlog.Printf(wwlog.INFO, "backupFile: %v\nwriteFile: %v\n", backupFile, writeFile)
|
||||||
|
wwlog.Printf(wwlog.INFO, "Filename: %s\n\n", destFileName)
|
||||||
|
}
|
||||||
|
wwlog.Printf(wwlog.INFO, "%s", outBuffer.String())
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fmt.Print(string(f))
|
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,10 @@
|
|||||||
package show
|
package show
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"log"
|
||||||
|
|
||||||
|
"github.com/hpcng/warewulf/internal/pkg/node"
|
||||||
|
"github.com/hpcng/warewulf/internal/pkg/overlay"
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -13,10 +17,32 @@ var (
|
|||||||
RunE: CobraRunE,
|
RunE: CobraRunE,
|
||||||
Aliases: []string{"cat"},
|
Aliases: []string{"cat"},
|
||||||
Args: cobra.ExactArgs(2),
|
Args: cobra.ExactArgs(2),
|
||||||
|
ValidArgsFunction: func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) {
|
||||||
|
if len(args) != 0 {
|
||||||
|
return nil, cobra.ShellCompDirectiveNoFileComp
|
||||||
|
}
|
||||||
|
list, _ := overlay.FindOverlays()
|
||||||
|
return list, cobra.ShellCompDirectiveNoFileComp
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
NodeName string
|
||||||
|
Quiet bool
|
||||||
)
|
)
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
|
baseCmd.PersistentFlags().StringVarP(&NodeName, "render", "r", "", "node used for the variables in the template")
|
||||||
|
if err := baseCmd.RegisterFlagCompletionFunc("render", func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) {
|
||||||
|
nodeDB, _ := node.New()
|
||||||
|
nodes, _ := nodeDB.FindAllNodes()
|
||||||
|
var node_names []string
|
||||||
|
for _, node := range nodes {
|
||||||
|
node_names = append(node_names, node.Id.Get())
|
||||||
|
}
|
||||||
|
return node_names, cobra.ShellCompDirectiveNoFileComp
|
||||||
|
}); err != nil {
|
||||||
|
log.Println(err)
|
||||||
|
}
|
||||||
|
baseCmd.PersistentFlags().BoolVarP(&Quiet, "quiet", "q", false, "do not print information if multiple, backup files are written")
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetRootCommand returns the root cobra.Command for the application.
|
// GetRootCommand returns the root cobra.Command for the application.
|
||||||
|
|||||||
@@ -1,8 +1,14 @@
|
|||||||
package overlay
|
package overlay
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"net"
|
||||||
|
"os"
|
||||||
|
"strconv"
|
||||||
|
"time"
|
||||||
|
|
||||||
"github.com/hpcng/warewulf/internal/pkg/node"
|
"github.com/hpcng/warewulf/internal/pkg/node"
|
||||||
"github.com/hpcng/warewulf/internal/pkg/warewulfconf"
|
"github.com/hpcng/warewulf/internal/pkg/warewulfconf"
|
||||||
|
"github.com/hpcng/warewulf/internal/pkg/wwlog"
|
||||||
)
|
)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -38,3 +44,105 @@ type TemplateStruct struct {
|
|||||||
Nfs warewulfconf.NfsConf
|
Nfs warewulfconf.NfsConf
|
||||||
Warewulf warewulfconf.WarewulfConf
|
Warewulf warewulfconf.WarewulfConf
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Initialize an TemplateStruct with the given node.NodeInfo
|
||||||
|
*/
|
||||||
|
func InitStruct(nodeInfo node.NodeInfo) TemplateStruct {
|
||||||
|
var tstruct TemplateStruct
|
||||||
|
controller, err := warewulfconf.New()
|
||||||
|
if err != nil {
|
||||||
|
wwlog.Printf(wwlog.ERROR, "%s\n", err)
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
nodeDB, err := node.New()
|
||||||
|
if err != nil {
|
||||||
|
wwlog.Printf(wwlog.ERROR, "%s\n", err)
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
allNodes, err := nodeDB.FindAllNodes()
|
||||||
|
if err != nil {
|
||||||
|
wwlog.Printf(wwlog.ERROR, "%s\n", err)
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
tstruct.Kernel = new(node.KernelConf)
|
||||||
|
tstruct.Ipmi = new(node.IpmiConf)
|
||||||
|
tstruct.Id = nodeInfo.Id.Get()
|
||||||
|
tstruct.Hostname = nodeInfo.Id.Get()
|
||||||
|
tstruct.Id = nodeInfo.Id.Get()
|
||||||
|
tstruct.Hostname = nodeInfo.Id.Get()
|
||||||
|
tstruct.ClusterName = nodeInfo.ClusterName.Get()
|
||||||
|
tstruct.Container = nodeInfo.ContainerName.Get()
|
||||||
|
tstruct.Kernel.Version = nodeInfo.Kernel.Override.Get()
|
||||||
|
tstruct.Kernel.Override = nodeInfo.Kernel.Override.Get()
|
||||||
|
tstruct.Kernel.Args = nodeInfo.Kernel.Args.Get()
|
||||||
|
tstruct.Init = nodeInfo.Init.Get()
|
||||||
|
tstruct.Root = nodeInfo.Root.Get()
|
||||||
|
tstruct.Ipmi.Ipaddr = nodeInfo.Ipmi.Ipaddr.Get()
|
||||||
|
tstruct.Ipmi.Netmask = nodeInfo.Ipmi.Netmask.Get()
|
||||||
|
tstruct.Ipmi.Port = nodeInfo.Ipmi.Port.Get()
|
||||||
|
tstruct.Ipmi.Gateway = nodeInfo.Ipmi.Gateway.Get()
|
||||||
|
tstruct.Ipmi.UserName = nodeInfo.Ipmi.UserName.Get()
|
||||||
|
tstruct.Ipmi.Password = nodeInfo.Ipmi.Password.Get()
|
||||||
|
tstruct.Ipmi.Interface = nodeInfo.Ipmi.Interface.Get()
|
||||||
|
tstruct.Ipmi.Write = nodeInfo.Ipmi.Write.Get()
|
||||||
|
tstruct.RuntimeOverlay = nodeInfo.RuntimeOverlay.Print()
|
||||||
|
tstruct.SystemOverlay = nodeInfo.SystemOverlay.Print()
|
||||||
|
tstruct.NetDevs = make(map[string]*node.NetDevs)
|
||||||
|
tstruct.Keys = make(map[string]string)
|
||||||
|
tstruct.Tags = make(map[string]string)
|
||||||
|
for devname, netdev := range nodeInfo.NetDevs {
|
||||||
|
var nd node.NetDevs
|
||||||
|
tstruct.NetDevs[devname] = &nd
|
||||||
|
tstruct.NetDevs[devname].Device = netdev.Device.Get()
|
||||||
|
tstruct.NetDevs[devname].Hwaddr = netdev.Hwaddr.Get()
|
||||||
|
tstruct.NetDevs[devname].Ipaddr = netdev.Ipaddr.Get()
|
||||||
|
tstruct.NetDevs[devname].Netmask = netdev.Netmask.Get()
|
||||||
|
tstruct.NetDevs[devname].Gateway = netdev.Gateway.Get()
|
||||||
|
tstruct.NetDevs[devname].Type = netdev.Type.Get()
|
||||||
|
tstruct.NetDevs[devname].OnBoot = netdev.OnBoot.Get()
|
||||||
|
tstruct.NetDevs[devname].Primary = netdev.Primary.Get()
|
||||||
|
mask := net.IPMask(net.ParseIP(netdev.Netmask.Get()).To4())
|
||||||
|
ipaddr := net.ParseIP(netdev.Ipaddr.Get()).To4()
|
||||||
|
netaddr := net.IPNet{IP: ipaddr, Mask: mask}
|
||||||
|
netPrefix, _ := net.IPMask(net.ParseIP(netdev.Netmask.Get()).To4()).Size()
|
||||||
|
tstruct.NetDevs[devname].Prefix = strconv.Itoa(netPrefix)
|
||||||
|
tstruct.NetDevs[devname].IpCIDR = netaddr.String()
|
||||||
|
tstruct.NetDevs[devname].Ipaddr6 = netdev.Ipaddr6.Get()
|
||||||
|
tstruct.NetDevs[devname].Tags = make(map[string]string)
|
||||||
|
for key, value := range netdev.Tags {
|
||||||
|
tstruct.NetDevs[devname].Tags[key] = value.Get()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Backwards compatibility for templates using "Keys"
|
||||||
|
for keyname, key := range nodeInfo.Tags {
|
||||||
|
tstruct.Keys[keyname] = key.Get()
|
||||||
|
}
|
||||||
|
for keyname, key := range nodeInfo.Tags {
|
||||||
|
tstruct.Tags[keyname] = key.Get()
|
||||||
|
}
|
||||||
|
tstruct.AllNodes = allNodes
|
||||||
|
tstruct.Nfs = *controller.Nfs
|
||||||
|
tstruct.Dhcp = *controller.Dhcp
|
||||||
|
tstruct.Warewulf = *controller.Warewulf
|
||||||
|
tstruct.Ipaddr = controller.Ipaddr
|
||||||
|
tstruct.Ipaddr6 = controller.Ipaddr6
|
||||||
|
tstruct.Netmask = controller.Netmask
|
||||||
|
tstruct.Network = controller.Network
|
||||||
|
netaddrStruct := net.IPNet{IP: net.ParseIP(controller.Network), Mask: net.IPMask(net.ParseIP(controller.Netmask))}
|
||||||
|
tstruct.NetworkCIDR = netaddrStruct.String()
|
||||||
|
if controller.Ipaddr6 != "" {
|
||||||
|
tstruct.Ipv6 = true
|
||||||
|
} else {
|
||||||
|
tstruct.Ipv6 = false
|
||||||
|
}
|
||||||
|
hostname, _ := os.Hostname()
|
||||||
|
tstruct.BuildHost = hostname
|
||||||
|
dt := time.Now()
|
||||||
|
tstruct.BuildTime = dt.Format("01-02-2006 15:04:05 MST")
|
||||||
|
tstruct.BuildTimeUnix = strconv.FormatInt(dt.Unix(), 10)
|
||||||
|
|
||||||
|
return tstruct
|
||||||
|
|
||||||
|
}
|
||||||
|
|||||||
@@ -6,19 +6,15 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"io/fs"
|
"io/fs"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"net"
|
|
||||||
"os"
|
"os"
|
||||||
"path"
|
"path"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"regexp"
|
"regexp"
|
||||||
"strconv"
|
|
||||||
"strings"
|
"strings"
|
||||||
"text/template"
|
"text/template"
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/hpcng/warewulf/internal/pkg/node"
|
"github.com/hpcng/warewulf/internal/pkg/node"
|
||||||
"github.com/hpcng/warewulf/internal/pkg/util"
|
"github.com/hpcng/warewulf/internal/pkg/util"
|
||||||
"github.com/hpcng/warewulf/internal/pkg/warewulfconf"
|
|
||||||
"github.com/hpcng/warewulf/internal/pkg/wwlog"
|
"github.com/hpcng/warewulf/internal/pkg/wwlog"
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
)
|
)
|
||||||
@@ -199,106 +195,17 @@ func BuildOverlayIndir(nodeInfo node.NodeInfo, overlayNames []string, outputDir
|
|||||||
if !util.IsDir(outputDir) {
|
if !util.IsDir(outputDir) {
|
||||||
return errors.Errorf("output must a be a directory: %s", outputDir)
|
return errors.Errorf("output must a be a directory: %s", outputDir)
|
||||||
}
|
}
|
||||||
controller, err := warewulfconf.New()
|
|
||||||
if err != nil {
|
|
||||||
wwlog.ErrorExc(err, "")
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
nodeDB, err := node.New()
|
|
||||||
if err != nil {
|
|
||||||
wwlog.ErrorExc(err, "")
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
allNodes, err := nodeDB.FindAllNodes()
|
|
||||||
if err != nil {
|
|
||||||
wwlog.ErrorExc(err, "")
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
|
|
||||||
if !util.ValidString(strings.Join(overlayNames, ""), "^[a-zA-Z0-9-._:]+$") {
|
if !util.ValidString(strings.Join(overlayNames, ""), "^[a-zA-Z0-9-._:]+$") {
|
||||||
return errors.Errorf("overlay names contains illegal characters: %v", overlayNames)
|
return errors.Errorf("overlay names contains illegal characters: %v", overlayNames)
|
||||||
}
|
}
|
||||||
wwlog.Verbose("Processing node/overlay: %s/%s", nodeInfo.Id.Get(), strings.Join(overlayNames, "-"))
|
|
||||||
var tstruct TemplateStruct
|
wwlog.Printf(wwlog.VERBOSE, "Processing node/overlay: %s/%s\n", nodeInfo.Id.Get(), strings.Join(overlayNames, "-"))
|
||||||
tstruct.Kernel = new(node.KernelConf)
|
|
||||||
tstruct.Ipmi = new(node.IpmiConf)
|
|
||||||
tstruct.Id = nodeInfo.Id.Get()
|
|
||||||
tstruct.Hostname = nodeInfo.Id.Get()
|
|
||||||
tstruct.ClusterName = nodeInfo.ClusterName.Get()
|
|
||||||
tstruct.Container = nodeInfo.ContainerName.Get()
|
|
||||||
tstruct.Kernel.Version = nodeInfo.Kernel.Override.Get()
|
|
||||||
tstruct.Kernel.Override = nodeInfo.Kernel.Override.Get()
|
|
||||||
tstruct.Kernel.Args = nodeInfo.Kernel.Args.Get()
|
|
||||||
tstruct.Init = nodeInfo.Init.Get()
|
|
||||||
tstruct.Root = nodeInfo.Root.Get()
|
|
||||||
tstruct.Ipmi.Ipaddr = nodeInfo.Ipmi.Ipaddr.Get()
|
|
||||||
tstruct.Ipmi.Netmask = nodeInfo.Ipmi.Netmask.Get()
|
|
||||||
tstruct.Ipmi.Port = nodeInfo.Ipmi.Port.Get()
|
|
||||||
tstruct.Ipmi.Gateway = nodeInfo.Ipmi.Gateway.Get()
|
|
||||||
tstruct.Ipmi.UserName = nodeInfo.Ipmi.UserName.Get()
|
|
||||||
tstruct.Ipmi.Password = nodeInfo.Ipmi.Password.Get()
|
|
||||||
tstruct.Ipmi.Interface = nodeInfo.Ipmi.Interface.Get()
|
|
||||||
tstruct.Ipmi.Write = nodeInfo.Ipmi.Write.Get()
|
|
||||||
tstruct.RuntimeOverlay = nodeInfo.RuntimeOverlay.Print()
|
|
||||||
tstruct.SystemOverlay = nodeInfo.SystemOverlay.Print()
|
|
||||||
tstruct.NetDevs = make(map[string]*node.NetDevs)
|
|
||||||
tstruct.Keys = make(map[string]string)
|
|
||||||
tstruct.Tags = make(map[string]string)
|
|
||||||
for devname, netdev := range nodeInfo.NetDevs {
|
|
||||||
var nd node.NetDevs
|
|
||||||
tstruct.NetDevs[devname] = &nd
|
|
||||||
tstruct.NetDevs[devname].Device = netdev.Device.Get()
|
|
||||||
tstruct.NetDevs[devname].Hwaddr = netdev.Hwaddr.Get()
|
|
||||||
tstruct.NetDevs[devname].Ipaddr = netdev.Ipaddr.Get()
|
|
||||||
tstruct.NetDevs[devname].Netmask = netdev.Netmask.Get()
|
|
||||||
tstruct.NetDevs[devname].Gateway = netdev.Gateway.Get()
|
|
||||||
tstruct.NetDevs[devname].Type = netdev.Type.Get()
|
|
||||||
tstruct.NetDevs[devname].OnBoot = netdev.OnBoot.Get()
|
|
||||||
tstruct.NetDevs[devname].Primary = netdev.Primary.Get()
|
|
||||||
mask := net.IPMask(net.ParseIP(netdev.Netmask.Get()).To4())
|
|
||||||
ipaddr := net.ParseIP(netdev.Ipaddr.Get()).To4()
|
|
||||||
netaddr := net.IPNet{IP: ipaddr, Mask: mask}
|
|
||||||
netPrefix, _ := net.IPMask(net.ParseIP(netdev.Netmask.Get()).To4()).Size()
|
|
||||||
tstruct.NetDevs[devname].Prefix = strconv.Itoa(netPrefix)
|
|
||||||
tstruct.NetDevs[devname].IpCIDR = netaddr.String()
|
|
||||||
tstruct.NetDevs[devname].Ipaddr6 = netdev.Ipaddr6.Get()
|
|
||||||
tstruct.NetDevs[devname].Tags = make(map[string]string)
|
|
||||||
for key, value := range netdev.Tags {
|
|
||||||
tstruct.NetDevs[devname].Tags[key] = value.Get()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Backwards compatibility for templates using "Keys"
|
|
||||||
for keyname, key := range nodeInfo.Tags {
|
|
||||||
tstruct.Keys[keyname] = key.Get()
|
|
||||||
}
|
|
||||||
for keyname, key := range nodeInfo.Tags {
|
|
||||||
tstruct.Tags[keyname] = key.Get()
|
|
||||||
}
|
|
||||||
tstruct.AllNodes = allNodes
|
|
||||||
tstruct.Nfs = *controller.Nfs
|
|
||||||
tstruct.Dhcp = *controller.Dhcp
|
|
||||||
tstruct.Warewulf = *controller.Warewulf
|
|
||||||
tstruct.Ipaddr = controller.Ipaddr
|
|
||||||
tstruct.Ipaddr6 = controller.Ipaddr6
|
|
||||||
tstruct.Netmask = controller.Netmask
|
|
||||||
tstruct.Network = controller.Network
|
|
||||||
netaddrStruct := net.IPNet{IP: net.ParseIP(controller.Network), Mask: net.IPMask(net.ParseIP(controller.Netmask))}
|
|
||||||
tstruct.NetworkCIDR = netaddrStruct.String()
|
|
||||||
if controller.Ipaddr6 != "" {
|
|
||||||
tstruct.Ipv6 = true
|
|
||||||
} else {
|
|
||||||
tstruct.Ipv6 = false
|
|
||||||
}
|
|
||||||
hostname, _ := os.Hostname()
|
|
||||||
tstruct.BuildHost = hostname
|
|
||||||
dt := time.Now()
|
|
||||||
tstruct.BuildTime = dt.Format("01-02-2006 15:04:05 MST")
|
|
||||||
tstruct.BuildTimeUnix = strconv.FormatInt(dt.Unix(), 10)
|
|
||||||
for _, overlayName := range overlayNames {
|
for _, overlayName := range overlayNames {
|
||||||
wwlog.Verbose("Building overlay %s for node %s in %s", overlayName, nodeInfo.Id.Get(), outputDir)
|
wwlog.Verbose("Building overlay %s for node %s in %s", overlayName, nodeInfo.Id.Get(), outputDir)
|
||||||
overlaySourceDir := OverlaySourceDir(overlayName)
|
overlaySourceDir := OverlaySourceDir(overlayName)
|
||||||
wwlog.Debug("Starting to build overlay %s\nChanging directory to OverlayDir: %s", overlayName, overlaySourceDir)
|
wwlog.Printf(wwlog.DEBUG, "Starting to build overlay %s\nChanging directory to OverlayDir: %s\n", overlayName, overlaySourceDir)
|
||||||
err = os.Chdir(overlaySourceDir)
|
err := os.Chdir(overlaySourceDir)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Wrap(err, "could not change directory to overlay dir")
|
return errors.Wrap(err, "could not change directory to overlay dir")
|
||||||
}
|
}
|
||||||
@@ -330,48 +237,21 @@ func BuildOverlayIndir(nodeInfo node.NodeInfo, overlayNames []string, outputDir
|
|||||||
wwlog.Debug("Created directory in overlay: %s", location)
|
wwlog.Debug("Created directory in overlay: %s", location)
|
||||||
|
|
||||||
} else if filepath.Ext(location) == ".ww" {
|
} else if filepath.Ext(location) == ".ww" {
|
||||||
|
tstruct := InitStruct(nodeInfo)
|
||||||
tstruct.BuildSource = path.Join(overlaySourceDir, location)
|
tstruct.BuildSource = path.Join(overlaySourceDir, location)
|
||||||
wwlog.Verbose("Evaluating overlay template file: %s", location)
|
wwlog.Verbose("Evaluating overlay template file: %s", location)
|
||||||
destFile := strings.TrimSuffix(location, ".ww")
|
destFile := strings.TrimSuffix(location, ".ww")
|
||||||
backupFile := true
|
|
||||||
writeFile := true
|
buffer, backupFile, writeFile, err := RenderTemplateFile(location, tstruct)
|
||||||
tmpl, err := template.New(path.Base(location)).Option("missingkey=default").Funcs(template.FuncMap{
|
|
||||||
// TODO: Fix for missingkey=zero
|
|
||||||
"Include": templateFileInclude,
|
|
||||||
"IncludeFrom": templateContainerFileInclude,
|
|
||||||
"IncludeBlock": templateFileBlock,
|
|
||||||
"inc": func(i int) int { return i + 1 },
|
|
||||||
"dec": func(i int) int { return i - 1 },
|
|
||||||
"file": func(str string) string { return fmt.Sprintf("{{ /* file \"%s\" */ }}", str) },
|
|
||||||
"abort": func() string {
|
|
||||||
wwlog.Debug("abort file called in %s", location)
|
|
||||||
writeFile = false
|
|
||||||
return ""
|
|
||||||
},
|
|
||||||
"nobackup": func() string {
|
|
||||||
wwlog.Debug("not backup for %s", location)
|
|
||||||
backupFile = false
|
|
||||||
return ""
|
|
||||||
},
|
|
||||||
"split": func(s string, d string) []string {
|
|
||||||
return strings.Split(s, d)
|
|
||||||
},
|
|
||||||
// }).ParseGlob(path.Join(OverlayDir, destFile+".ww*"))
|
|
||||||
}).ParseGlob(location)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Wrap(err, "could not parse template "+location)
|
return errors.Wrap(err, fmt.Sprintf("Failed to render template %s", location))
|
||||||
}
|
|
||||||
var buffer bytes.Buffer
|
|
||||||
err = tmpl.Execute(&buffer, tstruct)
|
|
||||||
if err != nil {
|
|
||||||
return errors.Wrap(err, "could not execute template")
|
|
||||||
}
|
}
|
||||||
if writeFile {
|
if writeFile {
|
||||||
destFileName := destFile
|
destFileName := destFile
|
||||||
var fileBuffer bytes.Buffer
|
var fileBuffer bytes.Buffer
|
||||||
// search for magic file name comment
|
// search for magic file name comment
|
||||||
fileScanner := bufio.NewScanner(bytes.NewReader(buffer.Bytes()))
|
fileScanner := bufio.NewScanner(bytes.NewReader(buffer.Bytes()))
|
||||||
fileScanner.Split(scanLines)
|
fileScanner.Split(ScanLines)
|
||||||
reg := regexp.MustCompile(`.*{{\s*/\*\s*file\s*["'](.*)["']\s*\*/\s*}}.*`)
|
reg := regexp.MustCompile(`.*{{\s*/\*\s*file\s*["'](.*)["']\s*\*/\s*}}.*`)
|
||||||
foundFileComment := false
|
foundFileComment := false
|
||||||
for fileScanner.Scan() {
|
for fileScanner.Scan() {
|
||||||
@@ -475,8 +355,55 @@ func carefulWriteBuffer(destFile string, buffer bytes.Buffer, backupFile bool, p
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Parses the template with the given filename, variables must be in data. Returns the
|
||||||
|
parsed template as bytes.Buffer, and the bool variables for backupFile and writeFile.
|
||||||
|
If something goes wrong an error is returned.
|
||||||
|
*/
|
||||||
|
func RenderTemplateFile(fileName string, data TemplateStruct) (
|
||||||
|
buffer bytes.Buffer,
|
||||||
|
backupFile bool,
|
||||||
|
writeFile bool,
|
||||||
|
err error) {
|
||||||
|
backupFile = true
|
||||||
|
writeFile = true
|
||||||
|
tmpl, err := template.New(path.Base(fileName)).Option("missingkey=default").Funcs(template.FuncMap{
|
||||||
|
// TODO: Fix for missingkey=zero
|
||||||
|
"Include": templateFileInclude,
|
||||||
|
"IncludeFrom": templateContainerFileInclude,
|
||||||
|
"IncludeBlock": templateFileBlock,
|
||||||
|
"inc": func(i int) int { return i + 1 },
|
||||||
|
"dec": func(i int) int { return i - 1 },
|
||||||
|
"file": func(str string) string { return fmt.Sprintf("{{ /* file \"%s\" */ }}", str) },
|
||||||
|
"abort": func() string {
|
||||||
|
wwlog.Printf(wwlog.DEBUG, "abort file called in %s\n", fileName)
|
||||||
|
writeFile = false
|
||||||
|
return ""
|
||||||
|
},
|
||||||
|
"nobackup": func() string {
|
||||||
|
wwlog.Printf(wwlog.DEBUG, "not backup for %s\n", fileName)
|
||||||
|
backupFile = false
|
||||||
|
return ""
|
||||||
|
},
|
||||||
|
"split": func(s string, d string) []string {
|
||||||
|
return strings.Split(s, d)
|
||||||
|
},
|
||||||
|
// }).ParseGlob(path.Join(OverlayDir, destFile+".ww*"))
|
||||||
|
}).ParseGlob(fileName)
|
||||||
|
if err != nil {
|
||||||
|
err = errors.Wrap(err, "could not parse template "+fileName)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
err = tmpl.Execute(&buffer, data)
|
||||||
|
if err != nil {
|
||||||
|
err = errors.Wrap(err, "could not execute template")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
// Simple version of ScanLines, but include the line break
|
// Simple version of ScanLines, but include the line break
|
||||||
func scanLines(data []byte, atEOF bool) (advance int, token []byte, err error) {
|
func ScanLines(data []byte, atEOF bool) (advance int, token []byte, err error) {
|
||||||
if atEOF && len(data) == 0 {
|
if atEOF && len(data) == 0 {
|
||||||
return 0, nil, nil
|
return 0, nil, nil
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user