Merge branch 'main' of github.com:ctrl-cmd/warewulf into main

This commit is contained in:
Shannon V. Davidson
2020-12-01 13:49:28 -06:00
85 changed files with 3085 additions and 1440 deletions

View File

@@ -0,0 +1,13 @@
package main
import (
"github.com/hpcng/warewulf/internal/pkg/node"
"github.com/hpcng/warewulf/internal/pkg/overlay"
)
func main() {
nodeDB, _ := node.New()
nodes, _ := nodeDB.FindAllNodes()
// wwlog.SetLevel(wwlog.DEBUG)
overlay.OverlayBuild(nodes, "runtime")
}

View File

@@ -46,13 +46,13 @@ func IpxeSend(w http.ResponseWriter, req *http.Request) {
return
}
if node.HostName != "" {
if node.Id.Defined() == true {
conf := config.New()
log.Printf("IPXE: %15s: %s\n", node.Fqdn, req.URL.Path)
log.Printf("IPXE: %15s: %s\n", node.Fqdn.Get(), req.URL.Path)
// TODO: Fix template path to use config package
ipxeTemplate := fmt.Sprintf("/etc/warewulf/ipxe/%s.ipxe", node.Ipxe)
ipxeTemplate := fmt.Sprintf("/etc/warewulf/ipxe/%s.ipxe", node.Ipxe.Get())
tmpl, err := template.ParseFiles(ipxeTemplate)
if err != nil {
@@ -62,13 +62,13 @@ func IpxeSend(w http.ResponseWriter, req *http.Request) {
var replace iPxeTemplate
replace.Fqdn = node.Fqdn
replace.Fqdn = node.Fqdn.Get()
replace.Ipaddr = conf.Ipaddr
replace.Port = strconv.Itoa(conf.Port)
replace.Hostname = node.HostName
replace.Hostname = node.HostName.Get()
replace.Hwaddr = url[2]
replace.Vnfs = node.Vnfs
replace.Kernelargs = node.KernelArgs
replace.Vnfs = node.Vnfs.Get()
replace.Kernelargs = node.KernelArgs.Get()
err = tmpl.Execute(w, replace)
if err != nil {
@@ -76,7 +76,7 @@ func IpxeSend(w http.ResponseWriter, req *http.Request) {
return
}
log.Printf("SEND: %15s: %s\n", node.Fqdn, ipxeTemplate)
log.Printf("SEND: %15s: %s\n", node.Fqdn.Get(), ipxeTemplate)
} else {
log.Printf("ERROR: iPXE request from unknown Node (hwaddr=%s)\n", url[2])

View File

@@ -16,19 +16,19 @@ func KernelSend(w http.ResponseWriter, req *http.Request) {
return
}
if node.KernelVersion != "" {
fileName := config.KernelImage(node.KernelVersion)
if node.KernelVersion.Defined() == true {
fileName := config.KernelImage(node.KernelVersion.Get())
err := sendFile(w, fileName, node.Fqdn)
err := sendFile(w, fileName, node.Fqdn.Get())
if err != nil {
log.Printf("ERROR: %s\n", err)
} else {
log.Printf("SEND: %15s: %s\n", node.Fqdn, fileName)
log.Printf("SEND: %15s: %s\n", node.Fqdn.Get(), fileName)
}
} else {
w.WriteHeader(503)
log.Printf("ERROR: No 'kernel version' set for node %s\n", node.Fqdn)
log.Printf("ERROR: No 'kernel version' set for node %s\n", node.Fqdn.Get())
}
return

View File

@@ -15,19 +15,20 @@ func KmodsSend(w http.ResponseWriter, req *http.Request) {
log.Println(err)
return
}
if node.KernelVersion != "" {
fileName := config.KmodsImage(node.KernelVersion)
err := sendFile(w, fileName, node.Fqdn)
if node.KernelVersion.Defined() == true {
fileName := config.KmodsImage(node.KernelVersion.Get())
err := sendFile(w, fileName, node.Fqdn.Get())
if err != nil {
log.Printf("ERROR: %s\n", err)
} else {
log.Printf("SEND: %15s: %s\n", node.Fqdn, fileName)
log.Printf("SEND: %15s: %s\n", node.Fqdn.Get(), fileName)
}
} else {
w.WriteHeader(503)
log.Printf("ERROR: No 'kernel version' set for node %s\n", node.Fqdn)
log.Printf("ERROR: No 'kernel version' set for node %s\n", node.Fqdn.Get())
}
return

View File

@@ -47,26 +47,26 @@ func RuntimeOverlaySend(w http.ResponseWriter, req *http.Request) {
return
}
if node.Fqdn == "" {
if node.Id.Defined() == false {
log.Printf("UNKNOWN: %15s: %s\n", remote[0], req.URL.Path)
w.WriteHeader(404)
return
} else {
log.Printf("REQ: %15s: %s\n", node.Fqdn, req.URL.Path)
log.Printf("REQ: %15s: %s\n", node.Fqdn.Get(), req.URL.Path)
}
if node.RuntimeOverlay != "" {
fileName := config.RuntimeOverlayImage(node.Fqdn)
if node.RuntimeOverlay.Defined() == true {
fileName := config.RuntimeOverlayImage(node.Fqdn.Get())
err := sendFile(w, fileName, node.Fqdn)
err := sendFile(w, fileName, node.Fqdn.Get())
if err != nil {
log.Printf("ERROR: %s\n", err)
} else {
log.Printf("SEND: %15s: %s\n", node.Fqdn, fileName)
log.Printf("SEND: %15s: %s\n", node.Fqdn.Get(), fileName)
}
} else {
w.WriteHeader(503)
log.Printf("ERROR: No 'runtime system-overlay' set for node %s\n", node.Fqdn)
log.Printf("ERROR: No 'runtime system-overlay' set for node %s\n", node.Fqdn.Get())
}
return

View File

@@ -16,18 +16,18 @@ func SystemOverlaySend(w http.ResponseWriter, req *http.Request) {
return
}
if node.SystemOverlay != "" {
fileName := config.SystemOverlayImage(node.Fqdn)
if node.SystemOverlay.Defined() == true {
fileName := config.SystemOverlayImage(node.Fqdn.Get())
err := sendFile(w, fileName, node.Fqdn)
err := sendFile(w, fileName, node.Fqdn.Get())
if err != nil {
log.Printf("ERROR: %s\n", err)
} else {
log.Printf("SEND: %15s: %s\n", node.Fqdn, fileName)
log.Printf("SEND: %15s: %s\n", node.Fqdn.Get(), fileName)
}
} else {
w.WriteHeader(503)
log.Printf("ERROR: No 'system system-overlay' set for node %s\n", node.Fqdn)
log.Printf("ERROR: No 'system system-overlay' set for node %s\n", node.Fqdn.Get())
}
return

View File

@@ -2,8 +2,8 @@ package response
import (
"fmt"
"github.com/hpcng/warewulf/internal/pkg/node"
"github.com/hpcng/warewulf/internal/pkg/errors"
"github.com/hpcng/warewulf/internal/pkg/node"
"io"
"log"
"net/http"
@@ -27,11 +27,11 @@ func getSanity(req *http.Request) (node.NodeInfo, error) {
return ret, errors.New("Could not find node by HW address")
}
if ret.Fqdn == "" {
if ret.Fqdn.Defined() == false {
log.Printf("UNKNOWN: %15s: %s\n", hwaddr, req.URL.Path)
return ret, errors.New("Unknown node HW address: " + hwaddr)
} else {
log.Printf("REQ: %15s: %s\n", ret.Fqdn, req.URL.Path)
log.Printf("REQ: %15s: %s\n", ret.Fqdn.Get(), req.URL.Path)
}
return ret, nil

View File

@@ -1,14 +1,12 @@
package response
import (
"github.com/hpcng/warewulf/internal/pkg/config"
"github.com/hpcng/warewulf/internal/pkg/vnfs"
"log"
"net/http"
)
func VnfsSend(w http.ResponseWriter, req *http.Request) {
config := config.New()
node, err := getSanity(req)
if err != nil {
@@ -17,18 +15,24 @@ func VnfsSend(w http.ResponseWriter, req *http.Request) {
return
}
if node.Vnfs != "" {
v := vnfs.New(node.Vnfs)
if node.Vnfs.Defined() == true {
err := sendFile(w, config.VnfsImage(v.NameClean()), node.Fqdn)
v, err := vnfs.Load(node.Vnfs.Get())
if err != nil {
log.Printf("ERROR: %s\n", err)
w.WriteHeader(503)
log.Printf("ERROR: Could not load VNFS: %s\n", node.Fqdn.Get())
return
}
err = sendFile(w, v.Image, node.Fqdn.Get())
if err != nil {
log.Printf("ERROR1: %s\n", err)
} else {
log.Printf("SEND: %15s: %s\n", node.Fqdn, config.VnfsImage(v.NameClean()))
log.Printf("SEND: %15s: %s\n", node.Fqdn.Get(), v.Image)
}
} else {
w.WriteHeader(503)
log.Printf("ERROR: No VNFS set for node %s\n", node.Fqdn)
log.Printf("ERROR: No VNFS set for node %s\n", node.Fqdn.Get())
}
return

View File

@@ -46,7 +46,7 @@ func CobraRunE(cmd *cobra.Command, args []string) error {
wwlog.Printf(wwlog.INFO, "Building VNFS images...\n")
for _, node := range nodes {
set[node.Vnfs] ++
set[node.Vnfs.String()] ++
}
for e := range set {
vnfs.Build(e, buildForce)
@@ -60,7 +60,7 @@ func CobraRunE(cmd *cobra.Command, args []string) error {
wwlog.Printf(wwlog.INFO, "Building Kernel images...\n")
for _, node := range nodes {
set[node.KernelVersion] ++
set[node.KernelVersion.String()] ++
}
for e := range set {
kernel.Build(e)

View File

@@ -0,0 +1,29 @@
package add
import (
"github.com/hpcng/warewulf/internal/pkg/node"
"github.com/hpcng/warewulf/internal/pkg/wwlog"
"github.com/spf13/cobra"
"os"
)
func CobraRunE(cmd *cobra.Command, args []string) error {
nodeDB, err := node.New()
if err != nil {
wwlog.Printf(wwlog.ERROR, "Failed opening node database: %s\n", err)
os.Exit(1)
}
for _, c := range args {
err = nodeDB.AddController(c)
if err != nil {
wwlog.Printf(wwlog.ERROR, "%s\n", err)
os.Exit(1)
}
}
nodeDB.Persist()
return nil
}

View File

@@ -0,0 +1,23 @@
package add
import "github.com/spf13/cobra"
var (
baseCmd = &cobra.Command{
Use: "add",
Short: "Add",
Long: "Add",
RunE: CobraRunE,
Args: cobra.MinimumNArgs(1),
}
SetController string
)
func init() {
}
// GetRootCommand returns the root cobra.Command for the application.
func GetCommand() *cobra.Command {
return baseCmd
}

View File

@@ -0,0 +1,61 @@
package delete
import (
"fmt"
"github.com/hpcng/warewulf/internal/pkg/node"
"github.com/hpcng/warewulf/internal/pkg/wwlog"
"github.com/manifoldco/promptui"
"github.com/spf13/cobra"
"os"
)
func CobraRunE(cmd *cobra.Command, args []string) error {
var count int
var numNodes int
nodeDB, err := node.New()
if err != nil {
wwlog.Printf(wwlog.ERROR, "Failed to open node database: %s\n", err)
os.Exit(1)
}
nodes, err := nodeDB. FindAllNodes()
if err != nil {
wwlog.Printf(wwlog.ERROR, "Could not load all nodes: %s\n", err)
os.Exit(1)
}
for _, c := range args {
err := nodeDB.DelController(c)
if err != nil {
wwlog.Printf(wwlog.ERROR, "%s\n", err)
} else {
for _, n := range nodes {
if n.Cid.Get() == c {
numNodes ++
}
}
count ++
}
}
if count > 0 {
q := fmt.Sprintf("Are you sure you want to delete %d controllers(s) (%d nodes)", count, numNodes)
prompt := promptui.Prompt{
Label: q,
IsConfirm: true,
}
result, _ := prompt.Run()
if result == "y" || result == "yes" {
nodeDB.Persist()
}
} else {
wwlog.Printf(wwlog.INFO, "No controllers found\n")
}
return nil
}

View File

@@ -0,0 +1,23 @@
package delete
import "github.com/spf13/cobra"
var (
baseCmd = &cobra.Command{
Use: "delete",
Short: "Delete",
Long: "Delete",
RunE: CobraRunE,
Args: cobra.MinimumNArgs(1),
}
SetController string
)
func init() {
}
// GetRootCommand returns the root cobra.Command for the application.
func GetCommand() *cobra.Command {
return baseCmd
}

View File

@@ -0,0 +1,45 @@
package list
import "C"
import (
"fmt"
"github.com/hpcng/warewulf/internal/pkg/node"
"github.com/hpcng/warewulf/internal/pkg/wwlog"
"github.com/spf13/cobra"
"os"
"reflect"
)
func CobraRunE(cmd *cobra.Command, args []string) error {
nodeDB, err := node.New()
if err != nil {
wwlog.Printf(wwlog.ERROR, "Could not open node configuration: %s\n", err)
os.Exit(1)
}
controllers, err := nodeDB.FindAllControllers()
if err != nil {
wwlog.Printf(wwlog.ERROR, "Could not find all nodes: %s\n", err)
os.Exit(1)
}
if ShowAll == true {
for _, controller := range controllers {
v := reflect.ValueOf(controller)
typeOfS := v.Type()
fmt.Printf("################################################################################\n")
for i := 0; i< v.NumField(); i++ {
fmt.Printf("%-25s %s = %v\n", controller.Id, typeOfS.Field(i).Name, v.Field(i).Interface())
}
}
} else {
fmt.Printf("%-22s\n", "CONTROLLER NAME")
for _, c := range controllers {
fmt.Printf("%-22s\n", c.Id)
}
}
return nil
}

View File

@@ -0,0 +1,23 @@
package list
import "github.com/spf13/cobra"
var (
baseCmd = &cobra.Command{
Use: "list",
Short: "List",
Long: "List",
RunE: CobraRunE,
}
ShowAll bool
)
func init() {
baseCmd.PersistentFlags().BoolVarP(&ShowAll, "all", "a", false, "Show all node configurations")
}
// GetRootCommand returns the root cobra.Command for the application.
func GetCommand() *cobra.Command {
return baseCmd
}

View File

@@ -0,0 +1,30 @@
package controller
import (
"github.com/spf13/cobra"
"github.com/hpcng/warewulf/internal/app/wwctl/controller/add"
"github.com/hpcng/warewulf/internal/app/wwctl/controller/delete"
"github.com/hpcng/warewulf/internal/app/wwctl/controller/list"
"github.com/hpcng/warewulf/internal/app/wwctl/controller/set"
)
var (
baseCmd = &cobra.Command{
Use: "controller",
Short: "Controller management",
Long: "Management of group settings and power management",
}
)
func init() {
baseCmd.AddCommand(list.GetCommand())
baseCmd.AddCommand(set.GetCommand())
baseCmd.AddCommand(add.GetCommand())
baseCmd.AddCommand(delete.GetCommand())
}
// GetRootCommand returns the root cobra.Command for the application.
func GetCommand() *cobra.Command {
return baseCmd
}

View File

@@ -0,0 +1,94 @@
package set
import (
"fmt"
"github.com/hpcng/warewulf/internal/pkg/node"
"github.com/hpcng/warewulf/internal/pkg/wwlog"
"github.com/manifoldco/promptui"
"github.com/spf13/cobra"
"os"
)
func CobraRunE(cmd *cobra.Command, args []string) error {
var err error
var controllers []node.ControllerInfo
nodeDB, err := node.New()
if err != nil {
wwlog.Printf(wwlog.ERROR, "Could not open node configuration: %s\n", err)
os.Exit(1)
}
if err != nil {
wwlog.Printf(wwlog.ERROR, "Cloud not get nodeList: %s\n", err)
os.Exit(1)
}
if SetAll == true {
var tmp []node.ControllerInfo
tmp, err = nodeDB.FindAllControllers()
if err != nil {
wwlog.Printf(wwlog.ERROR, "%s\n", err)
os.Exit(1)
}
for _, c := range tmp {
controllers = append(controllers, c)
}
} else if len(args) > 0 {
var tmp []node.ControllerInfo
tmp, err = nodeDB.FindAllControllers()
if err != nil {
wwlog.Printf(wwlog.ERROR, "%s\n", err)
os.Exit(1)
}
for _, a := range args {
for _, c := range tmp {
if c.Id == a {
controllers = append(controllers, c)
}
}
}
} else {
cmd.Usage()
os.Exit(1)
}
for _, c := range controllers {
if SetIpaddr != "" {
wwlog.Printf(wwlog.VERBOSE, "Controller: %s, Setting IP Addr to: %s\n", c.Id, SetIpaddr)
c.Ipaddr = SetIpaddr
err := nodeDB.ControllerUpdate(c)
if err != nil {
wwlog.Printf(wwlog.ERROR, "%s\n", err)
os.Exit(1)
}
}
}
if len(controllers) > 0 {
q := fmt.Sprintf("Are you sure you want to modify %d group(s)", len(controllers))
prompt := promptui.Prompt{
Label: q,
IsConfirm: true,
}
result, _ := prompt.Run()
if result == "y" || result == "yes" {
nodeDB.Persist()
}
} else {
fmt.Printf("No controllers found\n")
}
return nil
}

View File

@@ -0,0 +1,26 @@
package set
import "github.com/spf13/cobra"
var (
baseCmd = &cobra.Command{
Use: "set",
Short: "Set",
Long: "Set",
RunE: CobraRunE,
Args: cobra.MinimumNArgs(1),
}
SetAll bool
SetIpaddr string
)
func init() {
baseCmd.PersistentFlags().BoolVarP(&SetAll, "all", "a", false, "Set all controllers")
baseCmd.PersistentFlags().StringVarP(&SetIpaddr, "ipaddr", "i", "", "Set the controller's IP address")
}
// GetRootCommand returns the root cobra.Command for the application.
func GetCommand() *cobra.Command {
return baseCmd
}

View File

@@ -15,7 +15,7 @@ func CobraRunE(cmd *cobra.Command, args []string) error {
}
for _, g := range args {
err = nodeDB.AddGroup(g)
err = nodeDB.AddGroup(SetController, g)
if err != nil {
wwlog.Printf(wwlog.ERROR, "%s\n", err)
os.Exit(1)

View File

@@ -10,13 +10,12 @@ var (
RunE: CobraRunE,
Args: cobra.MinimumNArgs(1),
}
SetVnfs string
SetKernel string
SetController string
)
func init() {
baseCmd.PersistentFlags().StringVarP(&SetVnfs, "vnfs", "V", "", "Set node Virtual Node File System (VNFS)")
baseCmd.PersistentFlags().StringVarP(&SetKernel, "kernel", "K", "", "Set Kernel version for nodes")
baseCmd.PersistentFlags().StringVarP(&SetController, "controller", "c", "default", "Controller to add group to")
}
// GetRootCommand returns the root cobra.Command for the application.

View File

@@ -26,12 +26,12 @@ func CobraRunE(cmd *cobra.Command, args []string) error {
}
for _, g := range args {
err := nodeDB.DelGroup(g)
err := nodeDB.DelGroup(SetController, g)
if err != nil {
wwlog.Printf(wwlog.ERROR, "%s\n", err)
} else {
for _, n := range nodes {
if n.GroupName == g {
if n.Gid.Get() == g {
numNodes ++
}
}

View File

@@ -9,14 +9,11 @@ var (
Long: "Add a new node group ",
RunE: CobraRunE,
}
SetVnfs string
SetKernel string
// SetGroupLevel bool
SetController string
)
func init() {
baseCmd.PersistentFlags().StringVarP(&SetVnfs, "vnfs", "V", "", "Set node Virtual Node File System (VNFS)")
baseCmd.PersistentFlags().StringVarP(&SetKernel, "kernel", "K", "", "Set Kernel version for nodes")
baseCmd.PersistentFlags().StringVarP(&SetController, "controller", "c", "default", "Controller to add group to")
}
// GetRootCommand returns the root cobra.Command for the application.

View File

@@ -7,6 +7,7 @@ import (
"github.com/spf13/cobra"
"os"
"reflect"
"strings"
)
func CobraRunE(cmd *cobra.Command, args []string) error {
@@ -33,9 +34,9 @@ func CobraRunE(cmd *cobra.Command, args []string) error {
}
}
} else {
fmt.Printf("%-22s %-16s %-30s %-30s %-16s\n", "GROUP NAME", "DOMAINNAME", "KERNEL VERSION", "VNFS IMAGE", "RUNTIME OVERLAY")
fmt.Printf("%-22s %-16s %-16s %s\n", "GROUP NAME", "DOMAINNAME", "CONTROLLER", "PROFILES")
for _, g := range groups {
fmt.Printf("%-22s %-16s %-30s %-30s %-16s\n", g.GroupName, g.DomainName, g.KernelVersion, g.Vnfs, g.RuntimeOverlay)
fmt.Printf("%-22s %-16s %-16s %s\n", g.Id, g.DomainName, g.Cid, strings.Join(g.Profiles, ","))
}
}

View File

@@ -3,6 +3,7 @@ package set
import (
"fmt"
"github.com/hpcng/warewulf/internal/pkg/node"
"github.com/hpcng/warewulf/internal/pkg/util"
"github.com/hpcng/warewulf/internal/pkg/wwlog"
"github.com/manifoldco/promptui"
"github.com/spf13/cobra"
@@ -24,7 +25,19 @@ func CobraRunE(cmd *cobra.Command, args []string) error {
os.Exit(1)
}
if len(args) > 0 {
if SetGroupAll == true {
var tmp []node.GroupInfo
tmp, err = nodeDB.FindAllGroups()
if err != nil {
wwlog.Printf(wwlog.ERROR, "%s\n", err)
os.Exit(1)
}
for _, g := range tmp {
groups = append(groups, g)
}
} else if len(args) > 0 {
var tmp []node.GroupInfo
tmp, err = nodeDB.FindAllGroups()
if err != nil {
@@ -46,181 +59,100 @@ func CobraRunE(cmd *cobra.Command, args []string) error {
}
for _, g := range groups {
if SetVnfs != "" {
wwlog.Printf(wwlog.VERBOSE, "Group: %s, Setting vnfs to: %s\n", g.Id, SetVnfs)
err := nodeDB.SetGroupVal(g.Id, "vnfs", SetVnfs)
if err != nil {
wwlog.Printf(wwlog.ERROR, "%s\n", err)
os.Exit(1)
}
if SetClearNodes == true {
nodes, err := nodeDB.FindAllNodes()
if err != nil {
wwlog.Printf(wwlog.ERROR, "%s\n", err)
os.Exit(1)
}
for _, n := range nodes {
_ = nodeDB.SetNodeVal(g.Id, n.Id, "vnfs", "")
}
}
}
if SetKernel != "" {
wwlog.Printf(wwlog.VERBOSE, "Group: %s, Setting kernel to: %s\n", g.Id, SetVnfs)
err := nodeDB.SetGroupVal(g.Id, "kernel", SetKernel)
if err != nil {
wwlog.Printf(wwlog.ERROR, "%s\n", err)
os.Exit(1)
}
if SetClearNodes == true {
nodes, err := nodeDB.FindAllNodes()
if err != nil {
wwlog.Printf(wwlog.ERROR, "%s\n", err)
os.Exit(1)
}
for _, n := range nodes {
_ = nodeDB.SetNodeVal(g.Id, n.Id, "kernel", "")
}
}
}
if SetDomainName != "" {
wwlog.Printf(wwlog.VERBOSE, "Group: %s, Setting domain name to: %s\n", g.Id, SetDomainName)
err := nodeDB.SetGroupVal(g.Id, "domain", SetDomainName)
g.DomainName = SetDomainName
err := nodeDB.GroupUpdate(g)
if err != nil {
wwlog.Printf(wwlog.ERROR, "%s\n", err)
os.Exit(1)
}
if SetClearNodes == true {
nodes, err := nodeDB.FindAllNodes()
if err != nil {
wwlog.Printf(wwlog.ERROR, "%s\n", err)
os.Exit(1)
}
for _, n := range nodes {
_ = nodeDB.SetNodeVal(g.Id, n.Id, "domain", "")
}
}
}
if SetVnfs != "" {
wwlog.Printf(wwlog.VERBOSE, "Group: %s, Setting VNFS to: %s\n", g.Id, SetVnfs)
if SetIpxe != "" {
wwlog.Printf(wwlog.VERBOSE, "Group: %s, Setting iPXE template to: %s\n", g.Id, SetIpxe)
err := nodeDB.SetGroupVal(g.Id, "ipxe", SetIpxe)
g.Vnfs = SetVnfs
err := nodeDB.GroupUpdate(g)
if err != nil {
wwlog.Printf(wwlog.ERROR, "%s\n", err)
os.Exit(1)
}
if SetClearNodes == true {
nodes, err := nodeDB.FindAllNodes()
if err != nil {
wwlog.Printf(wwlog.ERROR, "%s\n", err)
os.Exit(1)
}
for _, n := range nodes {
_ = nodeDB.SetNodeVal(g.Id, n.Id, "ipxe", "")
}
}
}
if SetKernel != "" {
wwlog.Printf(wwlog.VERBOSE, "Group: %s, Setting kernel to: %s\n", g.Id, SetKernel)
if SetRuntimeOverlay != "" {
wwlog.Printf(wwlog.VERBOSE, "Group: %s, Setting runtime overlay to: %s\n", g.Id, SetRuntimeOverlay)
err := nodeDB.SetGroupVal(g.Id, "runtimeoverlay", SetRuntimeOverlay)
g.KernelVersion = SetKernel
err := nodeDB.GroupUpdate(g)
if err != nil {
wwlog.Printf(wwlog.ERROR, "%s\n", err)
os.Exit(1)
}
if SetClearNodes == true {
nodes, err := nodeDB.FindAllNodes()
if err != nil {
wwlog.Printf(wwlog.ERROR, "%s\n", err)
os.Exit(1)
}
for _, n := range nodes {
_ = nodeDB.SetNodeVal(g.Id, n.Id, "runtimeoverlay", "")
}
}
}
if SetSystemOverlay != "" {
wwlog.Printf(wwlog.VERBOSE, "Group: %s, Setting system overlay to: %s\n", g.Id, SetSystemOverlay)
err := nodeDB.SetGroupVal(g.Id, "systemoverlay", SetSystemOverlay)
if err != nil {
wwlog.Printf(wwlog.ERROR, "%s\n", err)
os.Exit(1)
}
if SetClearNodes == true {
nodes, err := nodeDB.FindAllNodes()
if err != nil {
wwlog.Printf(wwlog.ERROR, "%s\n", err)
os.Exit(1)
}
for _, n := range nodes {
_ = nodeDB.SetNodeVal(g.Id, n.Id, "systemoverlay", "")
}
}
}
if SetIpmiIpaddr != "" {
wwlog.Printf(wwlog.VERBOSE, "Group: %s, Setting IPMI IP address to: %s\n", g.Id, SetIpmiIpaddr)
err := nodeDB.SetGroupVal(g.Id, "ipmiipaddr", SetIpmiIpaddr)
if err != nil {
wwlog.Printf(wwlog.ERROR, "%s\n", err)
os.Exit(1)
}
if SetClearNodes == true {
nodes, err := nodeDB.FindAllNodes()
if err != nil {
wwlog.Printf(wwlog.ERROR, "%s\n", err)
os.Exit(1)
}
for _, n := range nodes {
_ = nodeDB.SetNodeVal(g.Id, n.Id, "ipmiipaddr", "")
}
}
}
if SetIpmiUsername != "" {
wwlog.Printf(wwlog.VERBOSE, "Group: %s, Setting IPMI IP username to: %s\n", g.Id, SetIpmiUsername)
err := nodeDB.SetGroupVal(g.Id, "ipmiusername", SetIpmiUsername)
wwlog.Printf(wwlog.VERBOSE, "Group: %s, Setting IPMI username to: %s\n", g.Id, SetIpmiUsername)
g.IpmiUserName = SetIpmiUsername
err := nodeDB.GroupUpdate(g)
if err != nil {
wwlog.Printf(wwlog.ERROR, "%s\n", err)
os.Exit(1)
}
if SetClearNodes == true {
nodes, err := nodeDB.FindAllNodes()
if err != nil {
wwlog.Printf(wwlog.ERROR, "%s\n", err)
os.Exit(1)
}
for _, n := range nodes {
_ = nodeDB.SetNodeVal(g.Id, n.Id, "ipmiusername", "")
}
}
}
if SetIpmiPassword != "" {
wwlog.Printf(wwlog.VERBOSE, "Group: %s, Setting IPMI IP password to: %s\n", g.Id, SetIpmiPassword)
err := nodeDB.SetGroupVal(g.Id, "ipmipassword", SetIpmiPassword)
wwlog.Printf(wwlog.VERBOSE, "Group: %s, Setting IPMI password to: %s\n", g.Id, SetIpmiPassword)
g.IpmiPassword = SetIpmiPassword
err := nodeDB.GroupUpdate(g)
if err != nil {
wwlog.Printf(wwlog.ERROR, "%s\n", err)
os.Exit(1)
}
if SetClearNodes == true {
nodes, err := nodeDB.FindAllNodes()
if err != nil {
wwlog.Printf(wwlog.ERROR, "%s\n", err)
os.Exit(1)
}
for _, n := range nodes {
_ = nodeDB.SetNodeVal(g.Id, n.Id, "ipmipassword", "")
}
}
if SetSystemOverlay != "" {
wwlog.Printf(wwlog.VERBOSE, "Group: %s, Setting system overlay to: %s\n", g.Id, SetSystemOverlay)
g.SystemOverlay = SetSystemOverlay
err := nodeDB.GroupUpdate(g)
if err != nil {
wwlog.Printf(wwlog.ERROR, "%s\n", err)
os.Exit(1)
}
}
if SetRuntimeOverlay != "" {
wwlog.Printf(wwlog.VERBOSE, "Group: %s, Setting runtime overlay to: %s\n", g.Id, SetRuntimeOverlay)
g.RuntimeOverlay = SetRuntimeOverlay
err := nodeDB.GroupUpdate(g)
if err != nil {
wwlog.Printf(wwlog.ERROR, "%s\n", err)
os.Exit(1)
}
}
if len(SetAddProfile) > 0 {
for _, p := range SetAddProfile {
wwlog.Printf(wwlog.VERBOSE, "Adding profile to '%s': '%s'\n", g.Id, p)
g.Profiles = util.SliceAddUniqueElement(g.Profiles, p)
}
err := nodeDB.GroupUpdate(g)
if err != nil {
wwlog.Printf(wwlog.ERROR, "%s\n", err)
os.Exit(1)
}
}
if len(SetDelProfile) > 0 {
for _, p := range SetDelProfile {
wwlog.Printf(wwlog.VERBOSE, "Removing profile to '%s': '%s'\n", g.Id, p)
g.Profiles = util.SliceRemoveElement(g.Profiles, p)
}
err := nodeDB.GroupUpdate(g)
if err != nil {
wwlog.Printf(wwlog.ERROR, "%s\n", err)
os.Exit(1)
}
}
}

View File

@@ -15,12 +15,12 @@ var (
SetIpxe string
SetRuntimeOverlay string
SetSystemOverlay string
SetHostname string
SetClearNodes bool
SetIpmiIpaddr string
SetIpmiUsername string
SetIpmiPassword string
SetGroupAll bool
SetAddProfile []string
SetDelProfile []string
)
func init() {
@@ -30,11 +30,15 @@ func init() {
baseCmd.PersistentFlags().StringVarP(&SetIpxe, "ipxe", "P", "", "Set the node's iPXE template name")
baseCmd.PersistentFlags().StringVarP(&SetRuntimeOverlay, "runtime", "R", "", "Set the node's runtime overlay")
baseCmd.PersistentFlags().StringVarP(&SetSystemOverlay, "system", "S", "", "Set the node's system overlay")
baseCmd.PersistentFlags().StringVar(&SetIpmiIpaddr, "ipmi", "", "Set the node's IPMI address")
baseCmd.PersistentFlags().StringVar(&SetIpmiUsername, "ipmiuser", "", "Set the node's IPMI username")
baseCmd.PersistentFlags().StringVar(&SetIpmiPassword, "ipmipass", "", "Set the node's IPMI password")
baseCmd.PersistentFlags().StringSliceVarP(&SetAddProfile, "addprofile", "p", []string{}, "Add Profile(s) to group")
baseCmd.PersistentFlags().StringSliceVarP(&SetDelProfile, "delprofile", "r", []string{}, "Remove Profile(s) to group")
baseCmd.PersistentFlags().BoolVarP(&SetClearNodes, "clear", "c", false, "Clear node configurations when setting parent group")
baseCmd.PersistentFlags().BoolVarP(&SetGroupAll, "all", "a", false, "Set all nodes")
}
// GetRootCommand returns the root cobra.Command for the application.

View File

@@ -27,7 +27,9 @@ func CobraRunE(cmd *cobra.Command, args []string) error {
}
for _, node := range nodes {
set[node.KernelVersion] ++
if node.KernelVersion.Defined() == true {
set[node.KernelVersion.Get()] ++
}
}
} else if BuildAll == true {
@@ -39,7 +41,10 @@ func CobraRunE(cmd *cobra.Command, args []string) error {
}
for _, node := range nodes {
set[node.KernelVersion] ++
wwlog.Printf(wwlog.DEBUG, "evaluating node/kernel: %s/%s\n", node.Fqdn.Get(), node.KernelVersion.String())
if node.KernelVersion.Defined() == true {
set[node.KernelVersion.Get()] ++
}
}
} else if len(args) == 1 {
@@ -50,6 +55,7 @@ func CobraRunE(cmd *cobra.Command, args []string) error {
}
for k := range set {
wwlog.Printf(wwlog.INFO, "Building kernel: %s\n", k)
err := kernel.Build(k)
if err != nil {
wwlog.Printf(wwlog.ERROR, "%s\n", err)

View File

@@ -2,11 +2,52 @@ package list
import (
"fmt"
"github.com/hpcng/warewulf/internal/pkg/config"
"github.com/hpcng/warewulf/internal/pkg/node"
"github.com/hpcng/warewulf/internal/pkg/util"
"github.com/spf13/cobra"
"io/ioutil"
"os"
"path"
"strings"
)
func CobraRunE(cmd *cobra.Command, args []string) error {
fmt.Printf("This command is coming soon...\n")
config := config.New()
nconfig, _ := node.New()
nodes, _ := nconfig.FindAllNodes()
nodemap := make(map[string]int)
for _, n := range nodes {
nodemap[n.KernelVersion.String()] ++
}
images, _ := ioutil.ReadDir(config.KernelParentDir())
fmt.Printf("%-38s %-16s %-16s %s\n", "KERNEL VERSION", "KERNEL SIZE(k)", "KMODS SIZE(k)", "NODES")
fmt.Println(strings.Repeat("=", 80))
for _, file := range images {
if util.IsDir(path.Join(config.KernelParentDir(), file.Name())) {
var kernel_size int64
var kmods_size int64
if util.IsFile( config.KernelImage(file.Name())) {
s, _ := os.Stat(config.KernelImage(file.Name()))
kernel_size = s.Size() / 1024
}
if util.IsFile( config.KmodsImage(file.Name())) {
s, _ := os.Stat(config.KmodsImage(file.Name()))
kmods_size = s.Size() / 1024
}
if nodemap[file.Name()] > 0 {
fmt.Printf("%-38s %-16d %-16d %d\n", file.Name(), kernel_size, kmods_size, nodemap[file.Name()])
} else {
fmt.Printf("%-38s %-16d %-16d %d\n", file.Name(), kernel_size, kmods_size, 0)
}
}
}
return nil
}

View File

@@ -1,6 +1,7 @@
package add
import (
"fmt"
"github.com/hpcng/warewulf/internal/pkg/node"
"github.com/hpcng/warewulf/internal/pkg/wwlog"
"github.com/spf13/cobra"
@@ -15,11 +16,12 @@ func CobraRunE(cmd *cobra.Command, args []string) error {
}
for _, a := range args {
err = nodeDB.AddNode(SetGroup, a)
err = nodeDB.AddNode(SetController, SetGroup, a)
if err != nil {
wwlog.Printf(wwlog.ERROR, "%s\n", err)
os.Exit(1)
}
fmt.Printf("Added node: %s\n", a)
}
nodeDB.Persist()

View File

@@ -11,10 +11,12 @@ var (
Args: cobra.MinimumNArgs(1),
}
SetGroup string
SetController string
)
func init() {
baseCmd.PersistentFlags().StringVarP(&SetGroup, "group", "g", "default", "Set group to add nodes to")
baseCmd.PersistentFlags().StringVarP(&SetGroup, "group", "g", "default", "Group to add nodes to")
baseCmd.PersistentFlags().StringVarP(&SetController, "controller", "c", "default", "Controller to add nodes to")
}
// GetRootCommand returns the root cobra.Command for the application.

View File

@@ -21,11 +21,11 @@ func CobraRunE(cmd *cobra.Command, args []string) error {
nodeList, err := nodeDB.SearchByNameList(args)
for _, n := range nodeList {
if SetGroup != "" && SetGroup != n.GroupName {
wwlog.Printf(wwlog.DEBUG, "skipping node of different group: %s/%s\n", n.GroupName, n.Id)
if SetGroup != "" && SetGroup != n.Gid.String() {
wwlog.Printf(wwlog.DEBUG, "skipping node of different group: %s/%s\n", n.Gid, n.Id)
continue
}
err := nodeDB.DelNode(n.GroupName, n.Id)
err := nodeDB.DelNode(n.Cid.Get(), n.Gid.Get(), n.Id.Get())
if err != nil {
wwlog.Printf(wwlog.ERROR, "%s\n", err)
} else {

View File

@@ -11,11 +11,13 @@ var (
}
SetForce string
SetGroup string
SetController string
)
func init() {
baseCmd.PersistentFlags().StringVarP(&SetForce, "force", "f", "", "Force node delete")
baseCmd.PersistentFlags().StringVarP(&SetGroup, "group", "g", "default", "Set group to delete nodes from")
baseCmd.PersistentFlags().StringVarP(&SetController, "controller", "c", "default", "Controller to add nodes to")
}

View File

@@ -6,7 +6,7 @@ import (
"github.com/hpcng/warewulf/internal/pkg/wwlog"
"github.com/spf13/cobra"
"os"
"reflect"
"strings"
)
@@ -34,36 +34,76 @@ func CobraRunE(cmd *cobra.Command, args []string) error {
if ShowAll == true {
for _, node := range nodes {
v := reflect.ValueOf(node)
typeOfS := v.Type()
fmt.Printf("################################################################################\n")
for i := 0; i< v.NumField(); i++ {
fmt.Printf("%-25s %s = %v\n", node.Fqdn, typeOfS.Field(i).Name, v.Field(i).Interface())
fmt.Printf("%-20s %-18s %8s: %s\n", node.Fqdn.Get(), "Id", node.Id.Source(), node.Id.String())
fmt.Printf("%-20s %-18s %8s: %s\n", node.Fqdn.Get(), "Comment", node.Comment.Source(), node.Comment.String())
fmt.Printf("%-20s %-18s %8s: %s\n", node.Fqdn.Get(), "GroupName", node.Gid.Source(), node.Gid.String())
fmt.Printf("%-20s %-18s %8s: %s\n", node.Fqdn.Get(), "DomainName", node.DomainName.Source(), node.DomainName.String())
fmt.Printf("%-20s %-18s %8s: %s\n", node.Fqdn.Get(), "Profiles (Group)", "group", strings.Join(node.GroupProfiles, ","))
fmt.Printf("%-20s %-18s %8s: %s\n", node.Fqdn.Get(), "Profiles (Node)", "node", strings.Join(node.Profiles, ","))
fmt.Printf("%-20s %-18s %8s: %s\n", node.Fqdn.Get(), "Vnfs", node.Vnfs.Source(), node.Vnfs.String())
fmt.Printf("%-20s %-18s %8s: %s\n", node.Fqdn.Get(), "KernelVersion", node.KernelVersion.Source(), node.KernelVersion.String())
fmt.Printf("%-20s %-18s %8s: %s\n", node.Fqdn.Get(), "KernelArgs", node.KernelArgs.Source(), node.KernelArgs.String())
fmt.Printf("%-20s %-18s %8s: %s\n", node.Fqdn.Get(), "RuntimeOverlay", node.RuntimeOverlay.Source(), node.RuntimeOverlay.String())
fmt.Printf("%-20s %-18s %8s: %s\n", node.Fqdn.Get(), "SystemOverlay", node.SystemOverlay.Source(), node.SystemOverlay.String())
fmt.Printf("%-20s %-18s %8s: %s\n", node.Fqdn.Get(), "IpmiUserName", node.IpmiUserName.Source(), node.IpmiUserName.String())
fmt.Printf("%-20s %-18s %8s: %s\n", node.Fqdn.Get(), "IpmiIpaddr", node.IpmiIpaddr.Source(), node.IpmiIpaddr.String())
fmt.Printf("%-20s %-18s %8s: %s\n", node.Fqdn.Get(), "Ipxe", node.Ipxe.Source(), node.Ipxe.String())
for name, netdev := range node.NetDevs {
fmt.Printf("%-20s %-18s %8s: %s\n", node.Fqdn.Get(), name +":IPADDR", "node", netdev.Ipaddr)
fmt.Printf("%-20s %-18s %8s: %s\n", node.Fqdn.Get(), name +":NETMASK", "node", netdev.Netmask)
fmt.Printf("%-20s %-18s %8s: %s\n", node.Fqdn.Get(), name +":GATEWAY", "node", netdev.Gateway)
fmt.Printf("%-20s %-18s %8s: %s\n", node.Fqdn.Get(), name +":HWADDR", "node", netdev.Hwaddr)
}
// v := reflect.ValueOf(node)
// typeOfS := v.Type()
// for i := 0; i< v.NumField(); i++ {
// //TODO: Fix for NetDevs and Interface should print Fprint() method
// fmt.Printf("%-25s %s = %#v\n", node.Fqdn.Get(), typeOfS.Field(i).Name, v.Field(i).Interface())
// }
}
} else if ShowNet == true {
fmt.Printf("%-22s %-10s %-20s %-16s %-16s %-16s %s\n", "NODE NAME", "DEVICE", "HWADDR", "IPADDR", "NETMASK", "GATEWAY", "TYPE")
fmt.Printf("%-22s %-6s %-18s %-15s %-15s\n", "NODE NAME", "DEVICE", "HWADDR", "IPADDR", "GATEWAY")
fmt.Println(strings.Repeat("=", 80))
for _, node := range nodes {
for name, dev := range node.NetDevs {
fmt.Printf("%-22s %-10s %-20s %-16s %-16s %-16s %s\n", node.Fqdn, name, dev.Hwaddr, dev.Ipaddr, dev.Netmask, dev.Gateway, dev.Type)
if len(node.NetDevs) > 0 {
for name, dev := range node.NetDevs {
fmt.Printf("%-22s %-6s %-18s %-15s %-15s\n", node.Fqdn.Get(), name, dev.Hwaddr, dev.Ipaddr, dev.Gateway)
}
} else {
fmt.Printf("%-22s %-6s %-18s %-15s %-15s\n", node.Fqdn.Get(), "--", "--", "--", "--")
}
}
} else if ShowIpmi == true {
fmt.Printf("%-22s %-16s %-20s %-20s\n", "NODE NAME", "IPMI IPADDR", "IPMI USERNAME", "IPMI PASSWORD")
fmt.Println(strings.Repeat("=", 80))
for _, node := range nodes {
fmt.Printf("%-22s %-16s %-20s %-20s\n", node.Fqdn, node.IpmiIpaddr, node.IpmiUserName, node.IpmiPassword)
fmt.Printf("%-22s %-16s %-20s %-20s\n", node.Fqdn.Get(), node.IpmiIpaddr.String(), node.IpmiUserName.String(), node.IpmiPassword.String())
}
} else if ShowLong == true {
fmt.Printf("%-22s %-12s %-26s %-35s %s\n", "NODE NAME", "GROUP NAME", "KERNEL VERSION", "VNFS IMAGE", "OVERLAYS (S/R)")
fmt.Println(strings.Repeat("=", 120))
for _, node := range nodes {
fmt.Printf("%-22s %-12s %-26s %-35s %s\n", node.Fqdn.Get(), node.Gid.String(), node.KernelVersion.String(), node.Vnfs.String(), node.SystemOverlay.String() +"/"+ node.RuntimeOverlay.String())
}
} else {
fmt.Printf("%-22s %-16s %-30s %-30s %-16s\n", "NODE NAME", "GROUP NAME", "KERNEL VERSION", "VNFS IMAGE", "RUNTIME OVERLAY")
fmt.Printf("%-22s %-30s %s\n", "NODE NAME", "VNFS", "PROFILES")
fmt.Println(strings.Repeat("=", 80))
for _, node := range nodes {
fmt.Printf("%-22s %-16s %-30s %-30s %-16s\n", node.Fqdn, node.GroupName, node.KernelVersion, node.Vnfs, node.RuntimeOverlay)
fmt.Printf("%-22s %-30s %s\n", node.Fqdn.Get(), node.Vnfs.String(), strings.Join(append(node.GroupProfiles, node.Profiles...), ","))
}
}

View File

@@ -12,12 +12,14 @@ var (
ShowNet bool
ShowIpmi bool
ShowAll bool
ShowLong bool
)
func init() {
baseCmd.PersistentFlags().BoolVarP(&ShowNet, "net", "n", false, "Show node network configurations")
baseCmd.PersistentFlags().BoolVarP(&ShowIpmi, "ipmi", "i", false, "Show node IPMI configurations")
baseCmd.PersistentFlags().BoolVarP(&ShowAll, "all", "a", false, "Show all node configurations")
baseCmd.PersistentFlags().BoolVarP(&ShowLong, "long", "l", false, "Show long or wide format")
}
// GetRootCommand returns the root cobra.Command for the application.

View File

@@ -34,13 +34,13 @@ func CobraRunE(cmd *cobra.Command, args []string) error {
for _, node := range nodeList {
if node.IpmiIpaddr == "" {
if node.IpmiIpaddr.String() == "" {
wwlog.Printf(wwlog.ERROR, "%s: No IPMI IP address\n", node.HostName)
continue
}
ipmiCmd := power.IPMI{
HostName: node.IpmiIpaddr,
HostName: node.IpmiIpaddr.String(),
User: "ADMIN",
Password: "ADMIN",
AuthType: "MD5",

View File

@@ -36,13 +36,13 @@ func CobraRunE(cmd *cobra.Command, args []string) error {
var powerCmd power.PowerOnInterface
if node.IpmiIpaddr == "" {
if node.IpmiIpaddr.String() == "" {
wwlog.Printf(wwlog.ERROR, "%s: No IPMI IP address\n", node.HostName)
continue
}
ipmiCmd := power.IPMI{
HostName: node.IpmiIpaddr,
HostName: node.IpmiIpaddr.String(),
User: "ADMIN",
Password: "ADMIN",
AuthType: "MD5",

View File

@@ -34,13 +34,13 @@ func CobraRunE(cmd *cobra.Command, args []string) error {
for _, node := range nodeList {
if node.IpmiIpaddr == "" {
if node.IpmiIpaddr.String() == "" {
wwlog.Printf(wwlog.ERROR, "%s: No IPMI IP address\n", node.HostName)
continue
}
ipmiCmd := power.IPMI{
HostName: node.IpmiIpaddr,
HostName: node.IpmiIpaddr.String(),
User: "ADMIN",
Password: "ADMIN",
AuthType: "MD5",

View File

@@ -3,6 +3,7 @@ package set
import (
"fmt"
"github.com/hpcng/warewulf/internal/pkg/node"
"github.com/hpcng/warewulf/internal/pkg/util"
"github.com/hpcng/warewulf/internal/pkg/wwlog"
"github.com/manifoldco/promptui"
"github.com/spf13/cobra"
@@ -24,31 +25,42 @@ func CobraRunE(cmd *cobra.Command, args []string) error {
os.Exit(1)
}
if len(args) > 0 {
nodes, err = nodeDB.SearchByNameList(args)
if SetNodeAll == true {
nodes, err = nodeDB.FindAllNodes()
if err != nil {
wwlog.Printf(wwlog.ERROR, "Cloud not get nodeList: %s\n", err)
os.Exit(1)
}
} else if len(args) > 0 {
nodes, err = nodeDB.SearchByNameList(args)
if err != nil {
wwlog.Printf(wwlog.ERROR, "Cloud not get nodeList: %s\n", err)
os.Exit(1)
}
} else {
cmd.Usage()
os.Exit(1)
}
for _, n := range nodes {
wwlog.Printf(wwlog.VERBOSE, "Evaluating node: %s\n", n.Fqdn)
wwlog.Printf(wwlog.VERBOSE, "Evaluating node: %s\n", n.Fqdn.String())
if SetVnfs != "" {
wwlog.Printf(wwlog.VERBOSE, "Node: %s, Setting vnfs to: %s\n", n.Fqdn, SetVnfs)
err := nodeDB.SetNodeVal(n.Gid, n.Id, "vnfs", SetVnfs)
wwlog.Printf(wwlog.VERBOSE, "Node: %s, Setting vnfs to: %s\n", n.Fqdn.String(), SetVnfs)
n.Vnfs.Set(SetVnfs)
err := nodeDB.NodeUpdate(n)
if err != nil {
wwlog.Printf(wwlog.ERROR, "%s\n", err)
os.Exit(1)
}
}
if SetKernel != "" {
wwlog.Printf(wwlog.VERBOSE, "Node: %s, Setting kernel to: %s\n", n.Fqdn, SetVnfs)
err := nodeDB.SetNodeVal(n.Gid, n.Id, "kernel", SetKernel)
wwlog.Printf(wwlog.VERBOSE, "Node: %s, Setting kernel to: %s\n", n.Fqdn.String(), SetKernel)
n.KernelVersion.Set(SetKernel)
err := nodeDB.NodeUpdate(n)
if err != nil {
wwlog.Printf(wwlog.ERROR, "%s\n", err)
os.Exit(1)
@@ -56,7 +68,9 @@ func CobraRunE(cmd *cobra.Command, args []string) error {
}
if SetDomainName != "" {
wwlog.Printf(wwlog.VERBOSE, "Node: %s, Setting domain name to: %s\n", n.Fqdn, SetDomainName)
err := nodeDB.SetNodeVal(n.Gid, n.Id, "domain", SetDomainName)
n.DomainName.Set(SetDomainName)
err := nodeDB.NodeUpdate(n)
if err != nil {
wwlog.Printf(wwlog.ERROR, "%s\n", err)
os.Exit(1)
@@ -64,7 +78,9 @@ func CobraRunE(cmd *cobra.Command, args []string) error {
}
if SetIpxe != "" {
wwlog.Printf(wwlog.VERBOSE, "Node: %s, Setting iPXE template to: %s\n", n.Fqdn, SetIpxe)
err := nodeDB.SetNodeVal(n.Gid, n.Id, "ipxe", SetIpxe)
n.Ipxe.Set(SetIpxe)
err := nodeDB.NodeUpdate(n)
if err != nil {
wwlog.Printf(wwlog.ERROR, "%s\n", err)
os.Exit(1)
@@ -72,7 +88,9 @@ func CobraRunE(cmd *cobra.Command, args []string) error {
}
if SetRuntimeOverlay != "" {
wwlog.Printf(wwlog.VERBOSE, "Node: %s, Setting runtime overlay to: %s\n", n.Fqdn, SetRuntimeOverlay)
err := nodeDB.SetNodeVal(n.Gid, n.Id, "runtimeoverlay", SetRuntimeOverlay)
n.RuntimeOverlay.Set(SetRuntimeOverlay)
err := nodeDB.NodeUpdate(n)
if err != nil {
wwlog.Printf(wwlog.ERROR, "%s\n", err)
os.Exit(1)
@@ -80,7 +98,9 @@ func CobraRunE(cmd *cobra.Command, args []string) error {
}
if SetSystemOverlay != "" {
wwlog.Printf(wwlog.VERBOSE, "Node: %s, Setting system overlay to: %s\n", n.Fqdn, SetSystemOverlay)
err := nodeDB.SetNodeVal(n.Gid, n.Id, "systemoverlay", SetSystemOverlay)
n.SystemOverlay.Set(SetSystemOverlay)
err := nodeDB.NodeUpdate(n)
if err != nil {
wwlog.Printf(wwlog.ERROR, "%s\n", err)
os.Exit(1)
@@ -88,7 +108,9 @@ func CobraRunE(cmd *cobra.Command, args []string) error {
}
if SetHostname != "" {
wwlog.Printf(wwlog.VERBOSE, "Node: %s, Setting hostname to: %s\n", n.Fqdn, SetHostname)
err := nodeDB.SetNodeVal(n.Gid, n.Id, "hostname", SetHostname)
n.HostName.Set(SetHostname)
err := nodeDB.NodeUpdate(n)
if err != nil {
wwlog.Printf(wwlog.ERROR, "%s\n", err)
os.Exit(1)
@@ -96,7 +118,9 @@ func CobraRunE(cmd *cobra.Command, args []string) error {
}
if SetIpmiIpaddr != "" {
wwlog.Printf(wwlog.VERBOSE, "Node: %s, Setting IPMI IP address to: %s\n", n.Fqdn, SetIpmiIpaddr)
err := nodeDB.SetNodeVal(n.Gid, n.Id, "ipmiipaddr", SetIpmiIpaddr)
n.IpmiIpaddr.Set(SetIpmiIpaddr)
err := nodeDB.NodeUpdate(n)
if err != nil {
wwlog.Printf(wwlog.ERROR, "%s\n", err)
os.Exit(1)
@@ -104,7 +128,9 @@ func CobraRunE(cmd *cobra.Command, args []string) error {
}
if SetIpmiUsername != "" {
wwlog.Printf(wwlog.VERBOSE, "Node: %s, Setting IPMI IP username to: %s\n", n.Fqdn, SetIpmiUsername)
err := nodeDB.SetNodeVal(n.Gid, n.Id, "ipmiusername", SetIpmiUsername)
n.IpmiUserName.Set(SetIpmiUsername)
err := nodeDB.NodeUpdate(n)
if err != nil {
wwlog.Printf(wwlog.ERROR, "%s\n", err)
os.Exit(1)
@@ -112,7 +138,32 @@ func CobraRunE(cmd *cobra.Command, args []string) error {
}
if SetIpmiPassword != "" {
wwlog.Printf(wwlog.VERBOSE, "Node: %s, Setting IPMI IP password to: %s\n", n.Fqdn, SetIpmiPassword)
err := nodeDB.SetNodeVal(n.Gid, n.Id, "ipmipassword", SetIpmiPassword)
n.IpmiPassword.Set(SetIpmiPassword)
err := nodeDB.NodeUpdate(n)
if err != nil {
wwlog.Printf(wwlog.ERROR, "%s\n", err)
os.Exit(1)
}
}
if len(SetAddProfile) > 0 {
for _, p := range SetAddProfile {
wwlog.Printf(wwlog.VERBOSE, "Node: %s, adding profile to '%s'\n", n.Fqdn, p)
n.Profiles = util.SliceAddUniqueElement(n.Profiles, p)
}
err := nodeDB.NodeUpdate(n)
if err != nil {
wwlog.Printf(wwlog.ERROR, "%s\n", err)
os.Exit(1)
}
}
if len(SetDelProfile) > 0 {
for _, p := range SetDelProfile {
wwlog.Printf(wwlog.VERBOSE, "Node: %s, deleting profile from '%s'\n", n.Fqdn, p)
n.Profiles = util.SliceRemoveElement(n.Profiles, p)
}
err := nodeDB.NodeUpdate(n)
if err != nil {
wwlog.Printf(wwlog.ERROR, "%s\n", err)
os.Exit(1)
@@ -127,20 +178,33 @@ func CobraRunE(cmd *cobra.Command, args []string) error {
os.Exit(1)
}
wwlog.Printf(wwlog.VERBOSE, "Node: %s, Deleting network device: %s\n", n.Fqdn, SetNetDev)
err := nodeDB.DelNodeNet(n.Gid, n.Id, SetNetDev)
if _, ok := n.NetDevs[SetNetDev]; !ok {
wwlog.Printf(wwlog.ERROR, "Network Device doesn't exist: %s\n", SetNetDev)
os.Exit(1)
}
delete(n.NetDevs, SetNetDev)
err := nodeDB.NodeUpdate(n)
if err != nil {
wwlog.Printf(wwlog.ERROR, "%s\n", err)
os.Exit(1)
}
}
if SetIpaddr != "" {
if SetNetDev == "" {
wwlog.Printf(wwlog.ERROR, "You must include the '--netdev' option\n")
os.Exit(1)
}
if _, ok := n.NetDevs[SetNetDev]; !ok {
wwlog.Printf(wwlog.ERROR, "Network Device doesn't exist: %s\n", SetNetDev)
os.Exit(1)
}
wwlog.Printf(wwlog.VERBOSE, "Node: %s:%s, Setting Ipaddr to: %s\n", n.Fqdn, SetNetDev, SetIpaddr)
err := nodeDB.SetNodeNet(n.Gid, n.Id, SetNetDev, "ipaddr", SetIpaddr)
n.NetDevs[SetNetDev].Ipaddr = SetIpaddr
err := nodeDB.NodeUpdate(n)
if err != nil {
wwlog.Printf(wwlog.ERROR, "%s\n", err)
os.Exit(1)
@@ -151,8 +215,15 @@ func CobraRunE(cmd *cobra.Command, args []string) error {
wwlog.Printf(wwlog.ERROR, "You must include the '--netdev' option\n")
os.Exit(1)
}
if _, ok := n.NetDevs[SetNetDev]; !ok {
wwlog.Printf(wwlog.ERROR, "Network Device doesn't exist: %s\n", SetNetDev)
os.Exit(1)
}
wwlog.Printf(wwlog.VERBOSE, "Node: %s:%s, Setting netmask to: %s\n", n.Fqdn, SetNetDev, SetNetmask)
err := nodeDB.SetNodeNet(n.Gid, n.Id, SetNetDev, "netmask", SetNetmask)
n.NetDevs[SetNetDev].Netmask = SetNetmask
err := nodeDB.NodeUpdate(n)
if err != nil {
wwlog.Printf(wwlog.ERROR, "%s\n", err)
os.Exit(1)
@@ -163,8 +234,15 @@ func CobraRunE(cmd *cobra.Command, args []string) error {
wwlog.Printf(wwlog.ERROR, "You must include the '--netdev' option\n")
os.Exit(1)
}
if _, ok := n.NetDevs[SetNetDev]; !ok {
wwlog.Printf(wwlog.ERROR, "Network Device doesn't exist: %s\n", SetNetDev)
os.Exit(1)
}
wwlog.Printf(wwlog.VERBOSE, "Node: %s:%s, Setting gateway to: %s\n", n.Fqdn, SetNetDev, SetGateway)
err := nodeDB.SetNodeNet(n.Gid, n.Id, SetNetDev, "gateway", SetGateway)
n.NetDevs[SetNetDev].Gateway = SetGateway
err := nodeDB.NodeUpdate(n)
if err != nil {
wwlog.Printf(wwlog.ERROR, "%s\n", err)
os.Exit(1)
@@ -175,8 +253,15 @@ func CobraRunE(cmd *cobra.Command, args []string) error {
wwlog.Printf(wwlog.ERROR, "You must include the '--netdev' option\n")
os.Exit(1)
}
if _, ok := n.NetDevs[SetNetDev]; !ok {
wwlog.Printf(wwlog.ERROR, "Network Device doesn't exist: %s\n", SetNetDev)
os.Exit(1)
}
wwlog.Printf(wwlog.VERBOSE, "Node: %s:%s, Setting HW address to: %s\n", n.Fqdn, SetNetDev, SetHwaddr)
err := nodeDB.SetNodeNet(n.Gid, n.Id, SetNetDev, "hwaddr", SetHwaddr)
n.NetDevs[SetNetDev].Hwaddr = SetHwaddr
err := nodeDB.NodeUpdate(n)
if err != nil {
wwlog.Printf(wwlog.ERROR, "%s\n", err)
os.Exit(1)
@@ -185,17 +270,21 @@ func CobraRunE(cmd *cobra.Command, args []string) error {
}
if len(nodes) > 0 {
q := fmt.Sprintf("Are you sure you want to modify %d nodes(s)", len(nodes))
prompt := promptui.Prompt{
Label: q,
IsConfirm: true,
}
result, _ := prompt.Run()
if result == "y" || result == "yes" {
if SetYes == true {
nodeDB.Persist()
} else {
q := fmt.Sprintf("Are you sure you want to modify %d nodes(s)", len(nodes))
prompt := promptui.Prompt{
Label: q,
IsConfirm: true,
}
result, _ := prompt.Run()
if result == "y" || result == "yes" {
nodeDB.Persist()
}
}
} else {

View File

@@ -25,7 +25,10 @@ var (
SetIpmiIpaddr string
SetIpmiUsername string
SetIpmiPassword string
SetNodeAll bool
SetYes bool
SetAddProfile []string
SetDelProfile []string
)
func init() {
@@ -35,17 +38,23 @@ func init() {
baseCmd.PersistentFlags().StringVarP(&SetIpxe, "ipxe", "P", "", "Set the node's iPXE template name")
baseCmd.PersistentFlags().StringVarP(&SetRuntimeOverlay, "runtime", "R", "", "Set the node's runtime overlay")
baseCmd.PersistentFlags().StringVarP(&SetSystemOverlay, "system", "S", "", "Set the node's system overlay")
baseCmd.PersistentFlags().StringVarP(&SetHostname, "hostname", "H", "", "Set the node's hostname")
baseCmd.PersistentFlags().StringVarP(&SetHostname, "hostname", "N", "", "Set the node's hostname")
baseCmd.PersistentFlags().StringVar(&SetIpmiIpaddr, "ipmi", "", "Set the node's IPMI address")
baseCmd.PersistentFlags().StringVar(&SetIpmiUsername, "ipmiuser", "", "Set the node's IPMI username")
baseCmd.PersistentFlags().StringVar(&SetIpmiPassword, "ipmipass", "", "Set the node's IPMI password")
baseCmd.PersistentFlags().StringSliceVarP(&SetAddProfile, "addprofile", "p", []string{}, "Add Profile(s) to node")
baseCmd.PersistentFlags().StringSliceVarP(&SetDelProfile, "delprofile", "r", []string{}, "Remove Profile(s) to node")
baseCmd.PersistentFlags().StringVarP(&SetNetDev, "netdev", "n", "", "Define the network device to configure")
baseCmd.PersistentFlags().StringVarP(&SetIpaddr, "ipaddr", "I", "", "Set the node's network device IP address")
baseCmd.PersistentFlags().StringVarP(&SetNetmask, "netmask", "M", "", "Set the node's network device netmask")
baseCmd.PersistentFlags().StringVarP(&SetGateway, "gateway", "G", "", "Set the node's network device gateway")
baseCmd.PersistentFlags().StringVarP(&SetHwaddr, "hwaddr", "N", "", "Set the node's network device HW address")
baseCmd.PersistentFlags().StringVarP(&SetHwaddr, "hwaddr", "H", "", "Set the node's network device HW address")
baseCmd.PersistentFlags().BoolVar(&SetNetDevDel, "delete", false, "Delete the node's network device")
baseCmd.PersistentFlags().BoolVarP(&SetNodeAll, "all", "a", false, "Set all nodes")
baseCmd.PersistentFlags().BoolVarP(&SetYes, "yes", "y", false, "Set 'yes' to all questions asked")
}

View File

@@ -25,9 +25,9 @@ func CobraRunE(cmd *cobra.Command, args []string) error {
}
for _, node := range nodes {
if SystemOverlay == true && node.SystemOverlay == args[0] {
if SystemOverlay == true && node.SystemOverlay.String() == args[0] {
updateNodes = append(updateNodes, node)
} else if node.RuntimeOverlay == args[0] {
} else if node.RuntimeOverlay.String() == args[0] {
updateNodes = append(updateNodes, node)
}
}
@@ -43,16 +43,16 @@ func CobraRunE(cmd *cobra.Command, args []string) error {
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)
err := overlay.BuildSystemOverlay(updateNodes)
if err != nil {
wwlog.Printf(wwlog.WARN, "Some system overlays failed to be generated\n")
wwlog.Printf(wwlog.WARN, "Some system overlays failed to be generated: %s\n", err)
}
}
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)
err := overlay.BuildRuntimeOverlay(updateNodes)
if err != nil {
wwlog.Printf(wwlog.WARN, "Some runtime overlays failed to be generated\n")
}

View File

@@ -64,19 +64,19 @@ func CobraRunE(cmd *cobra.Command, args []string) error {
var updateNodes []node.NodeInfo
for _, node := range nodes {
if SystemOverlay == true && node.SystemOverlay == overlayName {
if SystemOverlay == true && node.SystemOverlay.String() == overlayName {
updateNodes = append(updateNodes, node)
} else if node.RuntimeOverlay == overlayName {
} else if node.RuntimeOverlay.String() == overlayName {
updateNodes = append(updateNodes, node)
}
}
if SystemOverlay == true {
wwlog.Printf(wwlog.INFO, "Updating System Overlays...\n")
return overlay.SystemBuild(updateNodes, true)
return overlay.BuildSystemOverlay(updateNodes)
} else {
wwlog.Printf(wwlog.INFO, "Updating Runtime Overlays...\n")
return overlay.RuntimeBuild(updateNodes, true)
return overlay.BuildRuntimeOverlay(updateNodes)
}
}

View File

@@ -48,19 +48,19 @@ func CobraRunE(cmd *cobra.Command, args []string) error {
var updateNodes []node.NodeInfo
for _, node := range nodes {
if SystemOverlay == true && node.SystemOverlay == args[0] {
if SystemOverlay == true && node.SystemOverlay.String() == args[0] {
updateNodes = append(updateNodes, node)
} else if node.RuntimeOverlay == args[0] {
} else if node.RuntimeOverlay.String() == args[0] {
updateNodes = append(updateNodes, node)
}
}
if SystemOverlay == true {
wwlog.Printf(wwlog.INFO, "Updating System Overlays...\n")
return overlay.SystemBuild(updateNodes, true)
return overlay.BuildSystemOverlay(updateNodes)
} else {
wwlog.Printf(wwlog.INFO, "Updating Runtime Overlays...\n")
return overlay.RuntimeBuild(updateNodes, true)
return overlay.BuildRuntimeOverlay(updateNodes)
}
}

View File

@@ -110,19 +110,19 @@ func CobraRunE(cmd *cobra.Command, args []string) error {
var updateNodes []node.NodeInfo
for _, node := range nodes {
if SystemOverlay == true && node.SystemOverlay == args[0] {
if SystemOverlay == true && node.SystemOverlay.String() == args[0] {
updateNodes = append(updateNodes, node)
} else if node.RuntimeOverlay == args[0] {
} else if node.RuntimeOverlay.String() == args[0] {
updateNodes = append(updateNodes, node)
}
}
if SystemOverlay == true {
wwlog.Printf(wwlog.INFO, "Updating System Overlays...\n")
return overlay.SystemBuild(updateNodes, true)
return overlay.BuildSystemOverlay(updateNodes)
} else {
wwlog.Printf(wwlog.INFO, "Updating Runtime Overlays...\n")
return overlay.RuntimeBuild(updateNodes, true)
return overlay.BuildRuntimeOverlay(updateNodes)
}
}

View File

@@ -69,7 +69,6 @@ func CobraRunE(cmd *cobra.Command, args []string) error {
fmt.Fprintf(w, "\n")
}
shasum1, err := util.ShaSumFile(overlayFile)
if err != nil {
wwlog.Printf(wwlog.WARN, "Could not open overlay file for checksum: %s\n", err)
@@ -80,7 +79,7 @@ func CobraRunE(cmd *cobra.Command, args []string) error {
wwlog.Printf(wwlog.ERROR, "Editor process existed with non-zero\n")
os.Exit(1)
}
wwlog.Printf(wwlog.INFO, "Updated: %s %s\n", args[0], args[1] )
wwlog.Printf(wwlog.INFO, "Updated: %s %s\n", args[0], args[1])
shasum2, err := util.ShaSumFile(overlayFile)
if err != nil {
@@ -108,22 +107,21 @@ func CobraRunE(cmd *cobra.Command, args []string) error {
var updateNodes []node.NodeInfo
for _, node := range nodes {
if SystemOverlay == true && node.SystemOverlay == args[0] {
if SystemOverlay == true && node.SystemOverlay.String() == args[0] {
updateNodes = append(updateNodes, node)
} else if node.RuntimeOverlay == args[0] {
} else if node.RuntimeOverlay.String() == args[0] {
updateNodes = append(updateNodes, node)
}
}
if SystemOverlay == true {
wwlog.Printf(wwlog.INFO, "Updating System Overlays...\n")
return overlay.SystemBuild(updateNodes, true)
return overlay.BuildSystemOverlay(updateNodes)
} else {
wwlog.Printf(wwlog.INFO, "Updating Runtime Overlays...\n")
return overlay.RuntimeBuild(updateNodes, true)
return overlay.BuildRuntimeOverlay(updateNodes)
}
}
return nil
}

View File

@@ -60,19 +60,19 @@ func CobraRunE(cmd *cobra.Command, args []string) error {
var updateNodes []node.NodeInfo
for _, node := range nodes {
if SystemOverlay == true && node.SystemOverlay == overlayName {
if SystemOverlay == true && node.SystemOverlay.String() == overlayName {
updateNodes = append(updateNodes, node)
} else if node.RuntimeOverlay == overlayName {
} else if node.RuntimeOverlay.String() == overlayName {
updateNodes = append(updateNodes, node)
}
}
if SystemOverlay == true {
wwlog.Printf(wwlog.INFO, "Updating System Overlays...\n")
return overlay.SystemBuild(updateNodes, true)
return overlay.BuildSystemOverlay(updateNodes)
} else {
wwlog.Printf(wwlog.INFO, "Updating Runtime Overlays...\n")
return overlay.RuntimeBuild(updateNodes, true)
return overlay.BuildRuntimeOverlay(updateNodes)
}
}

View File

@@ -31,14 +31,14 @@ func CobraRunE(cmd *cobra.Command, args []string) error {
} else {
fmt.Printf("%-10s %5s %-5s %-18s %s\n", "PERM MODE", "UID", "GID", "SYSTEM-OVERLAY", "FILE PATH")
}
o, err = overlay.FindAllSystemOverlays()
o, err = overlay.FindSystemOverlays()
} else {
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()
o, err = overlay.FindRuntimeOverlays()
}
if err != nil {
wwlog.Printf(wwlog.ERROR, "Could not get system overlays: %s\n", err)
@@ -53,12 +53,12 @@ func CobraRunE(cmd *cobra.Command, args []string) error {
for _, node := range nodeList {
if SystemOverlay == true {
if node.SystemOverlay != "" {
set[node.SystemOverlay] ++
if node.SystemOverlay.Get() != "" {
set[node.SystemOverlay.Get()] ++
}
} else {
if node.RuntimeOverlay != "" {
set[node.RuntimeOverlay] ++
if node.RuntimeOverlay.Get() != "" {
set[node.RuntimeOverlay.Get()] ++
}
}
}

View File

@@ -57,19 +57,19 @@ func CobraRunE(cmd *cobra.Command, args []string) error {
var updateNodes []node.NodeInfo
for _, node := range nodes {
if SystemOverlay == true && node.SystemOverlay == args[0] {
if SystemOverlay == true && node.SystemOverlay.String() == args[0] {
updateNodes = append(updateNodes, node)
} else if node.RuntimeOverlay == args[0] {
} else if node.RuntimeOverlay.String() == args[0] {
updateNodes = append(updateNodes, node)
}
}
if SystemOverlay == true {
wwlog.Printf(wwlog.INFO, "Updating System Overlays...\n")
return overlay.SystemBuild(updateNodes, true)
return overlay.BuildSystemOverlay(updateNodes)
} else {
wwlog.Printf(wwlog.INFO, "Updating Runtime Overlays...\n")
return overlay.RuntimeBuild(updateNodes, true)
return overlay.BuildRuntimeOverlay(updateNodes)
}
}

View File

@@ -10,7 +10,6 @@ import (
"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"
)
@@ -35,7 +34,6 @@ func init() {
baseCmd.AddCommand(build.GetCommand())
baseCmd.AddCommand(imprt.GetCommand())
baseCmd.AddCommand(chmod.GetCommand())
}
// GetRootCommand returns the root cobra.Command for the application.

View File

@@ -0,0 +1,28 @@
package add
import (
"github.com/hpcng/warewulf/internal/pkg/node"
"github.com/hpcng/warewulf/internal/pkg/wwlog"
"github.com/spf13/cobra"
"os"
)
func CobraRunE(cmd *cobra.Command, args []string) error {
nodeDB, err := node.New()
if err != nil {
wwlog.Printf(wwlog.ERROR, "Failed opening node database: %s\n", err)
os.Exit(1)
}
for _, p := range args {
err = nodeDB.AddProfile(p)
if err != nil {
wwlog.Printf(wwlog.ERROR, "%s\n", err)
os.Exit(1)
}
}
nodeDB.Persist()
return nil
}

View File

@@ -0,0 +1,20 @@
package add
import "github.com/spf13/cobra"
var (
baseCmd = &cobra.Command{
Use: "add",
Short: "Add profiles",
Long: "Profile configurations ",
RunE: CobraRunE,
}
)
func init() {
}
// GetRootCommand returns the root cobra.Command for the application.
func GetCommand() *cobra.Command {
return baseCmd
}

View File

@@ -0,0 +1,85 @@
package delete
import (
"fmt"
"github.com/hpcng/warewulf/internal/pkg/node"
"github.com/hpcng/warewulf/internal/pkg/util"
"github.com/hpcng/warewulf/internal/pkg/wwlog"
"github.com/manifoldco/promptui"
"github.com/spf13/cobra"
"os"
)
func CobraRunE(cmd *cobra.Command, args []string) error {
var count int
var numNodes int
var numGroups int
nodeDB, err := node.New()
if err != nil {
wwlog.Printf(wwlog.ERROR, "Failed to open node database: %s\n", err)
os.Exit(1)
}
nodes, err := nodeDB.FindAllNodes()
if err != nil {
wwlog.Printf(wwlog.ERROR, "Could not load all nodes: %s\n", err)
os.Exit(1)
}
groups, err := nodeDB.FindAllGroups()
if err != nil {
wwlog.Printf(wwlog.ERROR, "Could not load all groups: %s\n", err)
os.Exit(1)
}
for _, p := range args {
err := nodeDB.DelProfile(p)
if err != nil {
wwlog.Printf(wwlog.ERROR, "%s\n", err)
continue
}
for _, n := range nodes {
for _, np := range n.Profiles {
if np == p {
numNodes++
wwlog.Printf(wwlog.VERBOSE, "Removing profile from node %s: %s\n", n.Fqdn.Get(), p)
n.Profiles = util.SliceRemoveElement(n.Profiles, p)
nodeDB.NodeUpdate(n)
}
}
}
for _, g := range groups {
for _, np := range g.Profiles {
if np == p {
numGroups++
wwlog.Printf(wwlog.VERBOSE, "Removing profile from group %s: %s\n", g.Id, p)
g.Profiles = util.SliceRemoveElement(g.Profiles, p)
nodeDB.GroupUpdate(g)
}
}
}
count++
}
if count > 0 {
q := fmt.Sprintf("Are you sure you want to delete %d profile(s) (%d groups, %d nodes)", count, numGroups, numNodes)
prompt := promptui.Prompt{
Label: q,
IsConfirm: true,
}
result, _ := prompt.Run()
if result == "y" || result == "yes" {
nodeDB.Persist()
}
} else {
wwlog.Printf(wwlog.INFO, "No groups found\n")
}
return nil
}

View File

@@ -0,0 +1,20 @@
package delete
import "github.com/spf13/cobra"
var (
baseCmd = &cobra.Command{
Use: "delete",
Short: "Delete profiles",
Long: "Profile configurations ",
RunE: CobraRunE,
}
)
func init() {
}
// GetRootCommand returns the root cobra.Command for the application.
func GetCommand() *cobra.Command {
return baseCmd
}

View File

@@ -0,0 +1,36 @@
package list
import (
"fmt"
"github.com/hpcng/warewulf/internal/pkg/node"
"github.com/hpcng/warewulf/internal/pkg/wwlog"
"github.com/spf13/cobra"
"os"
"reflect"
)
func CobraRunE(cmd *cobra.Command, args []string) error {
nodeDB, err := node.New()
if err != nil {
wwlog.Printf(wwlog.ERROR, "Could not open node configuration: %s\n", err)
os.Exit(1)
}
profiles, err := nodeDB.FindAllProfiles()
if err != nil {
wwlog.Printf(wwlog.ERROR, "Could not find all nodes: %s\n", err)
os.Exit(1)
}
for _, group := range profiles {
v := reflect.ValueOf(group)
typeOfS := v.Type()
fmt.Printf("################################################################################\n")
for i := 0; i< v.NumField(); i++ {
fmt.Printf("%-25s %s = %v\n", group.Id, typeOfS.Field(i).Name, v.Field(i).Interface())
}
}
return nil
}

View File

@@ -0,0 +1,20 @@
package list
import "github.com/spf13/cobra"
var (
baseCmd = &cobra.Command{
Use: "list",
Short: "List profiles",
Long: "Profile configurations ",
RunE: CobraRunE,
}
)
func init() {
}
// GetRootCommand returns the root cobra.Command for the application.
func GetCommand() *cobra.Command {
return baseCmd
}

View File

@@ -0,0 +1,30 @@
package profile
import (
"github.com/hpcng/warewulf/internal/app/wwctl/profile/add"
"github.com/hpcng/warewulf/internal/app/wwctl/profile/delete"
"github.com/hpcng/warewulf/internal/app/wwctl/profile/list"
"github.com/hpcng/warewulf/internal/app/wwctl/profile/set"
"github.com/spf13/cobra"
)
var (
baseCmd = &cobra.Command{
Use: "profile",
Short: "Management of node configuration profiles",
Long: "Warewulf profiles...",
}
test bool
)
func init() {
baseCmd.AddCommand(list.GetCommand())
baseCmd.AddCommand(set.GetCommand())
baseCmd.AddCommand(add.GetCommand())
baseCmd.AddCommand(delete.GetCommand())
}
// GetRootCommand returns the root cobra.Command for the application.
func GetCommand() *cobra.Command {
return baseCmd
}

View File

@@ -0,0 +1,164 @@
package set
import (
"fmt"
"github.com/hpcng/warewulf/internal/pkg/node"
"github.com/hpcng/warewulf/internal/pkg/wwlog"
"github.com/manifoldco/promptui"
"github.com/spf13/cobra"
"os"
)
func CobraRunE(cmd *cobra.Command, args []string) error {
var err error
var profiles []node.ProfileInfo
nodeDB, err := node.New()
if err != nil {
wwlog.Printf(wwlog.ERROR, "Could not open node configuration: %s\n", err)
os.Exit(1)
}
if err != nil {
wwlog.Printf(wwlog.ERROR, "Cloud not get nodeList: %s\n", err)
os.Exit(1)
}
if SetAll == true {
var tmp []node.ProfileInfo
tmp, err = nodeDB.FindAllProfiles()
if err != nil {
wwlog.Printf(wwlog.ERROR, "%s\n", err)
os.Exit(1)
}
for _, p := range tmp {
profiles = append(profiles, p)
}
} else if len(args) > 0 {
var tmp []node.ProfileInfo
tmp, err = nodeDB.FindAllProfiles()
if err != nil {
wwlog.Printf(wwlog.ERROR, "%s\n", err)
os.Exit(1)
}
for _, a := range args {
for _, p := range tmp {
if p.Id == a {
profiles = append(profiles, p)
}
}
}
} else {
cmd.Usage()
os.Exit(1)
}
for _, p := range profiles {
if SetDomainName != "" {
wwlog.Printf(wwlog.VERBOSE, "Profile: %s, Setting domain name to: %s\n", p.Id, SetDomainName)
p.DomainName = SetDomainName
err := nodeDB.ProfileUpdate(p)
if err != nil {
wwlog.Printf(wwlog.ERROR, "%s\n", err)
os.Exit(1)
}
}
if SetVnfs != "" {
wwlog.Printf(wwlog.VERBOSE, "Profile: %s, Setting VNFS to: %s\n", p.Id, SetVnfs)
p.Vnfs = SetVnfs
err := nodeDB.ProfileUpdate(p)
if err != nil {
wwlog.Printf(wwlog.ERROR, "%s\n", err)
os.Exit(1)
}
}
if SetKernel != "" {
wwlog.Printf(wwlog.VERBOSE, "Profile: %s, Setting Kernel version to: %s\n", p.Id, SetKernel)
p.KernelVersion = SetKernel
err := nodeDB.ProfileUpdate(p)
if err != nil {
wwlog.Printf(wwlog.ERROR, "%s\n", err)
os.Exit(1)
}
}
if SetIpxe != "" {
wwlog.Printf(wwlog.VERBOSE, "Profile: %s, Setting iPXE template to: %s\n", p.Id, SetIpxe)
p.Ipxe = SetIpxe
err := nodeDB.ProfileUpdate(p)
if err != nil {
wwlog.Printf(wwlog.ERROR, "%s\n", err)
os.Exit(1)
}
}
if SetRuntimeOverlay != "" {
wwlog.Printf(wwlog.VERBOSE, "Profile: %s, Setting runtime overlay to: %s\n", p.Id, SetRuntimeOverlay)
p.RuntimeOverlay = SetRuntimeOverlay
err := nodeDB.ProfileUpdate(p)
if err != nil {
wwlog.Printf(wwlog.ERROR, "%s\n", err)
os.Exit(1)
}
}
if SetSystemOverlay != "" {
wwlog.Printf(wwlog.VERBOSE, "Profile: %s, Setting system overlay to: %s\n", p.Id, SetSystemOverlay)
p.SystemOverlay = SetSystemOverlay
err := nodeDB.ProfileUpdate(p)
if err != nil {
wwlog.Printf(wwlog.ERROR, "%s\n", err)
os.Exit(1)
}
}
if SetIpmiUsername != "" {
wwlog.Printf(wwlog.VERBOSE, "Profile: %s, Setting IPMI username to: %s\n", p.Id, SetIpmiUsername)
p.IpmiUserName = SetIpmiUsername
err := nodeDB.ProfileUpdate(p)
if err != nil {
wwlog.Printf(wwlog.ERROR, "%s\n", err)
os.Exit(1)
}
}
if SetIpmiPassword != "" {
wwlog.Printf(wwlog.VERBOSE, "Profile: %s, Setting IPMI username to: %s\n", p.Id, SetIpmiPassword)
p.IpmiPassword = SetIpmiPassword
err := nodeDB.ProfileUpdate(p)
if err != nil {
wwlog.Printf(wwlog.ERROR, "%s\n", err)
os.Exit(1)
}
}
}
if len(profiles) > 0 {
q := fmt.Sprintf("Are you sure you want to modify %d profile(s)", len(profiles))
prompt := promptui.Prompt{
Label: q,
IsConfirm: true,
}
result, _ := prompt.Run()
if result == "y" || result == "yes" {
nodeDB.Persist()
}
} else {
fmt.Printf("No profiles found\n")
}
return nil
}

View File

@@ -0,0 +1,40 @@
package set
import "github.com/spf13/cobra"
var (
baseCmd = &cobra.Command{
Use: "set",
Short: "Set profile configurations",
Long: "Profile configurations ",
RunE: CobraRunE,
}
SetAll bool
SetVnfs string
SetKernel string
SetDomainName string
SetIpxe string
SetRuntimeOverlay string
SetSystemOverlay string
SetIpmiUsername string
SetIpmiPassword string
)
func init() {
baseCmd.PersistentFlags().StringVarP(&SetVnfs, "vnfs", "V", "", "Set node Virtual Node File System (VNFS)")
baseCmd.PersistentFlags().StringVarP(&SetKernel, "kernel", "K", "", "Set Kernel version for nodes")
baseCmd.PersistentFlags().StringVarP(&SetDomainName, "domain", "D", "", "Set the node's domain name")
baseCmd.PersistentFlags().StringVarP(&SetIpxe, "ipxe", "P", "", "Set the node's iPXE template name")
baseCmd.PersistentFlags().StringVarP(&SetRuntimeOverlay, "runtime", "R", "", "Set the node's runtime overlay")
baseCmd.PersistentFlags().StringVarP(&SetSystemOverlay, "system", "S", "", "Set the node's system overlay")
baseCmd.PersistentFlags().StringVar(&SetIpmiUsername, "ipmiuser", "", "Set the node's IPMI username")
baseCmd.PersistentFlags().StringVar(&SetIpmiPassword, "ipmipass", "", "Set the node's IPMI password")
baseCmd.PersistentFlags().BoolVarP(&SetAll, "all", "a", false, "Set all profiles")
}
// GetRootCommand returns the root cobra.Command for the application.
func GetCommand() *cobra.Command {
return baseCmd
}

View File

@@ -1,37 +1,44 @@
package wwctl
import (
"github.com/hpcng/warewulf/internal/app/wwctl/build"
"github.com/hpcng/warewulf/internal/app/wwctl/controller"
"github.com/hpcng/warewulf/internal/app/wwctl/group"
"github.com/hpcng/warewulf/internal/app/wwctl/kernel"
"github.com/hpcng/warewulf/internal/app/wwctl/node"
"github.com/hpcng/warewulf/internal/app/wwctl/overlay"
"github.com/hpcng/warewulf/internal/app/wwctl/profile"
"github.com/hpcng/warewulf/internal/app/wwctl/services"
"github.com/hpcng/warewulf/internal/app/wwctl/vnfs"
"github.com/hpcng/warewulf/internal/pkg/wwlog"
"github.com/spf13/cobra"
)
var (
rootCmd = &cobra.Command{
Use: "wwctl",
Short: "Warewulf Control",
Long: "Control interface to the Cluster Warewulf Provisioning System.",
PersistentPreRunE: rootPersistentPreRunE,
Use: "wwctl",
Short: "Warewulf Control",
Long: "Control interface to the Cluster Warewulf Provisioning System.",
PersistentPreRunE: rootPersistentPreRunE,
}
verboseArg bool
debugArg bool
debugArg bool
)
func init() {
rootCmd.PersistentFlags().BoolVarP(&verboseArg, "verbose", "v", false, "Run with increased verbosity.")
rootCmd.PersistentFlags().BoolVarP(&debugArg, "debug", "d", false, "Run with debugging messages enabled.")
rootCmd.AddCommand(build.GetCommand())
//rootCmd.AddCommand(build.GetCommand())
rootCmd.AddCommand(overlay.GetCommand())
rootCmd.AddCommand(controller.GetCommand())
rootCmd.AddCommand(vnfs.GetCommand())
rootCmd.AddCommand(node.GetCommand())
rootCmd.AddCommand(kernel.GetCommand())
rootCmd.AddCommand(group.GetCommand())
rootCmd.AddCommand(profile.GetCommand())
rootCmd.AddCommand(services.GetCommand())
}
@@ -49,4 +56,4 @@ func rootPersistentPreRunE(cmd *cobra.Command, args []string) error {
wwlog.SetLevel(wwlog.INFO)
}
return nil
}
}

View File

@@ -0,0 +1,109 @@
package dhcp
import (
"fmt"
"github.com/hpcng/warewulf/internal/pkg/node"
"github.com/hpcng/warewulf/internal/pkg/wwlog"
"github.com/spf13/cobra"
"net"
"os"
"text/template"
)
type dhcpTemplate struct {
Ipaddr string
RangeStart string
RangeEnd string
Netmask string
Nodes []node.NodeInfo
}
func CobraRunE(cmd *cobra.Command, args []string) error {
nodeDB, err := node.New()
if err != nil {
wwlog.Printf(wwlog.ERROR, "Could not open node configuration: %s\n", err)
os.Exit(1)
}
controllers, err := nodeDB.FindAllControllers()
if err != nil {
wwlog.Printf(wwlog.ERROR, "Could not find all controllers: %s\n", err)
os.Exit(1)
}
for _, controller := range controllers {
var d dhcpTemplate
var configured bool
addrs, err := net.InterfaceAddrs()
if err != nil {
wwlog.Printf(wwlog.ERROR, "Could not get network interfaces: %s\n", err)
os.Exit(1)
}
for _, address := range addrs {
if ipnet, ok := address.(*net.IPNet); ok && !ipnet.IP.IsLoopback() {
if ipnet.IP.String() == controller.Ipaddr {
mask := ipnet.IP.DefaultMask()
d.Ipaddr = ipnet.IP.String()
d.Netmask = fmt.Sprintf("%d.%d.%d.%d", mask[0], mask[1], mask[2], mask[3])
d.RangeStart = controller.Services.Dhcp.RangeStart
d.RangeEnd = controller.Services.Dhcp.RangeEnd
configured = true
fmt.Printf("%#v\n", d)
break
}
}
}
if configured == false {
wwlog.Printf(wwlog.ERROR, "Could not identify this system in the Warewulf configuration by it's IP address\n")
os.Exit(1)
}
if controller.Services.Dhcp.ConfigFile == "" {
wwlog.Printf(wwlog.ERROR, "Could not locate the DHCP configuration file for this controller\n")
os.Exit(1)
}
if _, ok := nodeDB.Controllers[controller.Id]; !ok {
wwlog.Printf(wwlog.ERROR, "We should never get here, but since we did, Hello! %s\n", err)
os.Exit(1)
}
nodes, err := nodeDB.FindAllNodes()
if err != nil {
wwlog.Printf(wwlog.ERROR, "Could not find all controllers: %s\n", err)
os.Exit(1)
}
for _, node := range nodes {
d.Nodes = append(d.Nodes, node)
}
tmpl, err := template.New("default-dhcpd.conf").ParseFiles("/etc/warewulf/dhcp/default-dhcpd.conf")
if err != nil {
wwlog.Printf(wwlog.ERROR, "%s\n", err)
os.Exit(1)
}
// w, err := os.OpenFile(controller.Services.Dhcp.ConfigFile, os.O_RDWR|os.O_CREATE, 0640)
// if err != nil {
// wwlog.Printf(wwlog.ERROR, "%s\n", err)
// os.Exit(1)
// }
// defer w.Close()
err = tmpl.Execute(os.Stdout, d)
if err != nil {
wwlog.Printf(wwlog.ERROR, "%s\n", err)
os.Exit(1)
}
// Just in case we get here, we've now finished the loop
break
}
return nil
}

View File

@@ -0,0 +1,23 @@
package dhcp
import (
"github.com/spf13/cobra"
)
var (
baseCmd = &cobra.Command{
Use: "dhcp",
Short: "DHCP configuration",
Long: "DHCP Config",
RunE: CobraRunE,
}
test bool
)
func init() {
}
// GetRootCommand returns the root cobra.Command for the application.
func GetCommand() *cobra.Command {
return baseCmd
}

View File

@@ -0,0 +1,23 @@
package services
import (
"github.com/hpcng/warewulf/internal/app/wwctl/services/dhcp"
"github.com/spf13/cobra"
)
var (
baseCmd = &cobra.Command{
Use: "services",
Short: "Initialize Warewulf services",
Long: "Warewulf Initialization",
}
)
func init() {
baseCmd.AddCommand(dhcp.GetCommand())
}
// GetRootCommand returns the root cobra.Command for the application.
func GetCommand() *cobra.Command {
return baseCmd
}

View File

@@ -28,7 +28,9 @@ func CobraRunE(cmd *cobra.Command, args []string) error {
}
for _, node := range nodes {
set[node.Vnfs] ++
if node.Vnfs.Defined() == true {
set[node.Vnfs.Get()] ++
}
}
} else if BuildAll == true {
@@ -40,7 +42,9 @@ func CobraRunE(cmd *cobra.Command, args []string) error {
}
for _, node := range nodes {
set[node.Vnfs] ++
if node.Vnfs.Defined() == true {
set[node.Vnfs.Get()] ++
}
}
} else if len(args) == 1 {

View File

@@ -3,25 +3,62 @@ package list
import (
"fmt"
"github.com/hpcng/warewulf/internal/pkg/config"
"github.com/hpcng/warewulf/internal/pkg/wwlog"
"github.com/hpcng/warewulf/internal/pkg/node"
"github.com/hpcng/warewulf/internal/pkg/util"
"github.com/hpcng/warewulf/internal/pkg/vnfs"
"github.com/spf13/cobra"
"io/ioutil"
"os"
"path"
"strings"
)
func CobraRunE(cmd *cobra.Command, args []string) error {
config := config.New()
nconfig, _ := node.New()
nodes, _ := nconfig.FindAllNodes()
nodemap := make(map[string]int)
files, err := ioutil.ReadDir(config.VnfsImageParentDir())
if err != nil {
wwlog.Printf(wwlog.ERROR, "%s\n", err)
os.Exit(1)
for _, n := range nodes {
nodemap[n.Vnfs.Get()] ++
}
for _, f := range files {
fmt.Println(f.Name())
}
images, _ := ioutil.ReadDir(config.VnfsImageParentDir())
fmt.Printf("VNFS LIST: work in progress: %s\n", config.VnfsImageParentDir())
fmt.Printf("%-38s %-16s %s\n", "VNFS Name", "VNFS SIZE(k)", "NODES")
fmt.Println(strings.Repeat("=", 80))
for _, file := range images {
v, err := vnfs.Load(file.Name())
if err == nil {
var vnfs_size int64
if util.IsFile( config.VnfsImage(file.Name())) {
s, _ := os.Stat(config.VnfsImage(file.Name()))
vnfs_size = s.Size() / 1024
}
if nodemap[v.Source] > 0 {
fmt.Printf("%-38s %-16d %d\n", v.Source, vnfs_size, nodemap[v.Source])
} else {
fmt.Printf("%-38s %-16d %d\n", v.Source, vnfs_size, 0)
}
}
continue
if util.IsDir(path.Join(config.VnfsImageParentDir(), file.Name())) {
var vnfs_size int64
if util.IsFile( config.VnfsImage(file.Name())) {
s, _ := os.Stat(config.VnfsImage(file.Name()))
vnfs_size = s.Size() / 1024
}
if nodemap[file.Name()] > 0 {
fmt.Printf("%-38s %-16d %d\n", file.Name(), vnfs_size, nodemap[file.Name()])
} else {
fmt.Printf("%-38s %-16d %d\n", file.Name(), vnfs_size, 0)
}
}
}
return nil
}

View File

@@ -14,8 +14,8 @@ var (
)
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)")
//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)")
}

View File

@@ -92,6 +92,10 @@ func (self *Config) VnfsChrootParentDir() string {
return fmt.Sprintf("%s/chroot/", self.LocalStateDir)
}
func (self *Config) KernelParentDir() string {
return fmt.Sprintf("%s/provision/kernel/", self.LocalStateDir)
}
func (self *Config) SystemOverlaySource(overlayName string) string {
if overlayName == "" {
wwlog.Printf(wwlog.ERROR, "System overlay name is not defined\n")
@@ -132,7 +136,7 @@ func (self *Config) KernelImage(kernelVersion string) string {
return ""
}
return fmt.Sprintf("%s/provision/kernel/vmlinuz-%s", self.LocalStateDir, kernelVersion)
return path.Join(self.KernelParentDir(), kernelVersion, "vmlinuz")
}
func (self *Config) KmodsImage(kernelVersion string) string {
@@ -146,7 +150,7 @@ func (self *Config) KmodsImage(kernelVersion string) string {
return ""
}
return fmt.Sprintf("%s/provision/kernel/kmods-%s.img", self.LocalStateDir, kernelVersion)
return path.Join(self.KernelParentDir(), kernelVersion, "kmods.img")
}
func (self *Config) SystemOverlayImage(nodeName string) string {
@@ -177,32 +181,34 @@ func (self *Config) RuntimeOverlayImage(nodeName string) string {
return fmt.Sprintf("%s/provision/overlays/runtime/%s.img", self.LocalStateDir, nodeName)
}
func (self *Config) VnfsImageDir(uri string) string {
if uri == "" {
wwlog.Printf(wwlog.ERROR, "VNFS URI is not defined\n")
return ""
}
func (self *Config) VnfsImage(vnfsNameClean string) string {
if vnfsNameClean == "" {
if util.TaintCheck(uri, "^[a-zA-Z0-9-._:]+$") == false {
wwlog.Printf(wwlog.ERROR, "VNFS name contains illegal characters: %s\n", uri)
return ""
}
return path.Join(self.VnfsImageParentDir(), uri)
}
func (self *Config) VnfsImage(uri string) string {
return path.Join(self.VnfsImageDir(uri), "image")
}
func (self *Config) VnfsChroot(uri string) string {
if uri == "" {
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)
if util.TaintCheck(uri, "^[a-zA-Z0-9-._:]+$") == false {
wwlog.Printf(wwlog.ERROR, "VNFS name contains illegal characters: %s\n", uri)
return ""
}
return path.Join(self.VnfsImageParentDir(), vnfsNameClean)
return path.Join(self.VnfsChrootParentDir(), uri)
}
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)
return ""
}
return path.Join(self.VnfsChrootParentDir(), vnfsNameClean)
}

View File

@@ -32,29 +32,20 @@ func Build(kernelVersion string) error {
}
if _, err := os.Stat(kernelImage); err == nil {
if util.PathIsNewer(kernelImage, kernelDestination) {
wwlog.Printf(wwlog.INFO, "%-45s: Skipping, kernel is current\n", "vmlinuz-"+kernelVersion)
} else {
err := util.CopyFile(kernelImage, kernelDestination)
if err != nil {
return err
}
wwlog.Printf(wwlog.INFO, "%-45s: Done\n", "vmlinuz-"+kernelVersion)
err := util.CopyFile(kernelImage, kernelDestination)
if err != nil {
return err
}
wwlog.Printf(wwlog.INFO, "%-45s: Done\n", "vmlinuz-"+kernelVersion)
}
if _, err := os.Stat(kernelDrivers); err == nil {
if util.PathIsNewer(kernelDrivers, driversDestination) {
wwlog.Printf(wwlog.INFO, "%-45s: Skipping, drivers are current\n", "kmods-"+kernelVersion+".img")
} else {
cmd := fmt.Sprintf("cd /; find .%s | cpio --quiet -o -H newc -F \"%s\"", kernelDrivers, driversDestination)
err := exec.Command("/bin/sh", "-c", cmd).Run()
if err != nil {
return err
}
wwlog.Printf(wwlog.INFO, "%-45s: Done\n", "kmods-"+kernelVersion+".img")
cmd := fmt.Sprintf("cd /; find .%s | cpio --quiet -o -H newc -F \"%s\"", kernelDrivers, driversDestination)
err := exec.Command("/bin/sh", "-c", cmd).Run()
if err != nil {
return err
}
wwlog.Printf(wwlog.INFO, "%-45s: Done\n", "kmods-"+kernelVersion+".img")
}
return nil

View File

@@ -0,0 +1,277 @@
package node
import (
"fmt"
"github.com/hpcng/warewulf/internal/pkg/errors"
"github.com/hpcng/warewulf/internal/pkg/wwlog"
"gopkg.in/yaml.v2"
"io/ioutil"
"regexp"
)
func New() (nodeYaml, error) {
var ret nodeYaml
wwlog.Printf(wwlog.DEBUG, "Opening node configuration file: %s\n", ConfigFile)
data, err := ioutil.ReadFile(ConfigFile)
if err != nil {
fmt.Printf("error reading node configuration file\n")
return ret, err
}
err = yaml.Unmarshal(data, &ret)
if err != nil {
return ret, err
}
return ret, nil
}
func (self *nodeYaml) FindAllNodes() ([]NodeInfo, error) {
var ret []NodeInfo
for controllername, controller := range self.Controllers {
for groupname, group := range controller.NodeGroups {
for nodename, node := range group.Nodes {
var n NodeInfo
var allProfiles []string
if node.Disabled == true || group.Disabled == true {
wwlog.Printf(wwlog.VERBOSE, "Skipping disabled node: %s/%s\n", groupname, nodename)
continue
}
n.Id.Set(nodename)
n.Gid.Set(groupname)
n.Cid.Set(controllername)
n.HostName.Set(node.Hostname)
n.IpmiIpaddr.Set(node.IpmiIpaddr)
n.DomainName.Set(node.DomainName)
n.Vnfs.Set(node.Vnfs)
n.KernelVersion.Set(node.KernelVersion)
n.KernelArgs.Set(node.KernelArgs)
n.Ipxe.Set(node.Ipxe)
n.IpmiUserName.Set(node.IpmiUserName)
n.IpmiPassword.Set(node.IpmiPassword)
n.SystemOverlay.Set(node.SystemOverlay)
n.RuntimeOverlay.Set(node.RuntimeOverlay)
n.DomainName.SetGroup(group.DomainName)
n.Vnfs.SetGroup(group.Vnfs)
n.KernelVersion.SetGroup(group.KernelVersion)
n.KernelArgs.SetGroup(group.KernelArgs)
n.Ipxe.SetGroup(group.Ipxe)
n.IpmiUserName.SetGroup(group.IpmiUserName)
n.IpmiPassword.SetGroup(group.IpmiPassword)
n.SystemOverlay.SetGroup(group.SystemOverlay)
n.RuntimeOverlay.SetGroup(group.RuntimeOverlay)
n.RuntimeOverlay.SetDefault("default")
n.SystemOverlay.SetDefault("default")
n.Ipxe.SetDefault("default")
n.KernelArgs.SetDefault("crashkernel=no quiet")
n.GroupProfiles = group.Profiles
n.Profiles = node.Profiles
allProfiles = append(allProfiles, group.Profiles...)
allProfiles = append(allProfiles, node.Profiles...)
for _, p := range allProfiles {
if _, ok := self.NodeProfiles[p]; !ok {
wwlog.Printf(wwlog.WARN, "Profile not found for node '%s': %s\n", nodename, p)
continue
}
n.DomainName.SetProfile(self.NodeProfiles[p].DomainName)
n.Vnfs.SetProfile(self.NodeProfiles[p].Vnfs)
n.KernelVersion.SetProfile(self.NodeProfiles[p].KernelVersion)
n.KernelArgs.SetProfile(self.NodeProfiles[p].KernelArgs)
n.Ipxe.SetProfile(self.NodeProfiles[p].Ipxe)
n.IpmiUserName.SetProfile(self.NodeProfiles[p].IpmiUserName)
n.IpmiPassword.SetProfile(self.NodeProfiles[p].IpmiPassword)
n.SystemOverlay.SetProfile(self.NodeProfiles[p].SystemOverlay)
n.RuntimeOverlay.SetProfile(self.NodeProfiles[p].RuntimeOverlay)
}
if n.DomainName.Defined() == true {
n.Fqdn.Set(node.Hostname + "." + n.DomainName.Get())
} else {
n.Fqdn.Set(node.Hostname)
}
n.NetDevs = node.NetDevs
ret = append(ret, n)
}
}
}
return ret, nil
}
func (self *nodeYaml) FindAllGroups() ([]GroupInfo, error) {
var ret []GroupInfo
for controllername, controller := range self.Controllers {
for groupname, group := range controller.NodeGroups {
var g GroupInfo
g.Id = groupname
g.Cid = controllername
g.DomainName = group.DomainName
g.Comment = group.Comment
g.Vnfs = group.Vnfs
g.KernelVersion = group.KernelVersion
g.KernelArgs = group.KernelArgs
g.IpmiPassword = group.IpmiPassword
g.IpmiUserName = group.IpmiUserName
g.SystemOverlay = group.SystemOverlay
g.RuntimeOverlay = group.RuntimeOverlay
g.Profiles = group.Profiles
// TODO: Validate or die on all inputs
ret = append(ret, g)
}
}
return ret, nil
}
func (self *nodeYaml) FindAllControllers() ([]ControllerInfo, error) {
var ret []ControllerInfo
for controllername, controller := range self.Controllers {
var c ControllerInfo
c.Id = controllername
c.Ipaddr = controller.Ipaddr
c.Services = struct {
Warewulfd struct {
Port string
Secure string
StartCmd string
RestartCmd string
EnableCmd string
}
Dhcp struct {
Enabled bool
RangeStart string
RangeEnd string
ConfigFile string
StartCmd string
RestartCmd string
EnableCmd string
}
Tftp struct {
Enabled bool
TftpRoot string
StartCmd string
RestartCmd string
EnableCmd string
}
Nfs struct {
Enabled bool
Exports []string
StartCmd string
RestartCmd string
EnableCmd string
}
}(controller.Services)
// TODO: Validate or die on all inputs
ret = append(ret, c)
}
return ret, nil
}
func (self *nodeYaml) FindAllProfiles() ([]ProfileInfo, error) {
var ret []ProfileInfo
for name, profile := range self.NodeProfiles {
var p ProfileInfo
p.Id = name
p.Comment = profile.Comment
p.Vnfs = profile.Vnfs
p.Ipxe = profile.Ipxe
p.KernelVersion = profile.KernelVersion
p.KernelArgs = profile.KernelArgs
p.IpmiUserName = profile.IpmiUserName
p.IpmiPassword = profile.IpmiPassword
p.DomainName = profile.DomainName
p.RuntimeOverlay = profile.RuntimeOverlay
p.SystemOverlay = profile.SystemOverlay
// TODO: Validate or die on all inputs
ret = append(ret, p)
}
return ret, nil
}
func (self *nodeYaml) FindByHwaddr(hwa string) (NodeInfo, error) {
var ret NodeInfo
n, _ := self.FindAllNodes()
for _, node := range n {
for _, dev := range node.NetDevs {
if dev.Hwaddr == hwa {
return node, nil
}
}
}
return ret, errors.New("No nodes found with HW Addr: " + hwa)
}
func (self *nodeYaml) FindByIpaddr(ipaddr string) (NodeInfo, error) {
var ret NodeInfo
n, _ := self.FindAllNodes()
for _, node := range n {
for _, dev := range node.NetDevs {
if dev.Ipaddr == ipaddr {
return node, nil
}
}
}
return ret, errors.New("No nodes found with IP Addr: " + ipaddr)
}
func (nodes *nodeYaml) SearchByName(search string) ([]NodeInfo, error) {
var ret []NodeInfo
n, _ := nodes.FindAllNodes()
for _, node := range n {
b, _ := regexp.MatchString(search, node.Fqdn.Get())
if b == true {
ret = append(ret, node)
}
}
return ret, nil
}
func (nodes *nodeYaml) SearchByNameList(searchList []string) ([]NodeInfo, error) {
var ret []NodeInfo
n, _ := nodes.FindAllNodes()
for _, search := range searchList {
for _, node := range n {
b, _ := regexp.MatchString(search, node.Fqdn.Get())
if b == true {
ret = append(ret, node)
}
}
}
return ret, nil
}

View File

@@ -0,0 +1,223 @@
package node
import (
"github.com/hpcng/warewulf/internal/pkg/util"
"github.com/hpcng/warewulf/internal/pkg/wwlog"
"os"
)
/******
* YAML data representations
******/
type nodeYaml struct {
NodeProfiles map[string]*ProfileConf
Controllers map[string]*ControllerConf `yaml:"control"`
}
type ProfileConf struct {
Comment string `yaml:"comment"`
Vnfs string `yaml:"vnfs,omitempty"`
Ipxe string `yaml:"ipxe template,omitempty"`
KernelVersion string `yaml:"kernel version,omitempty"`
KernelArgs string `yaml:"kernel args,omitempty"`
IpmiUserName string `yaml:"ipmi username,omitempty"`
IpmiPassword string `yaml:"ipmi password,omitempty"`
DomainName string `yaml:"domain name,omitempty"`
RuntimeOverlay string `yaml:"runtime overlay files,omitempty"`
SystemOverlay string `yaml:"system overlay files,omitempty"`
}
type ControllerConf struct {
Comment string `yaml:"comment"`
Ipaddr string `yaml:"ipaddr"`
Services struct {
Warewulfd struct {
Port string `yaml:"port"`
Secure string `yaml:"secure,omitempty"`
StartCmd string `yaml:"start command,omitempty"`
RestartCmd string `yaml:"restart command,omitempty"`
EnableCmd string `yaml:"enable command,omitempty"`
} `yaml:"warewulf"`
Dhcp struct {
Enabled bool `yaml:"enabled,omitempty"`
RangeStart string `yaml:"range start,omitempty"`
RangeEnd string `yaml:"range end,omitempty"`
ConfigFile string `yaml:"config file,omitempty"`
StartCmd string `yaml:"start command,omitempty"`
RestartCmd string `yaml:"restart command,omitempty"`
EnableCmd string `yaml:"enable command,omitempty"`
} `yaml:"dhcp,omitempty"`
Tftp struct {
Enabled bool `yaml:"enabled,omitempty"`
TftpRoot string `yaml:"tftp root,omitempty"`
StartCmd string `yaml:"start command,omitempty"`
RestartCmd string `yaml:"restart command,omitempty"`
EnableCmd string `yaml:"enable command,omitempty"`
} `yaml:"tftp,omitempty"`
Nfs struct {
Enabled bool `yaml:"enabled,omitempty"`
Exports []string `yaml:"exports,omitempty"`
StartCmd string `yaml:"start command,omitempty"`
RestartCmd string `yaml:"restart command,omitempty"`
EnableCmd string `yaml:"enable command,omitempty"`
} `yaml:"nfs,omitempty"`
} `yaml:"services"`
NodeGroups map[string]*GroupConf
}
type GroupConf struct {
Comment string `yaml:"comment"`
Disabled bool `yaml:"disabled,omitempty"`
DomainName string `yaml:"domain name"`
Vnfs string `yaml:"vnfs,omitempty"`
Ipxe string `yaml:"ipxe template,omitempty"`
KernelVersion string `yaml:"kernel version,omitempty"`
KernelArgs string `yaml:"kernel args,omitempty"`
IpmiUserName string `yaml:"ipmi username,omitempty"`
IpmiPassword string `yaml:"ipmi password,omitempty"`
RuntimeOverlay string `yaml:"runtime overlay files,omitempty"`
SystemOverlay string `yaml:"system overlay files,omitempty"`
Profiles []string `yaml:"profiles,omitempty"`
Nodes map[string]*NodeConf
}
type NodeConf struct {
Comment string `yaml:"comment,omitempty"`
Disabled bool `yaml:"disabled,omitempty"`
Hostname string `yaml:"hostname,omitempty"`
DomainName string `yaml:"domain name,omitempty"`
Vnfs string `yaml:"vnfs,omitempty"`
Ipxe string `yaml:"ipxe template,omitempty"`
KernelVersion string `yaml:"kernel version,omitempty"`
KernelArgs string `yaml:"kernel args,omitempty"`
IpmiUserName string `yaml:"ipmi username,omitempty"`
IpmiPassword string `yaml:"ipmi password,omitempty"`
IpmiIpaddr string `yaml:"ipmi ipaddr,omitempty"`
RuntimeOverlay string `yaml:"runtime overlay files,omitempty"`
SystemOverlay string `yaml:"system overlay files,omitempty"`
Profiles []string `yaml:"profiles,omitempty"`
NetDevs map[string]*NetDevs
}
type NetDevs struct {
Type string `yaml:"type,omitempty"`
Hwaddr string
Ipaddr string
Netmask string
Gateway string `yaml:"gateway,omitempty"`
}
/******
* Code internal data representations
******/
type NodeInfoEntry struct {
value string
profile string
group string
controller string
def string
}
type NodeInfo struct {
Id NodeInfoEntry
Gid NodeInfoEntry
Cid NodeInfoEntry
Comment NodeInfoEntry
HostName NodeInfoEntry
Fqdn NodeInfoEntry
DomainName NodeInfoEntry
Vnfs NodeInfoEntry
Ipxe NodeInfoEntry
KernelVersion NodeInfoEntry
KernelArgs NodeInfoEntry
IpmiIpaddr NodeInfoEntry
IpmiUserName NodeInfoEntry
IpmiPassword NodeInfoEntry
RuntimeOverlay NodeInfoEntry
SystemOverlay NodeInfoEntry
Profiles []string
GroupProfiles []string
NetDevs map[string]*NetDevs
}
type ControllerInfo struct {
Id string
Comment string
Ipaddr string
Fqdn string
DomainName string
Services struct {
Warewulfd struct {
Port string
Secure string
StartCmd string
RestartCmd string
EnableCmd string
}
Dhcp struct {
Enabled bool
RangeStart string
RangeEnd string
ConfigFile string
StartCmd string
RestartCmd string
EnableCmd string
}
Tftp struct {
Enabled bool
TftpRoot string
StartCmd string
RestartCmd string
EnableCmd string
}
Nfs struct {
Enabled bool
Exports []string
StartCmd string
RestartCmd string
EnableCmd string
}
}
}
type GroupInfo struct {
Id string
Cid string
Comment string
Vnfs string
Ipxe string
KernelVersion string
KernelArgs string
IpmiUserName string
IpmiPassword string
DomainName string
RuntimeOverlay string
SystemOverlay string
Profiles []string
}
type ProfileInfo struct {
Id string
Comment string
Vnfs string
Ipxe string
KernelVersion string
KernelArgs string
IpmiUserName string
IpmiPassword string
DomainName string
RuntimeOverlay string
SystemOverlay string
}
const ConfigFile = "/etc/warewulf/nodes.conf"
func init() {
//TODO: Check to make sure nodes.conf is found
if util.IsFile(ConfigFile) == false {
wwlog.Printf(wwlog.ERROR, "Configuration file not found: %s\n", ConfigFile)
os.Exit(1)
}
}

View File

@@ -0,0 +1,115 @@
package node
import (
"strings"
)
func (self *NodeInfoEntry) String() string {
if self.value != "" {
return self.value
}
if self.group != "" {
return self.group
}
if self.profile != "" {
return self.profile
}
if self.controller != "" {
return self.controller
}
if self.def != "" {
return self.def
}
return "--"
}
func (self *NodeInfoEntry) Source() string {
if self.value != "" {
return "node"
}
if self.group != "" {
return "group"
}
if self.profile != "" {
return "profile"
}
if self.controller != "" {
return "controller"
}
if self.def != "" {
return "default"
}
return ""
}
func (self *NodeInfoEntry) Get() string {
if self.value != "" {
return self.value
}
if self.group != "" {
return self.group
}
if self.profile != "" {
return self.profile
}
if self.controller != "" {
return self.controller
}
if self.def != "" {
return self.def
}
return ""
}
func (self *NodeInfoEntry) Defined() bool {
if self.Get() == "" {
return false
}
return true
}
func (self *NodeInfoEntry) SetDefault(value string) {
if value == "" {
return
}
self.def = value
}
func (self *NodeInfoEntry) SetGroup(value string) {
if value == "" {
return
}
self.group = value
}
func (self *NodeInfoEntry) SetProfile(value string) {
if value == "" {
return
}
self.profile = value
}
func (self *NodeInfoEntry) SetController(value string) {
if value == "" {
return
}
self.controller = value
}
func (self *NodeInfoEntry) Set(value string) {
if value == "" {
return
} else if strings.ToUpper(value) == "UNDEF" {
value = ""
}
self.value = value
}
func (self *NodeInfoEntry) Unset() {
self.value = ""
}
func (self *NodeInfoEntry) GetReal() string {
return self.value
}

View File

@@ -0,0 +1,323 @@
package node
import (
"github.com/hpcng/warewulf/internal/pkg/errors"
"github.com/hpcng/warewulf/internal/pkg/wwlog"
"gopkg.in/yaml.v2"
"os"
)
/****
*
* NODE MODIFIERS
*
****/
func (self *nodeYaml) AddNode(controllerID string, groupID string, nodeID string) error {
var node NodeConf
wwlog.Printf(wwlog.VERBOSE, "Adding new node: %s/%s\n", groupID, nodeID)
if _, ok := self.Controllers[controllerID]; ! ok {
return errors.New("Controller does not exist: " + controllerID)
}
if _, ok := self.Controllers[controllerID].NodeGroups[groupID]; ! ok {
return errors.New("Group does not exist: " + groupID)
}
if _, ok := self.Controllers[controllerID].NodeGroups[groupID].Nodes[groupID]; ok {
return errors.New("Nodename already exists in group: " + nodeID)
}
self.Controllers[controllerID].NodeGroups[groupID].Nodes[nodeID] = &node
self.Controllers[controllerID].NodeGroups[groupID].Nodes[nodeID].Hostname = nodeID
return nil
}
func (self *nodeYaml) DelNode(controllerID string, groupID string, nodeID string) error {
if _, ok := self.Controllers[controllerID]; ! ok {
return errors.New("Controller does not exist: " + controllerID)
}
if _, ok := self.Controllers[controllerID].NodeGroups[groupID]; ! ok {
return errors.New("Group does not exist: " + groupID)
}
if _, ok := self.Controllers[controllerID].NodeGroups[groupID].Nodes[groupID]; ok {
return errors.New("Nodename does not exist in group: " + nodeID)
}
wwlog.Printf(wwlog.VERBOSE, "Deleting node network device: %s/%s\n", groupID, nodeID)
delete(self.Controllers[controllerID].NodeGroups[groupID].Nodes, nodeID)
return nil
}
func(self *nodeYaml) NodeUpdate(node NodeInfo) error {
controllerID := node.Cid.Get()
groupID := node.Gid.Get()
nodeID := node.Id.Get()
if _, ok := self.Controllers[controllerID]; ! ok {
return errors.New("Controller does not exist: " + controllerID)
}
if _, ok := self.Controllers[controllerID].NodeGroups[groupID]; ! ok {
return errors.New("Group does not exist: " + groupID)
}
if _, ok := self.Controllers[controllerID].NodeGroups[groupID].Nodes[groupID]; ! ok {
return errors.New("Nodename does not exist in group: " + nodeID)
}
self.Controllers[controllerID].NodeGroups[groupID].Nodes[nodeID].Hostname = node.HostName.GetReal()
self.Controllers[controllerID].NodeGroups[groupID].Nodes[nodeID].Vnfs = node.Vnfs.GetReal()
self.Controllers[controllerID].NodeGroups[groupID].Nodes[nodeID].DomainName = node.DomainName.GetReal()
self.Controllers[controllerID].NodeGroups[groupID].Nodes[nodeID].Ipxe = node.Ipxe.GetReal()
self.Controllers[controllerID].NodeGroups[groupID].Nodes[nodeID].KernelVersion = node.KernelVersion.GetReal()
self.Controllers[controllerID].NodeGroups[groupID].Nodes[nodeID].KernelArgs = node.KernelArgs.GetReal()
self.Controllers[controllerID].NodeGroups[groupID].Nodes[nodeID].IpmiIpaddr = node.IpmiIpaddr.GetReal()
self.Controllers[controllerID].NodeGroups[groupID].Nodes[nodeID].IpmiUserName = node.IpmiUserName.GetReal()
self.Controllers[controllerID].NodeGroups[groupID].Nodes[nodeID].IpmiPassword = node.IpmiPassword.GetReal()
self.Controllers[controllerID].NodeGroups[groupID].Nodes[nodeID].RuntimeOverlay = node.RuntimeOverlay.GetReal()
self.Controllers[controllerID].NodeGroups[groupID].Nodes[nodeID].SystemOverlay = node.SystemOverlay.GetReal()
self.Controllers[controllerID].NodeGroups[groupID].Nodes[nodeID].Profiles = node.Profiles
self.Controllers[controllerID].NodeGroups[groupID].Nodes[nodeID].NetDevs = node.NetDevs
return nil
}
/****
*
* GROUP MODIFIERS
*
****/
func (self *nodeYaml) AddGroup(controllerID string, groupID string) error {
var group GroupConf
wwlog.Printf(wwlog.VERBOSE, "Adding new group: %s/%s\n", groupID)
if _, ok := self.Controllers[controllerID]; ! ok {
return errors.New("Controller does not exist: " + controllerID)
}
if _, ok := self.Controllers[controllerID].NodeGroups[groupID]; ok {
return errors.New("Group already exists: " + groupID)
}
self.Controllers[controllerID].NodeGroups[groupID] = &group
self.Controllers[controllerID].NodeGroups[groupID].DomainName = groupID
self.Controllers[controllerID].NodeGroups[groupID].Profiles = []string{"default"}
return nil
}
func (self *nodeYaml) DelGroup(controllerID string, groupID string) error {
if _, ok := self.Controllers[controllerID]; ! ok {
return errors.New("Controller does not exist: " + controllerID)
}
if _, ok := self.Controllers[controllerID].NodeGroups[groupID]; ! ok {
return errors.New("Group does not exist: " + groupID)
}
wwlog.Printf(wwlog.VERBOSE, "Deleting group: %s\n", groupID)
delete(self.Controllers[controllerID].NodeGroups, groupID)
return nil
}
func(self *nodeYaml) GroupUpdate(group GroupInfo) error {
controllerID := group.Cid
groupID := group.Id
if _, ok := self.Controllers[controllerID]; ! ok {
return errors.New("Controller does not exist: " + controllerID)
}
if _, ok := self.Controllers[controllerID].NodeGroups[groupID]; ! ok {
return errors.New("Group does not exist: " + groupID)
}
self.Controllers[controllerID].NodeGroups[groupID].DomainName = group.DomainName
self.Controllers[controllerID].NodeGroups[groupID].Vnfs = group.Vnfs
self.Controllers[controllerID].NodeGroups[groupID].KernelVersion = group.KernelVersion
self.Controllers[controllerID].NodeGroups[groupID].KernelArgs = group.KernelArgs
self.Controllers[controllerID].NodeGroups[groupID].Ipxe = group.Ipxe
self.Controllers[controllerID].NodeGroups[groupID].IpmiUserName = group.IpmiUserName
self.Controllers[controllerID].NodeGroups[groupID].IpmiPassword = group.IpmiPassword
self.Controllers[controllerID].NodeGroups[groupID].RuntimeOverlay = group.RuntimeOverlay
self.Controllers[controllerID].NodeGroups[groupID].SystemOverlay = group.SystemOverlay
self.Controllers[controllerID].NodeGroups[groupID].Profiles = group.Profiles
return nil
}
/****
*
* CONTROLLER MODIFIERS
*
****/
func (self *nodeYaml) AddController(controllerID string) error {
var controller ControllerConf
var group GroupConf
wwlog.Printf(wwlog.VERBOSE, "Adding new controller: %s/%s\n", controllerID)
if _, ok := self.Controllers[controllerID]; ok {
return errors.New("Controller already exists: " + controllerID)
}
self.Controllers[controllerID] = &controller
self.Controllers[controllerID].NodeGroups = make(map[string]*GroupConf)
self.Controllers[controllerID].NodeGroups["default"] = &group
return nil
}
func (self *nodeYaml) DelController(controllerID string) error {
if _, ok := self.Controllers[controllerID]; ! ok {
return errors.New("Controller does not exist: " + controllerID)
}
wwlog.Printf(wwlog.VERBOSE, "Deleting controller: %s\n", controllerID)
delete(self.Controllers, controllerID)
return nil
}
func(self *nodeYaml) ControllerUpdate(controller ControllerInfo) error {
controllerID := controller.Id
if _, ok := self.Controllers[controllerID]; ! ok {
return errors.New("Controller does not exist: " + controllerID)
}
self.Controllers[controllerID].Ipaddr = controller.Ipaddr
self.Controllers[controllerID].Comment = controller.Comment
self.Controllers[controllerID].Services.Warewulfd.Port = controller.Services.Warewulfd.Port
self.Controllers[controllerID].Services.Warewulfd.Secure = controller.Services.Warewulfd.Secure
self.Controllers[controllerID].Services.Warewulfd.StartCmd = controller.Services.Warewulfd.StartCmd
self.Controllers[controllerID].Services.Warewulfd.RestartCmd = controller.Services.Warewulfd.RestartCmd
self.Controllers[controllerID].Services.Warewulfd.EnableCmd = controller.Services.Warewulfd.EnableCmd
self.Controllers[controllerID].Services.Dhcp.Enabled = controller.Services.Dhcp.Enabled
self.Controllers[controllerID].Services.Dhcp.ConfigFile = controller.Services.Dhcp.ConfigFile
self.Controllers[controllerID].Services.Dhcp.RangeStart = controller.Services.Dhcp.RangeStart
self.Controllers[controllerID].Services.Dhcp.RangeEnd = controller.Services.Dhcp.RangeEnd
self.Controllers[controllerID].Services.Dhcp.StartCmd = controller.Services.Dhcp.StartCmd
self.Controllers[controllerID].Services.Dhcp.RestartCmd = controller.Services.Dhcp.RestartCmd
self.Controllers[controllerID].Services.Dhcp.EnableCmd = controller.Services.Dhcp.EnableCmd
self.Controllers[controllerID].Services.Nfs.Enabled = controller.Services.Nfs.Enabled
self.Controllers[controllerID].Services.Nfs.Exports = controller.Services.Nfs.Exports
self.Controllers[controllerID].Services.Nfs.StartCmd = controller.Services.Nfs.StartCmd
self.Controllers[controllerID].Services.Nfs.RestartCmd = controller.Services.Nfs.RestartCmd
self.Controllers[controllerID].Services.Nfs.EnableCmd = controller.Services.Nfs.EnableCmd
self.Controllers[controllerID].Services.Tftp.Enabled = controller.Services.Tftp.Enabled
self.Controllers[controllerID].Services.Tftp.TftpRoot = controller.Services.Tftp.TftpRoot
self.Controllers[controllerID].Services.Tftp.StartCmd = controller.Services.Tftp.StartCmd
self.Controllers[controllerID].Services.Tftp.RestartCmd = controller.Services.Tftp.RestartCmd
self.Controllers[controllerID].Services.Tftp.EnableCmd = controller.Services.Tftp.EnableCmd
return nil
}
/****
*
* PROFILE MODIFIERS
*
****/
func (self *nodeYaml) AddProfile(profileID string) error {
var profile ProfileConf
wwlog.Printf(wwlog.VERBOSE, "Adding new profile: %s/%s\n", profileID)
if _, ok := self.NodeProfiles[profileID]; ok {
return errors.New("Profile name already exists: " + profileID)
}
self.NodeProfiles[profileID] = &profile
return nil
}
func (self *nodeYaml) DelProfile(profileID string) error {
if _, ok := self.NodeProfiles[profileID]; ! ok {
return errors.New("Group '" + profileID + "' was not found")
}
wwlog.Printf(wwlog.VERBOSE, "Deleting profile: %s\n", profileID)
delete(self.NodeProfiles, profileID)
return nil
}
func(self *nodeYaml) ProfileUpdate(profile ProfileInfo) error {
profileID := profile.Id
if _, ok := self.NodeProfiles[profileID]; ! ok {
return errors.New("Group '" + profileID + "' was not found")
}
self.NodeProfiles[profileID].DomainName = profile.DomainName
self.NodeProfiles[profileID].Vnfs = profile.Vnfs
self.NodeProfiles[profileID].Ipxe = profile.Ipxe
self.NodeProfiles[profileID].KernelVersion = profile.KernelVersion
self.NodeProfiles[profileID].IpmiUserName = profile.IpmiUserName
self.NodeProfiles[profileID].IpmiPassword = profile.IpmiPassword
self.NodeProfiles[profileID].RuntimeOverlay = profile.RuntimeOverlay
self.NodeProfiles[profileID].SystemOverlay = profile.SystemOverlay
return nil
}
/****
*
* PERSISTENCE
*
****/
func (self *nodeYaml) Persist() error {
out, err := yaml.Marshal(self)
if err != nil {
return err
}
file, err := os.OpenFile(ConfigFile, os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0644)
if err != nil {
wwlog.Printf(wwlog.ERROR, "%s\n", err)
os.Exit(1)
}
defer file.Close()
_, err = file.WriteString(string(out))
if err != nil {
return err
}
return nil
}

View File

@@ -1,530 +0,0 @@
package node
import (
"fmt"
"github.com/hpcng/warewulf/internal/pkg/errors"
"github.com/hpcng/warewulf/internal/pkg/util"
"github.com/hpcng/warewulf/internal/pkg/wwlog"
"gopkg.in/yaml.v2"
"io/ioutil"
"os"
"regexp"
"strings"
)
const ConfigFile = "/etc/warewulf/nodes.conf"
const LocalStateDir = "/var/warewulf"
func init() {
//TODO: Check to make sure nodes.conf is found
}
type nodeYaml struct {
NodeGroups map[string]*nodeGroup //`yaml:"nodegroups"`
}
type nodeGroup struct {
Comment string
Vnfs string `yaml:"vnfs"`
Ipxe string `yaml:"ipxe template,omitempty"`
SystemOverlay string `yaml:"system overlay,omitempty""`
RuntimeOverlay string `yaml:"runtime overlay""`
DomainSuffix string `yaml:"domain suffix"`
KernelVersion string `yaml:"kernel version"`
KernelArgs string `yaml:"kernel args"`
IpmiUserName string `yaml:"ipmi username,omitempty"`
IpmiPassword string `yaml:"ipmi password,omitempty"`
Nodes map[string]*nodeEntry
}
type nodeEntry struct {
Hostname string `yaml:"hostname,omitempty"`
Vnfs string `yaml:"vnfs,omitempty"`
Ipxe string `yaml:"ipxe template,omitempty"`
SystemOverlay string `yaml:"system overlay,omitempty"`
RuntimeOverlay string `yaml:"runtime overlay,omitempty"`
DomainSuffix string `yaml:"domain suffix,omitempty"`
KernelVersion string `yaml:"kernel version,omitempty"`
KernelArgs string `yaml:"kernel args,omitempty"`
IpmiIpaddr string `yaml:"ipmi ipaddr,omitempty"`
IpmiUserName string `yaml:"ipmi username,omitempty"`
IpmiPassword string `yaml:"ipmi password,omitempty"`
NetDevs map[string]*netDevs
}
type netDevs struct {
Type string `yaml:"type,omitempty"`
Hwaddr string
Ipaddr string
Netmask string
Gateway string`yaml:"gateway,omitempty"`
}
type NodeInfo struct {
Id string
Gid string
Uid string
GroupName string
HostName string
DomainName string
Fqdn string
Vnfs string
Ipxe string
SystemOverlay string
RuntimeOverlay string
KernelVersion string
KernelArgs string
IpmiIpaddr string
IpmiUserName string
IpmiPassword string
NetDevs map[string]*netDevs
}
type GroupInfo struct {
Id string
GroupName string
DomainName string
Vnfs string
Ipxe string
SystemOverlay string
RuntimeOverlay string
KernelVersion string
KernelArgs string
IpmiUserName string
IpmiPassword string
}
func New() (nodeYaml, error) {
var ret nodeYaml
wwlog.Printf(wwlog.DEBUG, "Opening node configuration file: %s\n", ConfigFile)
data, err := ioutil.ReadFile(ConfigFile)
if err != nil {
fmt.Printf("error reading node configuration file\n")
return ret, err
}
err = yaml.Unmarshal(data, &ret)
if err != nil {
return ret, err
}
return ret, nil
}
func (self *nodeYaml) AddGroup(groupID string) error {
var group nodeGroup
if _, ok := self.NodeGroups[groupID]; ok {
return errors.New("Group name already exists: " + groupID)
}
self.NodeGroups[groupID] = &group
self.NodeGroups[groupID].DomainSuffix = groupID
return nil
}
func (self *nodeYaml) AddNode(groupID string, nodeID string) error {
var node nodeEntry
wwlog.Printf(wwlog.VERBOSE, "Adding new node: %s/%s\n", groupID, nodeID)
if _, ok := self.NodeGroups[groupID]; ok {
if _, ok := self.NodeGroups[groupID].Nodes[nodeID]; ok {
return errors.New("Nodename already exists in group: " + nodeID)
}
} else {
return errors.New("Group does not exist: "+groupID)
}
self.NodeGroups[groupID].Nodes[nodeID] = &node
self.NodeGroups[groupID].Nodes[nodeID].Hostname = nodeID
return nil
}
func (self *nodeYaml) DelNode(groupID string, nodeID string) error {
if _, ok := self.NodeGroups[groupID]; ok {
if _, ok := self.NodeGroups[groupID].Nodes[nodeID]; ok {
delete(self.NodeGroups[groupID].Nodes, nodeID)
wwlog.Printf(wwlog.VERBOSE, "Deleting node: %s/%s\n", groupID, nodeID)
} else {
return errors.New("Node '"+nodeID+"' was not found in group '"+groupID+"'")
}
} else {
return errors.New("Group '"+groupID+"' was not found")
}
return nil
}
func (self *nodeYaml) DelNodeNet(groupID string, nodeID string, netDev string) error {
if _, ok := self.NodeGroups[groupID]; ok {
if _, ok := self.NodeGroups[groupID].Nodes[nodeID]; ok {
if _, ok := self.NodeGroups[groupID].Nodes[nodeID].NetDevs[netDev]; ok {
wwlog.Printf(wwlog.VERBOSE, "Deleting node network device: %s/%s:%s\n", groupID, nodeID, netDev)
delete(self.NodeGroups[groupID].Nodes[nodeID].NetDevs, netDev)
} else {
return errors.New("Network device '"+netDev+"' was not found in node '"+groupID+"/"+nodeID+"'")
}
} else {
return errors.New("Node '"+nodeID+"' was not found in group '"+groupID+"'")
}
} else {
return errors.New("Group '"+groupID+"' was not found")
}
return nil
}
func (self *nodeYaml) DelGroup(groupname string) error {
if _, ok := self.NodeGroups[groupname]; ok {
delete(self.NodeGroups, groupname)
} else {
return errors.New("Node group undefined: " + groupname)
}
return nil
}
func (self *nodeYaml) SetGroupVal(groupID string, entry string, value string) error {
if strings.ToUpper(value) == "UNDEF" || strings.ToUpper(value) == "NIL" || strings.ToUpper(value) == "DEL" {
value = ""
}
if _, ok := self.NodeGroups[groupID]; ok {
wwlog.Printf(wwlog.VERBOSE, "Setting group %s to: %s = '%s'\n", groupID, entry, value )
switch strings.ToUpper(entry) {
case "VNFS":
util.ValidateOrDie("VNFS", entry, "^[a-zA-Z0-9-._]*$")
self.NodeGroups[groupID].Vnfs = value
case "KERNEL":
util.ValidateOrDie("Kernel Version", entry, "^[a-zA-Z0-9-._]*$")
self.NodeGroups[groupID].KernelVersion = value
case "DOMAINSUFFIX":
util.ValidateOrDie("Domain", entry, "^[a-zA-Z0-9-._]*$")
self.NodeGroups[groupID].DomainSuffix = value
case "IPXE":
util.ValidateOrDie("iPXE Template", entry, "^[a-zA-Z0-9-._]*$")
self.NodeGroups[groupID].Ipxe = value
case "SYSTEMOVERLAY":
util.ValidateOrDie("System Overlay", entry, "^[a-zA-Z0-9-._]*$")
self.NodeGroups[groupID].SystemOverlay = value
case "RUNTIMEOVERLAY":
util.ValidateOrDie("Runtime Overlay", entry, "^[a-zA-Z0-9-._]*$")
self.NodeGroups[groupID].RuntimeOverlay = value
case "IPMIUSERNAME":
util.ValidateOrDie("IPMI Username", entry, "^[a-zA-Z0-9-._]*$")
self.NodeGroups[groupID].IpmiUserName = value
case "IPMIPASSWORD":
util.ValidateOrDie("IPMI Password", entry, "^[a-zA-Z0-9-._]*$")
self.NodeGroups[groupID].IpmiPassword = value
}
} else {
return errors.New("Group does not exist: " +groupID)
}
return nil
}
func (self *nodeYaml) SetNodeVal(groupID string, nodeID string, entry string, value string) error {
if strings.ToUpper(value) == "UNDEF" || strings.ToUpper(value) == "NIL" || strings.ToUpper(value) == "DEL" {
value = ""
}
if _, ok := self.NodeGroups[groupID]; ok {
if _, ok := self.NodeGroups[groupID].Nodes[nodeID]; ok {
wwlog.Printf(wwlog.VERBOSE, "Setting node %s/%s to: %s = '%s'\n", groupID, nodeID, entry, value )
switch strings.ToUpper(entry) {
case "VNFS":
util.ValidateOrDie("VNFS", entry, "^[a-zA-Z0-9-._]*$")
self.NodeGroups[groupID].Nodes[nodeID].Vnfs = value
case "KERNEL":
util.ValidateOrDie("Kernel Version", entry, "^[a-zA-Z0-9-._]*$")
self.NodeGroups[groupID].Nodes[nodeID].KernelVersion = value
case "DOMAINSUFFIX":
util.ValidateOrDie("Domain", entry, "^[a-zA-Z0-9-._]*$")
self.NodeGroups[groupID].Nodes[nodeID].DomainSuffix = value
case "IPXE":
util.ValidateOrDie("iPXE Template", entry, "^[a-zA-Z0-9-._]*$")
self.NodeGroups[groupID].Nodes[nodeID].Ipxe = value
case "SYSTEMOVERLAY":
util.ValidateOrDie("System Overlay", entry, "^[a-zA-Z0-9-._]*$")
self.NodeGroups[groupID].Nodes[nodeID].SystemOverlay = value
case "RUNTIMEOVERLAY":
util.ValidateOrDie("Runtime Overlay", entry, "^[a-zA-Z0-9-._]*$")
self.NodeGroups[groupID].Nodes[nodeID].RuntimeOverlay = value
case "HOSTNAME":
util.ValidateOrDie("Hostname", entry, "^[a-zA-Z0-9-._]*$")
self.NodeGroups[groupID].Nodes[nodeID].Hostname = value
case "IPMIIPADDR":
util.ValidateOrDie("IPMI IP Address", entry, "^(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)(\\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)){3}$")
self.NodeGroups[groupID].Nodes[nodeID].IpmiIpaddr = value
case "IPMIUSERNAME":
util.ValidateOrDie("IPMI Username", entry, "^[a-zA-Z0-9-._]*$")
self.NodeGroups[groupID].Nodes[nodeID].IpmiUserName = value
case "IPMIPASSWORD":
util.ValidateOrDie("IPMI Password", entry, "^[a-zA-Z0-9-._]*$")
self.NodeGroups[groupID].Nodes[nodeID].IpmiPassword = value
}
} else {
return errors.New("Node does not exist: " +groupID+ "/" +nodeID)
}
} else {
return errors.New("Group does not exist: " +groupID)
}
return nil
}
func (self *nodeYaml) SetNodeNet(groupID string, nodeID string, netDev string, entry string, value string) error {
if strings.ToUpper(value) == "UNDEF" || strings.ToUpper(value) == "NIL" || strings.ToUpper(value) == "DEL" {
value = ""
}
if _, ok := self.NodeGroups[groupID]; ok {
if _, ok := self.NodeGroups[groupID].Nodes[nodeID]; ok {
if _, ok := self.NodeGroups[groupID].Nodes[nodeID].NetDevs[netDev]; ok {
wwlog.Printf(wwlog.VERBOSE, "Editing existing node NetDev entry for node: %s/%s\n", groupID, nodeID)
} else {
var nd netDevs
self.NodeGroups[groupID].Nodes[nodeID].NetDevs[netDev] = &nd
}
} else {
return errors.New("Node does not exist: "+groupID+"/"+nodeID)
}
} else {
return errors.New("Group does not exist: "+groupID)
}
switch strings.ToUpper(entry) {
case "IPADDR":
util.ValidateOrDie("IP address", value, "^(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)(\\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)){3}$")
self.NodeGroups[groupID].Nodes[nodeID].NetDevs[netDev].Ipaddr = value
case "NETMASK":
util.ValidateOrDie("Netmask", value, "^(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)(\\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)){3}$")
self.NodeGroups[groupID].Nodes[nodeID].NetDevs[netDev].Netmask = value
case "GATEWAY":
util.ValidateOrDie("Gateway", value, "^(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)(\\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)){3}$")
self.NodeGroups[groupID].Nodes[nodeID].NetDevs[netDev].Gateway = value
case "TYPE":
util.ValidateOrDie("Network device type", value, "^(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)(\\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)){3}$")
self.NodeGroups[groupID].Nodes[nodeID].NetDevs[netDev].Type = value
case "HWADDR":
util.ValidateOrDie("HW address", value, "^([0-9A-Fa-f]{2}[:-]){5}([0-9A-Fa-f]{2})$")
self.NodeGroups[groupID].Nodes[nodeID].NetDevs[netDev].Hwaddr = value
}
return nil
}
func (self *nodeYaml) Persist() error {
out, err := yaml.Marshal(self)
if err != nil {
return err
}
file, err := os.OpenFile(ConfigFile, os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0644)
if err != nil {
wwlog.Printf(wwlog.ERROR, "%s\n", err)
os.Exit(1)
}
defer file.Close()
_, err = file.WriteString(string(out))
if err != nil {
return err
}
return nil
}
func (self *nodeYaml) FindAllGroups() ([]GroupInfo, error) {
var ret []GroupInfo
for groupname, group := range self.NodeGroups {
var g GroupInfo
g.Id = groupname
g.GroupName = groupname
g.RuntimeOverlay = group.RuntimeOverlay
g.SystemOverlay = group.SystemOverlay
g.Ipxe = group.Ipxe
g.KernelVersion = group.KernelVersion
g.KernelArgs = group.KernelArgs
g.Vnfs = group.Vnfs
g.IpmiUserName = group.IpmiUserName
g.IpmiPassword = group.IpmiPassword
g.DomainName = group.DomainSuffix
// TODO: Validate or die on all inputs
ret = append(ret, g)
}
return ret, nil
}
func (self *nodeYaml) FindAllNodes() ([]NodeInfo, error) {
var ret []NodeInfo
for groupname, group := range self.NodeGroups {
for nodename, node := range group.Nodes {
var n NodeInfo
n.Id = nodename
n.Gid = groupname
// n.Uid = groupname + ":" + nodename
n.GroupName = groupname
n.HostName = node.Hostname
n.IpmiIpaddr = node.IpmiIpaddr
n.Vnfs = group.Vnfs
n.SystemOverlay = group.SystemOverlay
n.RuntimeOverlay = group.RuntimeOverlay
n.KernelVersion = group.KernelVersion
n.KernelArgs = group.KernelArgs
n.DomainName = group.DomainSuffix
n.Ipxe = group.Ipxe
n.IpmiUserName = group.IpmiUserName
n.IpmiPassword = group.IpmiPassword
n.NetDevs = node.NetDevs
if node.IpmiUserName != "" {
n.IpmiUserName = node.IpmiUserName
}
if node.IpmiPassword != "" {
n.IpmiPassword = node.IpmiPassword
}
if node.KernelVersion != "" {
n.KernelVersion = node.KernelVersion
}
if node.Vnfs != "" {
n.Vnfs = node.Vnfs
}
if node.SystemOverlay != "" {
n.SystemOverlay = node.SystemOverlay
}
if node.RuntimeOverlay != "" {
n.RuntimeOverlay = node.RuntimeOverlay
}
if node.DomainSuffix != "" {
n.DomainName = node.DomainSuffix
}
if node.Ipxe != "" {
n.Ipxe = node.Ipxe
}
if node.KernelArgs != "" {
n.KernelArgs = node.KernelArgs
}
if n.RuntimeOverlay == "" {
n.RuntimeOverlay = "default"
}
if n.SystemOverlay == "" {
n.SystemOverlay = "default"
}
if n.Ipxe == "" {
n.Ipxe = "default"
}
if n.HostName == "" {
n.HostName = nodename
}
if n.DomainName != "" {
n.Fqdn = node.Hostname + "." + n.DomainName
} else {
n.Fqdn = node.Hostname
}
util.ValidateOrDie(n.Fqdn +":group name", n.GroupName, "^[a-zA-Z0-9-._]*$")
util.ValidateOrDie(n.Fqdn +":vnfs", n.Vnfs, "^[a-zA-Z0-9-._:/]*$")
util.ValidateOrDie(n.Fqdn +":system overlay", n.SystemOverlay, "^[a-zA-Z0-9-._]*$")
util.ValidateOrDie(n.Fqdn +":runtime overlay", n.RuntimeOverlay, "^[a-zA-Z0-9-._]*$")
util.ValidateOrDie(n.Fqdn +":domain suffix", n.DomainName, "^[a-zA-Z0-9-._]*$")
util.ValidateOrDie(n.Fqdn +":hostname", n.HostName, "^[a-zA-Z0-9-_]*$")
util.ValidateOrDie(n.Fqdn +":kernel version", n.KernelVersion, "^[a-zA-Z0-9-._]*$")
ret = append(ret, n)
}
}
return ret, nil
}
func (nodes *nodeYaml) FindByHwaddr(hwa string) (NodeInfo, error) {
var ret NodeInfo
n, _ := nodes.FindAllNodes()
for _, node := range n {
for _, dev := range node.NetDevs {
if dev.Hwaddr == hwa {
return node, nil
}
}
}
return ret, errors.New("No nodes found with HW Addr: " + hwa)
}
func (nodes *nodeYaml) FindByIpaddr(ipaddr string) (NodeInfo, error) {
var ret NodeInfo
n, _ := nodes.FindAllNodes()
for _, node := range n {
for _, dev := range node.NetDevs {
if dev.Ipaddr == ipaddr {
return node, nil
}
}
}
return ret, errors.New("No nodes found with IP Addr: " + ipaddr)
}
func (nodes *nodeYaml) SearchByName(search string) ([]NodeInfo, error) {
var ret []NodeInfo
n, _ := nodes.FindAllNodes()
for _, node := range n {
b, _ := regexp.MatchString(search, node.Fqdn)
if b == true {
ret = append(ret, node)
}
}
return ret, nil
}
func (nodes *nodeYaml) SearchByNameList(searchList []string) ([]NodeInfo, error) {
var ret []NodeInfo
n, _ := nodes.FindAllNodes()
for _, search := range searchList {
for _, node := range n {
b, _ := regexp.MatchString(search, node.Fqdn)
if b == true {
ret = append(ret, node)
}
}
}
return ret, nil
}

View File

@@ -0,0 +1,44 @@
package overlay
import (
"github.com/hpcng/warewulf/internal/pkg/util"
"github.com/hpcng/warewulf/internal/pkg/vnfs"
"github.com/hpcng/warewulf/internal/pkg/wwlog"
"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.WARN, "Could not include file into template: %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)
if vnfsname == "" {
wwlog.Printf(wwlog.WARN, "VNFS not set for template: %s\n", filepath)
return ""
}
v, _ := vnfs.Load(vnfsname)
vnfsDir := v.Chroot
if util.IsDir(vnfsDir) == false {
wwlog.Printf(wwlog.WARN, "Template requires VNFS (%s) to be imported: %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,41 +1,247 @@
package overlay
import (
"fmt"
"github.com/hpcng/warewulf/internal/pkg/config"
"github.com/hpcng/warewulf/internal/pkg/errors"
"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/ioutil"
"os"
"os/exec"
"path"
"path/filepath"
"regexp"
"strings"
"text/template"
)
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.WARN, "Could not include file into template: %s\n", err)
type TemplateStruct struct {
Self struct {
Fqdn string
Hostname string
GroupName string
Vnfs string
NetDevs map[string]*node.NetDevs
}
return strings.TrimSuffix(string(content), "\n")
AllNodes []node.NodeInfo
}
func templateVnfsFileInclude(vnfsname string, filepath string) string {
wwlog.Printf(wwlog.DEBUG, "Including VNFS file into template: %s: %s\n", vnfsname, filepath)
func BuildSystemOverlay(nodeList []node.NodeInfo) error {
return buildOverlay(nodeList, "system")
}
func BuildRuntimeOverlay(nodeList []node.NodeInfo) error {
return buildOverlay(nodeList, "runtime")
}
func FindSystemOverlays() ([]string, error) {
return findAllOverlays("system")
}
func FindRuntimeOverlays() ([]string, error) {
return findAllOverlays("system")
}
func SystemOverlayInit(name string) error {
return overlayInit(name, "system")
}
func RuntimeOverlayInit(name string) error {
return overlayInit(name, "runtime")
}
func findAllOverlays(overlayType string) ([]string, error) {
config := config.New()
v := vnfs.New(vnfsname)
var ret []string
var files []os.FileInfo
var err error
vnfsdir := config.VnfsChroot(v.NameClean())
if util.IsDir(vnfsdir) == false {
wwlog.Printf(wwlog.WARN, "Template requesting file from non-imported VNFS: %s (%s)\n", vnfsname, filepath)
return ""
if overlayType == "system" {
wwlog.Printf(wwlog.DEBUG, "Looking for system overlays...")
files, err = ioutil.ReadDir(config.SystemOverlayDir())
} else if overlayType == "runtime" {
wwlog.Printf(wwlog.DEBUG, "Looking for runtime overlays...")
files, err = ioutil.ReadDir(config.RuntimeOverlayDir())
} else {
wwlog.Printf(wwlog.ERROR, "overlayType requested is not supported: %s\n", overlayType)
os.Exit(1)
}
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 ret, err
}
return strings.TrimSuffix(string(content), "\n")
for _, file := range files {
wwlog.Printf(wwlog.DEBUG, "Evaluating overlay source: %s\n", file.Name())
if file.IsDir() == true {
ret = append(ret, file.Name())
}
}
return ret, nil
}
func overlayInit(name string, overlayType string) error {
var path string
config := config.New()
if overlayType == "system" {
wwlog.Printf(wwlog.DEBUG, "Looking for system overlays...")
path = config.SystemOverlaySource(name)
} else if overlayType == "runtime" {
wwlog.Printf(wwlog.DEBUG, "Looking for runtime overlays...")
path = config.RuntimeOverlaySource(name)
} else {
wwlog.Printf(wwlog.ERROR, "overlayType requested is not supported: %s\n", overlayType)
os.Exit(1)
}
if util.IsDir(path) == true {
return errors.New("Overlay already exists: " + name)
}
err := os.MkdirAll(path, 0755)
return err
}
func buildOverlay(nodeList []node.NodeInfo, overlayType string) error {
config := config.New()
nodeDB, _ := node.New()
allNodes, _ := nodeDB.FindAllNodes()
for _, node := range nodeList {
var t TemplateStruct
var OverlayDir string
var OverlayFile string
if overlayType == "runtime" {
OverlayDir = config.RuntimeOverlaySource(node.RuntimeOverlay.Get())
OverlayFile = config.RuntimeOverlayImage(node.Fqdn.Get())
} else if overlayType == "system" {
OverlayDir = config.SystemOverlaySource(node.RuntimeOverlay.Get())
OverlayFile = config.SystemOverlayImage(node.Fqdn.Get())
} else {
wwlog.Printf(wwlog.ERROR, "overlayType requested is not supported: %s\n", overlayType)
os.Exit(1)
}
wwlog.Printf(wwlog.DEBUG, "Processing overlay for node: %s\n", node.Fqdn.Get())
t.Self.Fqdn = node.Fqdn.Get()
t.Self.Hostname = node.HostName.Get()
t.Self.GroupName = node.Gid.Get()
t.Self.Vnfs = node.Vnfs.Get()
t.Self.NetDevs = node.NetDevs
t.AllNodes = allNodes
if overlayType == "runtime" && node.RuntimeOverlay.Defined() == false {
wwlog.Printf(wwlog.WARN, "Undefined runtime overlay, skipping node: %s\n", node.Fqdn.Get())
}
if overlayType == "system" && node.SystemOverlay.Defined() == false {
wwlog.Printf(wwlog.WARN, "Undefined system overlay, skipping node: %s\n", node.Fqdn.Get())
}
wwlog.Printf(wwlog.DEBUG, "Checking to see if overlay directory exists: %s\n", OverlayDir)
if util.IsDir(OverlayDir) == false {
wwlog.Printf(wwlog.WARN, "%-35s: Skipped (runtime overlay template not found)\n", node.Fqdn.Get())
continue
}
wwlog.Printf(wwlog.DEBUG, "Creating parent directory for OverlayFile: %s\n", path.Dir(OverlayFile))
err := os.MkdirAll(path.Dir(OverlayFile), 0755)
if err != nil {
return err
}
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, "Creating temporary directory for overlay files\n")
tmpDir, err := ioutil.TempDir(os.TempDir(), ".wwctl-overlay-")
if err != nil {
return err
}
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,
"IncludeFromVnfs": 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, t)
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.Get())
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.Get())
wwlog.Printf(wwlog.DEBUG, "Removing temporary directory: %s\n", tmpDir)
os.RemoveAll(tmpDir)
}
return nil
}

View File

@@ -1,181 +0,0 @@
package overlay
import (
"fmt"
"github.com/hpcng/warewulf/internal/pkg/config"
"github.com/hpcng/warewulf/internal/pkg/errors"
"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/ioutil"
"os"
"os/exec"
"path"
"path/filepath"
"regexp"
"strings"
"text/template"
)
func FindAllRuntimeOverlays() ([]string, error) {
config := config.New()
var ret []string
wwlog.Printf(wwlog.DEBUG, "Looking for runtime overlays...")
files, err := ioutil.ReadDir(config.RuntimeOverlayDir())
if err != nil {
return ret, err
}
for _, file := range files {
wwlog.Printf(wwlog.DEBUG, "Evaluating runtime overlay: %s\n", file.Name())
if file.IsDir() == true {
ret = append(ret, file.Name())
}
}
return ret, nil
}
func RuntimeOverlayInit(name string) error {
config := config.New()
path := config.RuntimeOverlaySource(name)
if util.IsDir(path) == true {
return errors.New("Runtime overlay already exists: "+name)
}
err := os.MkdirAll(path, 0755)
return err
}
func RuntimeBuild(nodeList []node.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)
vnfs := vnfs.New(node.Vnfs)
vnfsDir := config.VnfsChroot(vnfs.NameClean())
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, "%-35s: Skipped (runtime overlay template not found)\n", node.Fqdn)
continue
}
if util.IsDir(vnfsDir) == false {
wwlog.Printf(wwlog.WARN, "%-35s: Skipped (VNFS not imported)\n", node.Fqdn)
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, "IncludeFromVnfs": 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,181 +0,0 @@
package overlay
import (
"fmt"
"github.com/hpcng/warewulf/internal/pkg/config"
"github.com/hpcng/warewulf/internal/pkg/errors"
"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/ioutil"
"os"
"os/exec"
"path"
"path/filepath"
"regexp"
"strings"
"text/template"
)
func FindAllSystemOverlays() ([]string, error) {
config := config.New()
var ret []string
wwlog.Printf(wwlog.DEBUG, "Looking for system overlays...")
files, err := ioutil.ReadDir(config.SystemOverlayDir())
if err != nil {
return ret, err
}
for _, file := range files {
wwlog.Printf(wwlog.DEBUG, "Evaluating system overlay: %s\n", file.Name())
if file.IsDir() == true {
ret = append(ret, file.Name())
}
}
return ret, nil
}
func SystemOverlayInit(name string) error {
config := config.New()
path := config.SystemOverlaySource(name)
if util.IsDir(path) == true {
return errors.New("Runtime overlay already exists: "+name)
}
err := os.MkdirAll(path, 0755)
return err
}
func SystemBuild(nodeList []node.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)
vnfs := vnfs.New(node.Vnfs)
vnfsDir := config.VnfsChroot(vnfs.NameClean())
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, "%-35s: Skipped (system overlay template not found)\n", node.Fqdn)
continue
}
if util.IsDir(vnfsDir) == false {
wwlog.Printf(wwlog.WARN, "%-35s: Skipped (VNFS not imported)\n", node.Fqdn)
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, "IncludeFromVnfs": 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

@@ -37,6 +37,8 @@ func DirModTime(path string) (time.Time, error) {
}
func PathIsNewer(source string, compare string) bool {
wwlog.Printf(wwlog.DEBUG, "Comparing times on paths: '%s' - '%s'\n", source, compare)
time1, err := DirModTime(source)
if err != nil {
wwlog.Printf(wwlog.DEBUG, "%s\n", err)
@@ -90,6 +92,9 @@ func CopyFile(source string, dest string) error {
func IsDir(path string) (bool) {
if path == "" {
return false
}
if stat, err := os.Stat(path); err == nil && stat.IsDir() {
return true
}
@@ -97,6 +102,10 @@ func IsDir(path string) (bool) {
}
func IsFile(path string) (bool) {
if path == "" {
return false
}
if _, err := os.Stat(path); err == nil {
return true
}
@@ -182,3 +191,38 @@ func ShaSumFile(file string) (string, error) {
return fmt.Sprintf("%x", h.Sum(nil)), nil
}
func SliceRemoveElement(array []string, remove string) []string {
var ret []string
// Linear time, maintains order
for _, r := range array {
if r != remove {
ret = append(ret, r)
} else {
wwlog.Printf(wwlog.DEBUG, "Removing slice from array: %s\n", remove)
}
}
return ret
}
func SliceAddUniqueElement(array []string, add string) []string {
var ret []string
var found bool
//Linear time, appends
for _, r := range array {
ret = append(ret, r)
if r == add {
found = true
}
}
if found == false {
ret = append(ret, add)
}
return ret
}

View File

@@ -2,63 +2,61 @@ package vnfs
import (
"fmt"
"github.com/hpcng/warewulf/internal/pkg/config"
"github.com/hpcng/warewulf/internal/pkg/util"
"github.com/hpcng/warewulf/internal/pkg/wwlog"
"os"
"path"
)
func BuildContainerdir(v VnfsObject, buildForce bool) {
config := config.New()
func BuildContainerdir(vnfs VnfsObject, buildForce bool) {
if _, err := os.Stat(v.Source()); err != nil {
wwlog.Printf(wwlog.INFO, "%-35s: Skipping (bad path)\n", v.Name())
if _, err := os.Stat(vnfs.Source); err != nil {
wwlog.Printf(wwlog.INFO, "%-35s: Skipping (bad path)\n", vnfs.Source)
return
}
wwlog.Printf(wwlog.DEBUG, "Checking if there have been any updates to the VNFS directory\n")
if util.PathIsNewer(v.Source(), config.VnfsImage(v.NameClean())) {
if util.PathIsNewer(vnfs.Source, vnfs.Image) {
if buildForce == false {
wwlog.Printf(wwlog.INFO, "%-35s: Skipping, VNFS is current\n", v.Name())
wwlog.Printf(wwlog.INFO, "%-35s: Skipping, VNFS is current\n", vnfs.Name)
return
}
}
wwlog.Printf(wwlog.DEBUG, "Making the directory: %s\n", path.Dir(config.VnfsImage(v.NameClean())))
err := os.MkdirAll(path.Dir(config.VnfsImage(v.NameClean())), 0755)
wwlog.Printf(wwlog.DEBUG, "Making parent directory for: %s\n", vnfs.Image)
err := os.MkdirAll(path.Dir(vnfs.Image), 0755)
if err != nil {
fmt.Printf("ERROR: %s\n", err)
return
}
wwlog.Printf(wwlog.DEBUG, "Making the directory: %s\n", path.Dir(config.VnfsChroot(v.NameClean())))
err = os.MkdirAll(path.Dir(config.VnfsChroot(v.NameClean())), 0755)
wwlog.Printf(wwlog.DEBUG, "Making parent directory for: %s\n", vnfs.Chroot)
err = os.MkdirAll(path.Dir(vnfs.Chroot), 0755)
if err != nil {
fmt.Printf("ERROR: %s\n", err)
return
}
wwlog.Printf(wwlog.DEBUG, "Building VNFS image: '%s' -> '%s'\n", v.Source(), config.VnfsImage(v.NameClean()))
err = buildVnfs(v.Source(), config.VnfsImage(v.NameClean()))
wwlog.Printf(wwlog.DEBUG, "Building VNFS image: '%s' -> '%s'\n", vnfs.Source, vnfs.Image)
err = buildVnfs(vnfs.Source, vnfs.Image)
if err != nil {
fmt.Printf("ERROR: %s\n", err)
os.Exit(1)
}
// Setup links from OCI rootfs to chroot path
_ = os.Remove(config.VnfsChroot(v.NameClean()) + "-link")
err = os.Symlink(v.Source(), config.VnfsChroot(v.NameClean())+"-link")
_ = os.Remove(vnfs.Chroot + "-link")
err = os.Symlink(vnfs.Source, vnfs.Chroot+"-link")
if err != nil {
wwlog.Printf(wwlog.ERROR, "Could not create symlink for Chroot: %s\n", err)
os.Exit(1)
}
err = os.Rename(config.VnfsChroot(v.NameClean())+"-link", config.VnfsChroot(v.NameClean()))
err = os.Rename(vnfs.Chroot + "-link", vnfs.Chroot)
if err != nil {
wwlog.Printf(wwlog.ERROR, "Could not rename link: %s\n", err)
os.Exit(1)
}
wwlog.Printf(wwlog.INFO, "%-35s: Done\n", v.Name())
wwlog.Printf(wwlog.INFO, "%-35s: Done\n", vnfs.Name)
}

View File

@@ -11,8 +11,8 @@ import (
)
func BuildDocker(v VnfsObject, buildForce bool) {
wwlog.Printf(wwlog.VERBOSE, "Building OCI Container: %s\n", v.Source())
func BuildDocker(vnfs VnfsObject, buildForce bool) {
wwlog.Printf(wwlog.VERBOSE, "Building OCI Container: %s\n", vnfs.Source)
config := config.New()
OciCacheDir := config.LocalStateDir + "/oci"
@@ -25,7 +25,7 @@ func BuildDocker(v VnfsObject, buildForce bool) {
}
wwlog.Printf(wwlog.VERBOSE, "Downloading OCI container layers\n")
sourcePath, err := c.Pull(context.Background(), v.Source(), nil)
sourcePath, err := c.Pull(context.Background(), vnfs.Source, nil)
if err != nil {
fmt.Printf("ERROR: %s\n", err)
os.Exit(1)
@@ -33,10 +33,10 @@ func BuildDocker(v VnfsObject, buildForce bool) {
hashDestination := VnfsHashDir + path.Base(sourcePath)
name, err := os.Readlink(config.VnfsImage(v.NameClean()))
name, err := os.Readlink(vnfs.Image)
if err == nil {
if name == hashDestination && buildForce == false {
wwlog.Printf(wwlog.INFO, "%-35s: Skipping, VNFS is current\n", v.Name())
wwlog.Printf(wwlog.INFO, "%-35s: Skipping, VNFS is current\n", vnfs.Name)
return
}
}
@@ -46,12 +46,16 @@ func BuildDocker(v VnfsObject, buildForce bool) {
fmt.Printf("ERROR: %s\n", err)
return
}
err = os.MkdirAll(path.Dir(config.VnfsImage(v.NameClean())), 0755)
wwlog.Printf(wwlog.DEBUG, "Making parent directory for: %s\n", vnfs.Image)
err = os.MkdirAll(path.Dir(vnfs.Image), 0755)
if err != nil {
fmt.Printf("ERROR: %s\n", err)
return
}
err = os.MkdirAll(path.Dir(config.VnfsChroot(v.NameClean())), 0755)
wwlog.Printf(wwlog.DEBUG, "Making parent directory for: %s\n", vnfs.Chroot)
err = os.MkdirAll(path.Dir(vnfs.Chroot), 0755)
if err != nil {
fmt.Printf("ERROR: %s\n", err)
return
@@ -68,33 +72,33 @@ func BuildDocker(v VnfsObject, buildForce bool) {
wwlog.Printf(wwlog.VERBOSE, "Finalizing Build\n")
// Setup links from OCI image to provision path
_ = os.Remove(config.VnfsImage(v.NameClean()) + "-link")
err = os.Symlink(hashDestination, config.VnfsImage(v.NameClean())+"-link")
_ = os.Remove(vnfs.Image + "-link")
err = os.Symlink(hashDestination, vnfs.Image + "-link")
if err != nil {
wwlog.Printf(wwlog.ERROR, "Could not create symlink for Image: %s\n", err)
os.Exit(1)
}
err = os.Rename(config.VnfsImage(v.NameClean())+"-link", config.VnfsImage(v.NameClean()))
err = os.Rename(vnfs.Image + "-link", vnfs.Image)
if err != nil {
wwlog.Printf(wwlog.ERROR, "Could not rename link: %s\n", err)
os.Exit(1)
}
// Setup links from OCI rootfs to chroot path
_ = os.Remove(config.VnfsChroot(v.NameClean()) + "-link")
err = os.Symlink(sourcePath, config.VnfsChroot(v.NameClean())+"-link")
_ = os.Remove(vnfs.Chroot + "-link")
err = os.Symlink(sourcePath, vnfs.Chroot + "-link")
if err != nil {
wwlog.Printf(wwlog.ERROR, "Could not create symlink for Chroot: %s\n", err)
os.Exit(1)
}
err = os.Rename(config.VnfsChroot(v.NameClean())+"-link", config.VnfsChroot(v.NameClean()))
err = os.Rename(vnfs.Chroot + "-link", vnfs.Chroot)
if err != nil {
wwlog.Printf(wwlog.ERROR, "Could not rename link: %s\n", err)
os.Exit(1)
}
wwlog.Printf(wwlog.INFO, "%-35s: Done\n", v.Name())
wwlog.Printf(wwlog.INFO, "%-35s: Done\n", vnfs.Source)
return
}

View File

@@ -1,70 +1,186 @@
package vnfs
import (
"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"
"gopkg.in/yaml.v2"
"io/ioutil"
"os"
"path"
"strings"
)
type VnfsObject struct {
SourcePath string
Name string
Source string
Chroot string
Image string
Config string
}
func New(s string) VnfsObject {
func Load (name string) (VnfsObject, error) {
config := config.New()
var ret VnfsObject
ret.SourcePath = s
if name == "" {
wwlog.Printf(wwlog.DEBUG, "Called vnfs.Load() without a name, returning error\n")
return ret, errors.New("Called vnfs.Load() without a VNFS name")
}
return ret
pathFriendlyName := CleanName(name)
configFile := path.Join(config.VnfsImageDir(pathFriendlyName), "config.yaml")
if util.IsFile(configFile) == false {
return ret, errors.New("VNFS has not been imported: " + name)
}
data, err := ioutil.ReadFile(configFile)
if err != nil {
return ret, errors.New("Error reading VNFS configuration file: " + name)
}
err = yaml.Unmarshal(data, &ret)
if err != nil {
return ret, err
}
return ret, nil
}
func (self *VnfsObject) Name() string {
if self.SourcePath == "" {
return ""
}
func CleanName(source string) string {
var tmp string
if strings.HasPrefix(self.SourcePath, "/") {
return path.Base(self.SourcePath)
}
return self.SourcePath
}
func (self *VnfsObject) NameClean() string {
if self.SourcePath == "" {
return ""
}
if strings.HasPrefix(self.SourcePath, "/") {
return path.Base(self.SourcePath)
}
uri := strings.Split(self.SourcePath, "://")
return strings.ReplaceAll(uri[0]+":"+uri[1], "/", "_")
}
func (self *VnfsObject) Source() string {
if self.SourcePath == "" {
return ""
}
return self.SourcePath
}
func Build(uri string, force bool) error {
v := New(uri)
wwlog.Printf(wwlog.VERBOSE, "Building VNFS: %s\n", uri)
if strings.HasPrefix(uri, "/") {
if strings.HasSuffix(uri, "tar.gz") {
//wwlog.Printf(wwlog.WARN, "Building VNFS from local tarball: %s\n", uri)
wwlog.Printf(wwlog.WARN, "Building VNFS from local tarball is not supported yet: %s\n", uri)
} else {
BuildContainerdir(v, force)
}
if strings.HasPrefix(source, "/") == true {
tmp = path.Base(source)
} else {
BuildDocker(v, force)
tmp = source
}
tmp = strings.ReplaceAll(tmp, "://", ":")
tmp = strings.ReplaceAll(tmp, "/", "-")
tmp = strings.ReplaceAll(tmp, ":", ":")
return tmp
}
func New(source string) (VnfsObject, error) {
var ret VnfsObject
config := config.New()
if source == "" {
wwlog.Printf(wwlog.DEBUG, "Called vnfs.Load() without a name, returning error\n")
return ret, errors.New("Called vnfs.Load() without a VNFS name")
}
if util.IsFile(ret.Config) {
return Load(source)
}
pathFriendlyName := CleanName(source)
if strings.HasPrefix(source, "/") == true {
ret.Source = source
ret.Name = pathFriendlyName
} else {
tmp := strings.ReplaceAll(source, "://", "-")
tmp = strings.ReplaceAll(tmp, "/", ".")
tmp = strings.ReplaceAll(tmp, ":", ".")
ret.Name = source
ret.Source = source
}
ret.Chroot = config.VnfsChroot(pathFriendlyName)
ret.Image = config.VnfsImage(pathFriendlyName)
ret.Config = path.Join(config.VnfsImageDir(pathFriendlyName), "config.yaml")
return ret, nil
}
func (self *VnfsObject) SaveConfig() error {
out, err := yaml.Marshal(self)
if err != nil {
return err
}
file, err := os.OpenFile(self.Config, os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0644)
if err != nil {
wwlog.Printf(wwlog.ERROR, "%s\n", err)
os.Exit(1)
}
defer file.Close()
_, err = file.WriteString(string(out))
if err != nil {
return err
}
return nil
}
func Build(name string, force bool) error {
vnfs, err := New(name)
if err != nil {
return err
}
wwlog.Printf(wwlog.VERBOSE, "Building VNFS: %s\n", vnfs.Name)
if strings.HasPrefix(vnfs.Source, "/") {
if strings.HasSuffix(vnfs.Source, "tar.gz") {
//wwlog.Printf(wwlog.WARN, "Building VNFS from local tarball: %s\n", uri)
wwlog.Printf(wwlog.WARN, "Building VNFS from local tarball is not supported yet: %s\n", vnfs.Name)
} else {
BuildContainerdir(vnfs, force)
}
} else {
BuildDocker(vnfs, force)
}
err = vnfs.SaveConfig()
if err != nil {
return err
}
return nil
}
func (self *VnfsObject) Nameold() string {
if self.Source == "" {
return ""
}
if strings.HasPrefix(self.Source, "/") {
return path.Base(self.Source)
}
return self.Source
}
func NameClean1(SourcePath string) string {
if SourcePath == "" {
return ""
}
if strings.HasPrefix(SourcePath, "/") {
return path.Base(SourcePath)
}
uri := strings.Split(SourcePath, "://")
return strings.ReplaceAll(uri[0]+":"+uri[1], "/", "_")
}