Merge branch 'main' of github.com:ctrl-cmd/warewulf into main
This commit is contained in:
13
internal/app/sandbox/main.go
Normal file
13
internal/app/sandbox/main.go
Normal 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")
|
||||
}
|
||||
@@ -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])
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
29
internal/app/wwctl/controller/add/main.go
Normal file
29
internal/app/wwctl/controller/add/main.go
Normal 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
|
||||
}
|
||||
23
internal/app/wwctl/controller/add/root.go
Normal file
23
internal/app/wwctl/controller/add/root.go
Normal 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
|
||||
}
|
||||
61
internal/app/wwctl/controller/delete/main.go
Normal file
61
internal/app/wwctl/controller/delete/main.go
Normal 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
|
||||
}
|
||||
23
internal/app/wwctl/controller/delete/root.go
Normal file
23
internal/app/wwctl/controller/delete/root.go
Normal 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
|
||||
}
|
||||
45
internal/app/wwctl/controller/list/main.go
Normal file
45
internal/app/wwctl/controller/list/main.go
Normal 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
|
||||
}
|
||||
23
internal/app/wwctl/controller/list/root.go
Normal file
23
internal/app/wwctl/controller/list/root.go
Normal 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
|
||||
}
|
||||
30
internal/app/wwctl/controller/root.go
Normal file
30
internal/app/wwctl/controller/root.go
Normal 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
|
||||
}
|
||||
94
internal/app/wwctl/controller/set/main.go
Normal file
94
internal/app/wwctl/controller/set/main.go
Normal 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
|
||||
}
|
||||
26
internal/app/wwctl/controller/set/root.go
Normal file
26
internal/app/wwctl/controller/set/root.go
Normal 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
|
||||
}
|
||||
@@ -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)
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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 ++
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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, ","))
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
}
|
||||
@@ -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()
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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")
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -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...), ","))
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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")
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -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")
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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()] ++
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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.
|
||||
|
||||
28
internal/app/wwctl/profile/add/main.go
Normal file
28
internal/app/wwctl/profile/add/main.go
Normal 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
|
||||
}
|
||||
20
internal/app/wwctl/profile/add/root.go
Normal file
20
internal/app/wwctl/profile/add/root.go
Normal 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
|
||||
}
|
||||
85
internal/app/wwctl/profile/delete/main.go
Normal file
85
internal/app/wwctl/profile/delete/main.go
Normal 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
|
||||
}
|
||||
20
internal/app/wwctl/profile/delete/root.go
Normal file
20
internal/app/wwctl/profile/delete/root.go
Normal 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
|
||||
}
|
||||
36
internal/app/wwctl/profile/list/main.go
Normal file
36
internal/app/wwctl/profile/list/main.go
Normal 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
|
||||
}
|
||||
20
internal/app/wwctl/profile/list/root.go
Normal file
20
internal/app/wwctl/profile/list/root.go
Normal 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
|
||||
}
|
||||
30
internal/app/wwctl/profile/root.go
Normal file
30
internal/app/wwctl/profile/root.go
Normal 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
|
||||
}
|
||||
164
internal/app/wwctl/profile/set/main.go
Normal file
164
internal/app/wwctl/profile/set/main.go
Normal 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
|
||||
}
|
||||
40
internal/app/wwctl/profile/set/root.go
Normal file
40
internal/app/wwctl/profile/set/root.go
Normal 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
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
|
||||
109
internal/app/wwctl/services/dhcp/main.go
Normal file
109
internal/app/wwctl/services/dhcp/main.go
Normal 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
|
||||
}
|
||||
23
internal/app/wwctl/services/dhcp/root.go
Normal file
23
internal/app/wwctl/services/dhcp/root.go
Normal 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
|
||||
}
|
||||
23
internal/app/wwctl/services/root.go
Normal file
23
internal/app/wwctl/services/root.go
Normal 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
|
||||
}
|
||||
@@ -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 {
|
||||
|
||||
@@ -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
|
||||
}
|
||||
@@ -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)")
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
277
internal/pkg/node/constructors.go
Normal file
277
internal/pkg/node/constructors.go
Normal 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
|
||||
}
|
||||
223
internal/pkg/node/datastructure.go
Normal file
223
internal/pkg/node/datastructure.go
Normal 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)
|
||||
}
|
||||
}
|
||||
115
internal/pkg/node/methods.go
Normal file
115
internal/pkg/node/methods.go
Normal 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
|
||||
}
|
||||
323
internal/pkg/node/modifiers.go
Normal file
323
internal/pkg/node/modifiers.go
Normal 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
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
44
internal/pkg/overlay/funcmap.go
Normal file
44
internal/pkg/overlay/funcmap.go
Normal 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")
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
@@ -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)
|
||||
|
||||
}
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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], "/", "_")
|
||||
}
|
||||
Reference in New Issue
Block a user