Added controllers, services, and lots of various optimizations and fixes

This commit is contained in:
Gregory Kurtzer
2020-11-30 23:07:42 -08:00
parent 210d0044a5
commit 4d752a67db
35 changed files with 1147 additions and 365 deletions

View File

@@ -22,6 +22,8 @@ sudo make install
``` ```
sudo ./wwctl profile set -K $(uname -r) -V docker://warewulf/centos-8 default sudo ./wwctl profile set -K $(uname -r) -V docker://warewulf/centos-8 default
sudo ./wwctl node add [node name]
sudo ./wwctl node set --netdev eth0 -I 192.168.1.10 -M 255.255.255.0 -G 192.168.1.1 -H aa:bb:cc:dd:ee:ff
``` ```

View File

@@ -1,4 +1,3 @@
allow booting; allow booting;
allow bootp; allow bootp;
ddns-update-style interim; ddns-update-style interim;
@@ -13,8 +12,6 @@ option ipxe.no-pxedhcp 1;
option architecture-type code 93 = unsigned integer 16; option architecture-type code 93 = unsigned integer 16;
if exists user-class and option user-class = "iPXE" { if exists user-class and option user-class = "iPXE" {
#filename "http://192.168.1.1/WW4/ipxe/${mac:hexhyp}";
#filename "http://192.168.1.1:9873/ipxe?hwaddr=${mac:hexhyp}";
filename "http://192.168.1.1:9873/ipxe/${mac:hexhyp}"; filename "http://192.168.1.1:9873/ipxe/${mac:hexhyp}";
} else { } else {
if option architecture-type = 00:0B { if option architecture-type = 00:0B {
@@ -32,23 +29,14 @@ if exists user-class and option user-class = "iPXE" {
} }
} }
subnet 192.168.1.0 netmask 255.255.255.0 { subnet {{.Ipaddr}} netmask {{.Netmask}} {
range 192.168.1.10 192.168.1.99; range {{.RangeStart}} {{.RangeEnd}};
next-server 192.168.1.1; next-server 192.168.1.1;
} }
{{range .Nodes}}
#subnet 192.168.1.0 netmask 255.255.255.0 { #host {{.Fqdn}} {
# not authoritative; # hardware ethernet {{.NetDevs.eth0.Hwaddr}}
# option subnet-mask 255.255.255.0; # filed-address {{.NetDevs.eth0.Ipaddr}}
#}
#group {
# host n0000_localdomain-eth0 {
# option host-name n0000;
# option domain-name "localdomain";
# hardware ethernet 00:0c:29:c3:bf:42;
# fixed-address 192.168.1.100;
# next-server 192.168.1.1;
# }
#} #}
{{end}}

View File

@@ -1,52 +1,87 @@
nodeprofiles: nodeprofiles:
default: default:
comment: "" comment: ""
vnfs: ""
kernel version: ""
kernel args: crashkernel=no quiet kernel args: crashkernel=no quiet
nodegroups:
default: control:
comment: This is the default group headnode01:
domain name: cluster01 comment: This is the first control system
profiles: ipaddr: 192.168.1.1
- default services:
nodes: warewulfd:
n0000: port: 9873
hostname: n0000 secure: true
netdevs: dhcp:
eth0: enabled: true
type: ethernet range start: 192.168.1.100
hwaddr: 00:0c:29:23:8b:48 range end: 192.168.1.250
ipaddr: 192.168.1.100 assign static: false
netmask: 255.255.255.0 config file: /etc/dhcp/dhcpd.conf
gateway: 192.168.1.1 start command: service dhcp start
ib0: restart command: killall dhcpd -HUP
type: infiniband enable command: chkconfig dhcp on
hwaddr: aa:bb:cc:dd:ee:a0 tftp:
ipaddr: 192.168.10.100 enabled: true
netmask: 255.255.255.0 tftproot: /var/lib/tftproot
n0001: start command: service tftp start
hostname: n0001 restart command: service tftp restart
ipmi ipaddr: x.x.x.x enable command: chkconfig tftp on
netdevs: nfs:
eth0: enabled: true
hwaddr: aa:bb:cc:dd:ee:b0 config file: /etc/exports
ipaddr: 192.168.1.101 exports:
netmask: 255.255.255.0 - /var/warewulf 192.168.1.1/255.255.255.0(ro,no_root_squash)
gateway: 192.168.1.1 - /home 192.168.1.1/255.255.255.0(rw,no_root_squash)
ib0: start command: service nfs start
hwaddr: aa:bb:cc:dd:ee:b1 restart command: service nfs restart
ipaddr: 192.168.10.100 enable command: chkconfig nfs on
netmask: 255.255.255.0 nodegroups:
group_1: default:
comment: This is the group 1 comment: This is the default group
domain name: group1 domain name: cluster01
profiles: profiles:
- default - default
nodes: nodes:
n0000: n0000:
hostname: n0000 hostname: n0000
netdevs: netdevs:
eth0: eth0:
hwaddr: aa:bb:cc:dd:ee:c0 type: ethernet
ipaddr: 192.168.2.100 hwaddr: 00:0c:29:23:8b:48
netmask: 255.255.255.0 ipaddr: 192.168.1.100
gateway: 192.168.2.1 netmask: 255.255.255.0
gateway: 192.168.1.1
ib0:
type: infiniband
hwaddr: aa:bb:cc:dd:ee:a0
ipaddr: 192.168.10.100
netmask: 255.255.255.0
n0001:
hostname: n0001
ipmi ipaddr: x.x.x.x
netdevs:
eth0:
hwaddr: aa:bb:cc:dd:ee:b0
ipaddr: 192.168.1.101
netmask: 255.255.255.0
gateway: 192.168.1.1
ib0:
hwaddr: aa:bb:cc:dd:ee:b1
ipaddr: 192.168.10.100
netmask: 255.255.255.0
group_1:
comment: This is the group 1
domain name: group1
profiles:
- default
nodes:
n0000:
hostname: n0000
netdevs:
eth0:
hwaddr: aa:bb:cc:dd:ee:c0
ipaddr: 192.168.2.100
netmask: 255.255.255.0
gateway: 192.168.2.1

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -34,9 +34,9 @@ func CobraRunE(cmd *cobra.Command, args []string) error {
} }
} }
} else { } else {
fmt.Printf("%-22s %-16s %s\n", "GROUP NAME", "DOMAINNAME", "PROFILES") fmt.Printf("%-22s %-16s %-16s %s\n", "GROUP NAME", "DOMAINNAME", "CONTROLLER", "PROFILES")
for _, g := range groups { for _, g := range groups {
fmt.Printf("%-22s %-16s %s\n", g.Id, g.DomainName, strings.Join(g.Profiles, ",")) fmt.Printf("%-22s %-16s %-16s %s\n", g.Id, g.DomainName, g.Cid, strings.Join(g.Profiles, ","))
} }
} }

View File

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

View File

@@ -11,10 +11,12 @@ var (
Args: cobra.MinimumNArgs(1), Args: cobra.MinimumNArgs(1),
} }
SetGroup string SetGroup string
SetController string
) )
func init() { 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. // GetRootCommand returns the root cobra.Command for the application.

View File

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

View File

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

View File

@@ -37,7 +37,7 @@ func CobraRunE(cmd *cobra.Command, args []string) error {
fmt.Printf("################################################################################\n") fmt.Printf("################################################################################\n")
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(), "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(), "Comment", node.Comment.Source(), node.Comment.String())
fmt.Printf("%-20s %-18s %8s: %s\n", node.Fqdn.Get(), "GroupName", node.GroupName.Source(), node.GroupName.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(), "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 (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(), "Profiles (Node)", "node", strings.Join(node.Profiles, ","))
@@ -93,7 +93,7 @@ func CobraRunE(cmd *cobra.Command, args []string) error {
fmt.Println(strings.Repeat("=", 120)) fmt.Println(strings.Repeat("=", 120))
for _, node := range nodes { for _, node := range nodes {
fmt.Printf("%-22s %-12s %-26s %-35s %s\n", node.Fqdn.Get(), node.GroupName.String(), node.KernelVersion.String(), node.Vnfs.String(), node.SystemOverlay.String() +"/"+ node.RuntimeOverlay.String()) 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 { } else {

View File

@@ -38,7 +38,7 @@ func init() {
baseCmd.PersistentFlags().StringVarP(&SetIpxe, "ipxe", "P", "", "Set the node's iPXE template 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(&SetRuntimeOverlay, "runtime", "R", "", "Set the node's runtime overlay")
baseCmd.PersistentFlags().StringVarP(&SetSystemOverlay, "system", "S", "", "Set the node's system 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(&SetIpmiIpaddr, "ipmi", "", "Set the node's IPMI address")
baseCmd.PersistentFlags().StringVar(&SetIpmiUsername, "ipmiuser", "", "Set the node's IPMI username") baseCmd.PersistentFlags().StringVar(&SetIpmiUsername, "ipmiuser", "", "Set the node's IPMI username")
baseCmd.PersistentFlags().StringVar(&SetIpmiPassword, "ipmipass", "", "Set the node's IPMI password") baseCmd.PersistentFlags().StringVar(&SetIpmiPassword, "ipmipass", "", "Set the node's IPMI password")
@@ -50,7 +50,7 @@ func init() {
baseCmd.PersistentFlags().StringVarP(&SetIpaddr, "ipaddr", "I", "", "Set the node's network device IP address") 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(&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(&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().BoolVar(&SetNetDevDel, "delete", false, "Delete the node's network device")
baseCmd.PersistentFlags().BoolVarP(&SetNodeAll, "all", "a", false, "Set all nodes") baseCmd.PersistentFlags().BoolVarP(&SetNodeAll, "all", "a", false, "Set all nodes")

View File

@@ -69,7 +69,6 @@ func CobraRunE(cmd *cobra.Command, args []string) error {
fmt.Fprintf(w, "\n") fmt.Fprintf(w, "\n")
} }
shasum1, err := util.ShaSumFile(overlayFile) shasum1, err := util.ShaSumFile(overlayFile)
if err != nil { if err != nil {
wwlog.Printf(wwlog.WARN, "Could not open overlay file for checksum: %s\n", err) 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") wwlog.Printf(wwlog.ERROR, "Editor process existed with non-zero\n")
os.Exit(1) 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) shasum2, err := util.ShaSumFile(overlayFile)
if err != nil { if err != nil {
@@ -126,4 +125,3 @@ func CobraRunE(cmd *cobra.Command, args []string) error {
return nil return nil
} }

View File

@@ -143,7 +143,7 @@ func CobraRunE(cmd *cobra.Command, args []string) error {
} }
if len(profiles) > 0 { if len(profiles) > 0 {
q := fmt.Sprintf("Are you sure you want to modify %d group(s)", len(profiles)) q := fmt.Sprintf("Are you sure you want to modify %d profile(s)", len(profiles))
prompt := promptui.Prompt{ prompt := promptui.Prompt{
Label: q, Label: q,

View File

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

View File

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

View File

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

View File

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

View File

@@ -30,78 +30,80 @@ func New() (nodeYaml, error) {
func (self *nodeYaml) FindAllNodes() ([]NodeInfo, error) { func (self *nodeYaml) FindAllNodes() ([]NodeInfo, error) {
var ret []NodeInfo var ret []NodeInfo
for groupname, group := range self.NodeGroups { for controllername, controller := range self.Controllers {
for nodename, node := range group.Nodes { for groupname, group := range controller.NodeGroups {
var n NodeInfo for nodename, node := range group.Nodes {
var allProfiles []string var n NodeInfo
var allProfiles []string
if node.Disabled == true || group.Disabled == true { if node.Disabled == true || group.Disabled == true {
wwlog.Printf(wwlog.VERBOSE, "Skipping disabled node: %s/%s\n", groupname, nodename) wwlog.Printf(wwlog.VERBOSE, "Skipping disabled node: %s/%s\n", groupname, nodename)
continue
}
n.Id.Set(nodename)
n.Gid.Set(groupname)
n.GroupName.Set(groupname)
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 continue
} }
n.DomainName.SetProfile(self.NodeProfiles[p].DomainName) n.Id.Set(nodename)
n.Vnfs.SetProfile(self.NodeProfiles[p].Vnfs) n.Gid.Set(groupname)
n.KernelVersion.SetProfile(self.NodeProfiles[p].KernelVersion) n.Cid.Set(controllername)
n.KernelArgs.SetProfile(self.NodeProfiles[p].KernelArgs) n.HostName.Set(node.Hostname)
n.Ipxe.SetProfile(self.NodeProfiles[p].Ipxe) n.IpmiIpaddr.Set(node.IpmiIpaddr)
n.IpmiUserName.SetProfile(self.NodeProfiles[p].IpmiUserName) n.DomainName.Set(node.DomainName)
n.IpmiPassword.SetProfile(self.NodeProfiles[p].IpmiPassword) n.Vnfs.Set(node.Vnfs)
n.SystemOverlay.SetProfile(self.NodeProfiles[p].SystemOverlay) n.KernelVersion.Set(node.KernelVersion)
n.RuntimeOverlay.SetProfile(self.NodeProfiles[p].RuntimeOverlay) 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)
} }
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)
} }
} }
@@ -111,25 +113,76 @@ func (self *nodeYaml) FindAllNodes() ([]NodeInfo, error) {
func (self *nodeYaml) FindAllGroups() ([]GroupInfo, error) { func (self *nodeYaml) FindAllGroups() ([]GroupInfo, error) {
var ret []GroupInfo var ret []GroupInfo
for groupname, group := range self.NodeGroups { for controllername, controller := range self.Controllers {
var g GroupInfo for groupname, group := range controller.NodeGroups {
var g GroupInfo
g.Id = groupname g.Id = groupname
g.DomainName = group.DomainName g.Cid = controllername
g.Comment = group.Comment g.DomainName = group.DomainName
g.Vnfs = group.Vnfs g.Comment = group.Comment
g.KernelVersion = group.KernelVersion g.Vnfs = group.Vnfs
g.KernelArgs = group.KernelArgs g.KernelVersion = group.KernelVersion
g.IpmiPassword = group.IpmiPassword g.KernelArgs = group.KernelArgs
g.IpmiUserName = group.IpmiUserName g.IpmiPassword = group.IpmiPassword
g.SystemOverlay = group.SystemOverlay g.IpmiUserName = group.IpmiUserName
g.RuntimeOverlay = group.RuntimeOverlay g.SystemOverlay = group.SystemOverlay
g.RuntimeOverlay = group.RuntimeOverlay
g.Profiles = group.Profiles 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 // TODO: Validate or die on all inputs
ret = append(ret, g) ret = append(ret, c)
} }
return ret, nil return ret, nil
} }
@@ -159,8 +212,6 @@ func (self *nodeYaml) FindAllProfiles() ([]ProfileInfo, error) {
return ret, nil return ret, nil
} }
func (self *nodeYaml) FindByHwaddr(hwa string) (NodeInfo, error) { func (self *nodeYaml) FindByHwaddr(hwa string) (NodeInfo, error) {
var ret NodeInfo var ret NodeInfo
@@ -193,13 +244,6 @@ func (self *nodeYaml) FindByIpaddr(ipaddr string) (NodeInfo, error) {
return ret, errors.New("No nodes found with IP Addr: " + ipaddr) return ret, errors.New("No nodes found with IP Addr: " + ipaddr)
} }
func (nodes *nodeYaml) SearchByName(search string) ([]NodeInfo, error) { func (nodes *nodeYaml) SearchByName(search string) ([]NodeInfo, error) {
var ret []NodeInfo var ret []NodeInfo

View File

@@ -6,127 +6,212 @@ import (
"os" "os"
) )
/******
* YAML data representations
******/
type nodeYaml struct { type nodeYaml struct {
NodeProfiles map[string]*ProfileConf NodeProfiles map[string]*ProfileConf
NodeGroups map[string]*GroupConf Controllers map[string]*ControllerConf `yaml:"control"`
} }
type ProfileConf struct { type ProfileConf struct {
Comment string `yaml:"comment"` Comment string `yaml:"comment"`
Vnfs string `yaml:"vnfs,omitempty"` Vnfs string `yaml:"vnfs,omitempty"`
Ipxe string `yaml:"ipxe template,omitempty"` Ipxe string `yaml:"ipxe template,omitempty"`
KernelVersion string `yaml:"kernel version,omitempty"` KernelVersion string `yaml:"kernel version,omitempty"`
KernelArgs string `yaml:"kernel args,omitempty"` KernelArgs string `yaml:"kernel args,omitempty"`
IpmiUserName string `yaml:"ipmi username,omitempty"` IpmiUserName string `yaml:"ipmi username,omitempty"`
IpmiPassword string `yaml:"ipmi password,omitempty"` IpmiPassword string `yaml:"ipmi password,omitempty"`
DomainName string `yaml:"domain name,omitempty"` DomainName string `yaml:"domain name,omitempty"`
RuntimeOverlay string `yaml:"runtime overlay files,omitempty"` RuntimeOverlay string `yaml:"runtime overlay files,omitempty"`
SystemOverlay string `yaml:"system 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 { type GroupConf struct {
Comment string `yaml:"comment"` Comment string `yaml:"comment"`
Disabled bool `yaml:"disabled,omitempty"` Disabled bool `yaml:"disabled,omitempty"`
DomainName string `yaml:"domain name"` DomainName string `yaml:"domain name"`
Vnfs string `yaml:"vnfs,omitempty"` Vnfs string `yaml:"vnfs,omitempty"`
Ipxe string `yaml:"ipxe template,omitempty"` Ipxe string `yaml:"ipxe template,omitempty"`
KernelVersion string `yaml:"kernel version,omitempty"` KernelVersion string `yaml:"kernel version,omitempty"`
KernelArgs string `yaml:"kernel args,omitempty"` KernelArgs string `yaml:"kernel args,omitempty"`
IpmiUserName string `yaml:"ipmi username,omitempty"` IpmiUserName string `yaml:"ipmi username,omitempty"`
IpmiPassword string `yaml:"ipmi password,omitempty"` IpmiPassword string `yaml:"ipmi password,omitempty"`
RuntimeOverlay string `yaml:"runtime overlay files,omitempty"` RuntimeOverlay string `yaml:"runtime overlay files,omitempty"`
SystemOverlay string `yaml:"system overlay files,omitempty"` SystemOverlay string `yaml:"system overlay files,omitempty"`
Profiles []string `yaml:"profiles,omitempty"` Profiles []string `yaml:"profiles,omitempty"`
Nodes map[string]*NodeConf Nodes map[string]*NodeConf
} }
type NodeConf struct { type NodeConf struct {
Comment string `yaml:"comment,omitempty"` Comment string `yaml:"comment,omitempty"`
Disabled bool `yaml:"disabled,omitempty"` Disabled bool `yaml:"disabled,omitempty"`
Hostname string `yaml:"hostname,omitempty"` Hostname string `yaml:"hostname,omitempty"`
DomainName string `yaml:"domain name,omitempty"` DomainName string `yaml:"domain name,omitempty"`
Vnfs string `yaml:"vnfs,omitempty"` Vnfs string `yaml:"vnfs,omitempty"`
Ipxe string `yaml:"ipxe template,omitempty"` Ipxe string `yaml:"ipxe template,omitempty"`
KernelVersion string `yaml:"kernel version,omitempty"` KernelVersion string `yaml:"kernel version,omitempty"`
KernelArgs string `yaml:"kernel args,omitempty"` KernelArgs string `yaml:"kernel args,omitempty"`
IpmiUserName string `yaml:"ipmi username,omitempty"` IpmiUserName string `yaml:"ipmi username,omitempty"`
IpmiPassword string `yaml:"ipmi password,omitempty"` IpmiPassword string `yaml:"ipmi password,omitempty"`
IpmiIpaddr string `yaml:"ipmi ipaddr,omitempty"` IpmiIpaddr string `yaml:"ipmi ipaddr,omitempty"`
RuntimeOverlay string `yaml:"runtime overlay files,omitempty"` RuntimeOverlay string `yaml:"runtime overlay files,omitempty"`
SystemOverlay string `yaml:"system overlay files,omitempty"` SystemOverlay string `yaml:"system overlay files,omitempty"`
Profiles []string `yaml:"profiles,omitempty"` Profiles []string `yaml:"profiles,omitempty"`
NetDevs map[string]*NetDevs NetDevs map[string]*NetDevs
} }
type NetDevs struct { type NetDevs struct {
Type string `yaml:"type,omitempty"` Type string `yaml:"type,omitempty"`
Hwaddr string Hwaddr string
Ipaddr string Ipaddr string
Netmask string Netmask string
Gateway string `yaml:"gateway,omitempty"` Gateway string `yaml:"gateway,omitempty"`
} }
/******
* Code internal data representations
******/
type NodeInfoEntry struct { type NodeInfoEntry struct {
value string value string
profile string profile string
group string group string
def string controller string
def string
} }
type NodeInfo struct { type NodeInfo struct {
Id NodeInfoEntry Id NodeInfoEntry
Gid NodeInfoEntry Gid NodeInfoEntry
Uid NodeInfoEntry Cid NodeInfoEntry
Comment NodeInfoEntry Comment NodeInfoEntry
GroupName NodeInfoEntry HostName NodeInfoEntry
HostName NodeInfoEntry Fqdn NodeInfoEntry
Fqdn NodeInfoEntry DomainName NodeInfoEntry
DomainName NodeInfoEntry Vnfs NodeInfoEntry
Vnfs NodeInfoEntry Ipxe NodeInfoEntry
Ipxe NodeInfoEntry KernelVersion NodeInfoEntry
KernelVersion NodeInfoEntry KernelArgs NodeInfoEntry
KernelArgs NodeInfoEntry IpmiIpaddr NodeInfoEntry
IpmiIpaddr NodeInfoEntry IpmiUserName NodeInfoEntry
IpmiUserName NodeInfoEntry IpmiPassword NodeInfoEntry
IpmiPassword NodeInfoEntry RuntimeOverlay NodeInfoEntry
RuntimeOverlay NodeInfoEntry SystemOverlay NodeInfoEntry
SystemOverlay NodeInfoEntry Profiles []string
Profiles []string GroupProfiles []string
GroupProfiles []string NetDevs map[string]*NetDevs
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 { type GroupInfo struct {
Id string Id string
Comment string Cid string
Vnfs string Comment string
Ipxe string Vnfs string
KernelVersion string Ipxe string
KernelArgs string KernelVersion string
IpmiUserName string KernelArgs string
IpmiPassword string IpmiUserName string
DomainName string IpmiPassword string
RuntimeOverlay string DomainName string
SystemOverlay string RuntimeOverlay string
Profiles []string SystemOverlay string
Profiles []string
} }
type ProfileInfo struct { type ProfileInfo struct {
Id string Id string
Comment string Comment string
Vnfs string Vnfs string
Ipxe string Ipxe string
KernelVersion string KernelVersion string
KernelArgs string KernelArgs string
IpmiUserName string IpmiUserName string
IpmiPassword string IpmiPassword string
DomainName string DomainName string
RuntimeOverlay string RuntimeOverlay string
SystemOverlay string SystemOverlay string
} }
const ConfigFile = "/etc/warewulf/nodes.conf" const ConfigFile = "/etc/warewulf/nodes.conf"
func init() { func init() {

View File

@@ -14,6 +14,9 @@ func (self *NodeInfoEntry) String() string {
if self.profile != "" { if self.profile != "" {
return self.profile return self.profile
} }
if self.controller != "" {
return self.controller
}
if self.def != "" { if self.def != "" {
return self.def return self.def
} }
@@ -30,6 +33,9 @@ func (self *NodeInfoEntry) Source() string {
if self.profile != "" { if self.profile != "" {
return "profile" return "profile"
} }
if self.controller != "" {
return "controller"
}
if self.def != "" { if self.def != "" {
return "default" return "default"
} }
@@ -46,6 +52,9 @@ func (self *NodeInfoEntry) Get() string {
if self.profile != "" { if self.profile != "" {
return self.profile return self.profile
} }
if self.controller != "" {
return self.controller
}
if self.def != "" { if self.def != "" {
return self.def return self.def
} }
@@ -81,6 +90,13 @@ func (self *NodeInfoEntry) SetProfile(value string) {
self.profile = value self.profile = value
} }
func (self *NodeInfoEntry) SetController(value string) {
if value == "" {
return
}
self.controller = value
}
func (self *NodeInfoEntry) Set(value string) { func (self *NodeInfoEntry) Set(value string) {
if value == "" { if value == "" {
return return

View File

@@ -14,64 +14,79 @@ import (
* *
****/ ****/
func (self *nodeYaml) AddNode(groupID string, nodeID string) error { func (self *nodeYaml) AddNode(controllerID string, groupID string, nodeID string) error {
var node NodeConf var node NodeConf
wwlog.Printf(wwlog.VERBOSE, "Adding new node: %s/%s\n", groupID, nodeID) wwlog.Printf(wwlog.VERBOSE, "Adding new node: %s/%s\n", groupID, nodeID)
if _, ok := self.NodeGroups[groupID]; !ok { 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) return errors.New("Group does not exist: " + groupID)
} }
if _, ok := self.NodeGroups[groupID].Nodes[groupID]; ok { if _, ok := self.Controllers[controllerID].NodeGroups[groupID].Nodes[groupID]; ok {
return errors.New("Nodename already exists in group: " + nodeID) return errors.New("Nodename already exists in group: " + nodeID)
} }
self.NodeGroups[groupID].Nodes[nodeID] = &node self.Controllers[controllerID].NodeGroups[groupID].Nodes[nodeID] = &node
self.NodeGroups[groupID].Nodes[nodeID].Hostname = nodeID self.Controllers[controllerID].NodeGroups[groupID].Nodes[nodeID].Hostname = nodeID
return nil return nil
} }
func (self *nodeYaml) DelNode(groupID string, nodeID string) error { func (self *nodeYaml) DelNode(controllerID string, groupID string, nodeID string) error {
if _, ok := self.NodeGroups[groupID]; !ok { if _, ok := self.Controllers[controllerID]; ! ok {
return errors.New("Group '" + groupID + "' was not found") return errors.New("Controller does not exist: " + controllerID)
} }
if _, ok := self.NodeGroups[groupID].Nodes[nodeID]; !ok {
return errors.New("Node '" + nodeID + "' was not found in group '" + groupID + "'") 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) wwlog.Printf(wwlog.VERBOSE, "Deleting node network device: %s/%s\n", groupID, nodeID)
delete(self.NodeGroups[groupID].Nodes, nodeID) delete(self.Controllers[controllerID].NodeGroups[groupID].Nodes, nodeID)
return nil return nil
} }
func(self *nodeYaml) NodeUpdate(node NodeInfo) error { func(self *nodeYaml) NodeUpdate(node NodeInfo) error {
controllerID := node.Cid.Get()
groupID := node.Gid.Get() groupID := node.Gid.Get()
nodeID := node.Id.Get() nodeID := node.Id.Get()
if _, ok := self.NodeGroups[groupID]; !ok { if _, ok := self.Controllers[controllerID]; ! ok {
return errors.New("Group '" + groupID + "' was not found") return errors.New("Controller does not exist: " + controllerID)
}
if _, ok := self.NodeGroups[groupID].Nodes[nodeID]; !ok {
return errors.New("Node '" + nodeID + "' was not found in group '" + groupID + "'")
} }
self.NodeGroups[groupID].Nodes[nodeID].Hostname = node.HostName.GetReal() if _, ok := self.Controllers[controllerID].NodeGroups[groupID]; ! ok {
self.NodeGroups[groupID].Nodes[nodeID].Vnfs = node.Vnfs.GetReal() return errors.New("Group does not exist: " + groupID)
self.NodeGroups[groupID].Nodes[nodeID].DomainName = node.DomainName.GetReal() }
self.NodeGroups[groupID].Nodes[nodeID].Ipxe = node.Ipxe.GetReal()
self.NodeGroups[groupID].Nodes[nodeID].KernelVersion = node.KernelVersion.GetReal() if _, ok := self.Controllers[controllerID].NodeGroups[groupID].Nodes[groupID]; ! ok {
self.NodeGroups[groupID].Nodes[nodeID].KernelArgs = node.KernelArgs.GetReal() return errors.New("Nodename does not exist in group: " + nodeID)
self.NodeGroups[groupID].Nodes[nodeID].IpmiIpaddr = node.IpmiIpaddr.GetReal() }
self.NodeGroups[groupID].Nodes[nodeID].IpmiUserName = node.IpmiUserName.GetReal()
self.NodeGroups[groupID].Nodes[nodeID].IpmiPassword = node.IpmiPassword.GetReal() self.Controllers[controllerID].NodeGroups[groupID].Nodes[nodeID].Hostname = node.HostName.GetReal()
self.NodeGroups[groupID].Nodes[nodeID].RuntimeOverlay = node.RuntimeOverlay.GetReal() self.Controllers[controllerID].NodeGroups[groupID].Nodes[nodeID].Vnfs = node.Vnfs.GetReal()
self.NodeGroups[groupID].Nodes[nodeID].SystemOverlay = node.SystemOverlay.GetReal() self.Controllers[controllerID].NodeGroups[groupID].Nodes[nodeID].DomainName = node.DomainName.GetReal()
self.NodeGroups[groupID].Nodes[nodeID].Profiles = node.Profiles self.Controllers[controllerID].NodeGroups[groupID].Nodes[nodeID].Ipxe = node.Ipxe.GetReal()
self.NodeGroups[groupID].Nodes[nodeID].NetDevs = node.NetDevs 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 return nil
} }
@@ -84,51 +99,140 @@ func(self *nodeYaml) NodeUpdate(node NodeInfo) error {
* *
****/ ****/
func (self *nodeYaml) AddGroup(groupID string) error { func (self *nodeYaml) AddGroup(controllerID string, groupID string) error {
var group GroupConf var group GroupConf
wwlog.Printf(wwlog.VERBOSE, "Adding new group: %s/%s\n", groupID) wwlog.Printf(wwlog.VERBOSE, "Adding new group: %s/%s\n", groupID)
if _, ok := self.NodeGroups[groupID]; ok { if _, ok := self.Controllers[controllerID]; ! ok {
return errors.New("Group name already exists: " + groupID) return errors.New("Controller does not exist: " + controllerID)
} }
self.NodeGroups[groupID] = &group if _, ok := self.Controllers[controllerID].NodeGroups[groupID]; ok {
self.NodeGroups[groupID].DomainName = groupID return errors.New("Group already exists: " + groupID)
self.NodeGroups[groupID].Profiles = []string{"default"} }
self.Controllers[controllerID].NodeGroups[groupID] = &group
self.Controllers[controllerID].NodeGroups[groupID].DomainName = groupID
self.Controllers[controllerID].NodeGroups[groupID].Profiles = []string{"default"}
return nil return nil
} }
func (self *nodeYaml) DelGroup(groupID string) error { func (self *nodeYaml) DelGroup(controllerID string, groupID string) error {
if _, ok := self.NodeGroups[groupID]; !ok {
return errors.New("Group '" + groupID + "' was not found") 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) wwlog.Printf(wwlog.VERBOSE, "Deleting group: %s\n", groupID)
delete(self.NodeGroups, groupID) delete(self.Controllers[controllerID].NodeGroups, groupID)
return nil return nil
} }
func(self *nodeYaml) GroupUpdate(group GroupInfo) error { func(self *nodeYaml) GroupUpdate(group GroupInfo) error {
controllerID := group.Cid
groupID := group.Id groupID := group.Id
if _, ok := self.NodeGroups[groupID]; !ok { if _, ok := self.Controllers[controllerID]; ! ok {
return errors.New("Group '" + groupID + "' was not found") return errors.New("Controller does not exist: " + controllerID)
} }
self.NodeGroups[groupID].DomainName = group.DomainName if _, ok := self.Controllers[controllerID].NodeGroups[groupID]; ! ok {
self.NodeGroups[groupID].Vnfs = group.Vnfs return errors.New("Group does not exist: " + groupID)
self.NodeGroups[groupID].KernelVersion = group.KernelVersion }
self.NodeGroups[groupID].KernelArgs = group.KernelArgs
self.NodeGroups[groupID].Ipxe = group.Ipxe self.Controllers[controllerID].NodeGroups[groupID].DomainName = group.DomainName
self.NodeGroups[groupID].IpmiUserName = group.IpmiUserName self.Controllers[controllerID].NodeGroups[groupID].Vnfs = group.Vnfs
self.NodeGroups[groupID].IpmiPassword = group.IpmiPassword self.Controllers[controllerID].NodeGroups[groupID].KernelVersion = group.KernelVersion
self.NodeGroups[groupID].RuntimeOverlay = group.RuntimeOverlay self.Controllers[controllerID].NodeGroups[groupID].KernelArgs = group.KernelArgs
self.NodeGroups[groupID].SystemOverlay = group.SystemOverlay self.Controllers[controllerID].NodeGroups[groupID].Ipxe = group.Ipxe
self.NodeGroups[groupID].Profiles = group.Profiles 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 return nil
} }

View File

@@ -18,11 +18,14 @@ import (
) )
type TemplateStruct struct { type TemplateStruct struct {
Fqdn string Self struct {
Hostname string Fqdn string
Groupname string Hostname string
Vnfs string GroupName string
Netdev map[string]*node.NetDevs Vnfs string
NetDevs map[string]*node.NetDevs
}
AllNodes []node.NodeInfo
} }
func BuildSystemOverlay(nodeList []node.NodeInfo) error { func BuildSystemOverlay(nodeList []node.NodeInfo) error {
@@ -49,9 +52,6 @@ func RuntimeOverlayInit(name string) error {
return overlayInit(name, "runtime") return overlayInit(name, "runtime")
} }
func findAllOverlays(overlayType string) ([]string, error) { func findAllOverlays(overlayType string) ([]string, error) {
config := config.New() config := config.New()
var ret []string var ret []string
@@ -83,7 +83,6 @@ func findAllOverlays(overlayType string) ([]string, error) {
return ret, nil return ret, nil
} }
func overlayInit(name string, overlayType string) error { func overlayInit(name string, overlayType string) error {
var path string var path string
config := config.New() config := config.New()
@@ -100,7 +99,7 @@ func overlayInit(name string, overlayType string) error {
} }
if util.IsDir(path) == true { if util.IsDir(path) == true {
return errors.New("Overlay already exists: "+name) return errors.New("Overlay already exists: " + name)
} }
err := os.MkdirAll(path, 0755) err := os.MkdirAll(path, 0755)
@@ -108,13 +107,10 @@ func overlayInit(name string, overlayType string) error {
return err return err
} }
func buildOverlay(nodeList []node.NodeInfo, overlayType string) error { func buildOverlay(nodeList []node.NodeInfo, overlayType string) error {
config := config.New() config := config.New()
nodeDB, _ := node.New()
allNodes, _ := nodeDB.FindAllNodes()
for _, node := range nodeList { for _, node := range nodeList {
var t TemplateStruct var t TemplateStruct
@@ -134,11 +130,12 @@ func buildOverlay(nodeList []node.NodeInfo, overlayType string) error {
wwlog.Printf(wwlog.DEBUG, "Processing overlay for node: %s\n", node.Fqdn.Get()) wwlog.Printf(wwlog.DEBUG, "Processing overlay for node: %s\n", node.Fqdn.Get())
t.Fqdn = node.Fqdn.Get() t.Self.Fqdn = node.Fqdn.Get()
t.Hostname = node.HostName.Get() t.Self.Hostname = node.HostName.Get()
t.Groupname = node.GroupName.Get() t.Self.GroupName = node.Gid.Get()
t.Vnfs = node.Vnfs.Get() t.Self.Vnfs = node.Vnfs.Get()
t.Netdev = node.NetDevs t.Self.NetDevs = node.NetDevs
t.AllNodes = allNodes
if overlayType == "runtime" && node.RuntimeOverlay.Defined() == false { if overlayType == "runtime" && node.RuntimeOverlay.Defined() == false {
wwlog.Printf(wwlog.WARN, "Undefined runtime overlay, skipping node: %s\n", node.Fqdn.Get()) wwlog.Printf(wwlog.WARN, "Undefined runtime overlay, skipping node: %s\n", node.Fqdn.Get())
@@ -230,7 +227,6 @@ func buildOverlay(nodeList []node.NodeInfo, overlayType string) error {
return nil return nil
}) })
wwlog.Printf(wwlog.VERBOSE, "Finished generating overlay directory for: %s\n", node.Fqdn.Get()) 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) cmd := fmt.Sprintf("cd \"%s\"; find . | cpio --quiet -o -H newc -F \"%s\"", tmpDir, OverlayFile)

View File

@@ -59,9 +59,9 @@ func CleanName(source string) string {
tmp = source tmp = source
} }
tmp = strings.ReplaceAll(tmp, "://", "-") tmp = strings.ReplaceAll(tmp, "://", ":")
tmp = strings.ReplaceAll(tmp, "/", ".") tmp = strings.ReplaceAll(tmp, "/", "-")
tmp = strings.ReplaceAll(tmp, ":", "-") tmp = strings.ReplaceAll(tmp, ":", ":")
return tmp return tmp
} }
@@ -75,6 +75,10 @@ func New(source string) (VnfsObject, error) {
return ret, errors.New("Called vnfs.Load() without a VNFS name") return ret, errors.New("Called vnfs.Load() without a VNFS name")
} }
if util.IsFile(ret.Config) {
return Load(source)
}
pathFriendlyName := CleanName(source) pathFriendlyName := CleanName(source)
if strings.HasPrefix(source, "/") == true { if strings.HasPrefix(source, "/") == true {
@@ -92,10 +96,6 @@ func New(source string) (VnfsObject, error) {
ret.Image = config.VnfsImage(pathFriendlyName) ret.Image = config.VnfsImage(pathFriendlyName)
ret.Config = path.Join(config.VnfsImageDir(pathFriendlyName), "config.yaml") ret.Config = path.Join(config.VnfsImageDir(pathFriendlyName), "config.yaml")
if util.IsFile(ret.Config) {
return Load(source)
}
return ret, nil return ret, nil
} }