diff --git a/README.md b/README.md index 80ac5a2d..d334bdf3 100644 --- a/README.md +++ b/README.md @@ -22,6 +22,8 @@ sudo make install ``` 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 ``` diff --git a/etc/dhcpd.conf b/etc/dhcp/default-dhcpd.conf similarity index 66% rename from etc/dhcpd.conf rename to etc/dhcp/default-dhcpd.conf index 0c3349fc..ea5e9f72 100644 --- a/etc/dhcpd.conf +++ b/etc/dhcp/default-dhcpd.conf @@ -1,4 +1,3 @@ - allow booting; allow bootp; ddns-update-style interim; @@ -13,8 +12,6 @@ option ipxe.no-pxedhcp 1; option architecture-type code 93 = unsigned integer 16; 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}"; } else { 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 { - range 192.168.1.10 192.168.1.99; +subnet {{.Ipaddr}} netmask {{.Netmask}} { + range {{.RangeStart}} {{.RangeEnd}}; next-server 192.168.1.1; -} +} - -#subnet 192.168.1.0 netmask 255.255.255.0 { -# not authoritative; -# option subnet-mask 255.255.255.0; -#} - -#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; -# } +{{range .Nodes}} +#host {{.Fqdn}} { +# hardware ethernet {{.NetDevs.eth0.Hwaddr}} +# filed-address {{.NetDevs.eth0.Ipaddr}} #} +{{end}} diff --git a/etc/nodes.conf b/etc/nodes.conf index e28002f1..444d8364 100644 --- a/etc/nodes.conf +++ b/etc/nodes.conf @@ -1,52 +1,87 @@ nodeprofiles: default: comment: "" + vnfs: "" + kernel version: "" kernel args: crashkernel=no quiet -nodegroups: - default: - comment: This is the default group - domain name: cluster01 - profiles: - - default - nodes: - n0000: - hostname: n0000 - netdevs: - eth0: - type: ethernet - hwaddr: 00:0c:29:23:8b:48 - ipaddr: 192.168.1.100 - 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 + +control: + headnode01: + comment: This is the first control system + ipaddr: 192.168.1.1 + services: + warewulfd: + port: 9873 + secure: true + dhcp: + enabled: true + range start: 192.168.1.100 + range end: 192.168.1.250 + assign static: false + config file: /etc/dhcp/dhcpd.conf + start command: service dhcp start + restart command: killall dhcpd -HUP + enable command: chkconfig dhcp on + tftp: + enabled: true + tftproot: /var/lib/tftproot + start command: service tftp start + restart command: service tftp restart + enable command: chkconfig tftp on + nfs: + enabled: true + config file: /etc/exports + exports: + - /var/warewulf 192.168.1.1/255.255.255.0(ro,no_root_squash) + - /home 192.168.1.1/255.255.255.0(rw,no_root_squash) + start command: service nfs start + restart command: service nfs restart + enable command: chkconfig nfs on + nodegroups: + default: + comment: This is the default group + domain name: cluster01 + profiles: + - default + nodes: + n0000: + hostname: n0000 + netdevs: + eth0: + type: ethernet + hwaddr: 00:0c:29:23:8b:48 + ipaddr: 192.168.1.100 + 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 diff --git a/internal/app/wwctl/controller/add/main.go b/internal/app/wwctl/controller/add/main.go new file mode 100644 index 00000000..f7231a4a --- /dev/null +++ b/internal/app/wwctl/controller/add/main.go @@ -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 +} \ No newline at end of file diff --git a/internal/app/wwctl/controller/add/root.go b/internal/app/wwctl/controller/add/root.go new file mode 100644 index 00000000..f26c860d --- /dev/null +++ b/internal/app/wwctl/controller/add/root.go @@ -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 +} diff --git a/internal/app/wwctl/controller/delete/main.go b/internal/app/wwctl/controller/delete/main.go new file mode 100644 index 00000000..4939940a --- /dev/null +++ b/internal/app/wwctl/controller/delete/main.go @@ -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 +} \ No newline at end of file diff --git a/internal/app/wwctl/controller/delete/root.go b/internal/app/wwctl/controller/delete/root.go new file mode 100644 index 00000000..0fc4fdcc --- /dev/null +++ b/internal/app/wwctl/controller/delete/root.go @@ -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 +} diff --git a/internal/app/wwctl/controller/list/main.go b/internal/app/wwctl/controller/list/main.go new file mode 100644 index 00000000..ff2e1396 --- /dev/null +++ b/internal/app/wwctl/controller/list/main.go @@ -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 +} \ No newline at end of file diff --git a/internal/app/wwctl/controller/list/root.go b/internal/app/wwctl/controller/list/root.go new file mode 100644 index 00000000..583c8fed --- /dev/null +++ b/internal/app/wwctl/controller/list/root.go @@ -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 +} diff --git a/internal/app/wwctl/controller/root.go b/internal/app/wwctl/controller/root.go new file mode 100644 index 00000000..31e100f5 --- /dev/null +++ b/internal/app/wwctl/controller/root.go @@ -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 +} diff --git a/internal/app/wwctl/controller/set/main.go b/internal/app/wwctl/controller/set/main.go new file mode 100644 index 00000000..4740acfe --- /dev/null +++ b/internal/app/wwctl/controller/set/main.go @@ -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 +} diff --git a/internal/app/wwctl/controller/set/root.go b/internal/app/wwctl/controller/set/root.go new file mode 100644 index 00000000..5f1b5499 --- /dev/null +++ b/internal/app/wwctl/controller/set/root.go @@ -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 +} diff --git a/internal/app/wwctl/group/add/main.go b/internal/app/wwctl/group/add/main.go index ab092f67..8b4bdadb 100644 --- a/internal/app/wwctl/group/add/main.go +++ b/internal/app/wwctl/group/add/main.go @@ -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) diff --git a/internal/app/wwctl/group/add/root.go b/internal/app/wwctl/group/add/root.go index 35070791..972e1fe0 100644 --- a/internal/app/wwctl/group/add/root.go +++ b/internal/app/wwctl/group/add/root.go @@ -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. diff --git a/internal/app/wwctl/group/delete/main.go b/internal/app/wwctl/group/delete/main.go index 71ee3fd4..5e3120c5 100644 --- a/internal/app/wwctl/group/delete/main.go +++ b/internal/app/wwctl/group/delete/main.go @@ -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.String() == g { + if n.Gid.Get() == g { numNodes ++ } } diff --git a/internal/app/wwctl/group/delete/root.go b/internal/app/wwctl/group/delete/root.go index a4a58522..bb343acd 100644 --- a/internal/app/wwctl/group/delete/root.go +++ b/internal/app/wwctl/group/delete/root.go @@ -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. diff --git a/internal/app/wwctl/group/list/main.go b/internal/app/wwctl/group/list/main.go index 0d5f88e1..cbe06514 100644 --- a/internal/app/wwctl/group/list/main.go +++ b/internal/app/wwctl/group/list/main.go @@ -34,9 +34,9 @@ func CobraRunE(cmd *cobra.Command, args []string) error { } } } 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 { - 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, ",")) } } diff --git a/internal/app/wwctl/node/add/main.go b/internal/app/wwctl/node/add/main.go index ad4d3a49..232ee268 100644 --- a/internal/app/wwctl/node/add/main.go +++ b/internal/app/wwctl/node/add/main.go @@ -16,7 +16,7 @@ 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) diff --git a/internal/app/wwctl/node/add/root.go b/internal/app/wwctl/node/add/root.go index b95a8b90..e394fa72 100644 --- a/internal/app/wwctl/node/add/root.go +++ b/internal/app/wwctl/node/add/root.go @@ -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. diff --git a/internal/app/wwctl/node/delete/main.go b/internal/app/wwctl/node/delete/main.go index f036e7c4..e20ea7f9 100644 --- a/internal/app/wwctl/node/delete/main.go +++ b/internal/app/wwctl/node/delete/main.go @@ -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.String() { - 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.String(), n.Id.String()) + err := nodeDB.DelNode(n.Cid.Get(), n.Gid.Get(), n.Id.Get()) if err != nil { wwlog.Printf(wwlog.ERROR, "%s\n", err) } else { diff --git a/internal/app/wwctl/node/delete/root.go b/internal/app/wwctl/node/delete/root.go index ded732bf..9a7b5a7d 100644 --- a/internal/app/wwctl/node/delete/root.go +++ b/internal/app/wwctl/node/delete/root.go @@ -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") } diff --git a/internal/app/wwctl/node/list/main.go b/internal/app/wwctl/node/list/main.go index 921e8832..ff449667 100644 --- a/internal/app/wwctl/node/list/main.go +++ b/internal/app/wwctl/node/list/main.go @@ -37,7 +37,7 @@ func CobraRunE(cmd *cobra.Command, args []string) error { 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(), "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(), "Profiles (Group)", "group", strings.Join(node.GroupProfiles, ",")) 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)) 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 { diff --git a/internal/app/wwctl/node/set/root.go b/internal/app/wwctl/node/set/root.go index 937b6025..2c5a429f 100644 --- a/internal/app/wwctl/node/set/root.go +++ b/internal/app/wwctl/node/set/root.go @@ -38,7 +38,7 @@ 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") @@ -50,7 +50,7 @@ func init() { 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") diff --git a/internal/app/wwctl/overlay/edit/main.go b/internal/app/wwctl/overlay/edit/main.go index 836c96fe..89e08d27 100644 --- a/internal/app/wwctl/overlay/edit/main.go +++ b/internal/app/wwctl/overlay/edit/main.go @@ -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 { @@ -126,4 +125,3 @@ func CobraRunE(cmd *cobra.Command, args []string) error { return nil } - diff --git a/internal/app/wwctl/profile/set/main.go b/internal/app/wwctl/profile/set/main.go index 548b53c2..8a95673a 100644 --- a/internal/app/wwctl/profile/set/main.go +++ b/internal/app/wwctl/profile/set/main.go @@ -143,7 +143,7 @@ func CobraRunE(cmd *cobra.Command, args []string) error { } 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{ Label: q, diff --git a/internal/app/wwctl/root.go b/internal/app/wwctl/root.go index ee52e7dd..05f732f3 100644 --- a/internal/app/wwctl/root.go +++ b/internal/app/wwctl/root.go @@ -1,11 +1,13 @@ package wwctl import ( + "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" @@ -14,26 +16,29 @@ import ( 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(overlay.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()) } @@ -51,4 +56,4 @@ func rootPersistentPreRunE(cmd *cobra.Command, args []string) error { wwlog.SetLevel(wwlog.INFO) } return nil -} \ No newline at end of file +} diff --git a/internal/app/wwctl/services/dhcp/main.go b/internal/app/wwctl/services/dhcp/main.go new file mode 100644 index 00000000..88d9b7e5 --- /dev/null +++ b/internal/app/wwctl/services/dhcp/main.go @@ -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 +} diff --git a/internal/app/wwctl/services/dhcp/root.go b/internal/app/wwctl/services/dhcp/root.go new file mode 100644 index 00000000..189f85db --- /dev/null +++ b/internal/app/wwctl/services/dhcp/root.go @@ -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 +} diff --git a/internal/app/wwctl/services/root.go b/internal/app/wwctl/services/root.go new file mode 100644 index 00000000..fa6a5c9b --- /dev/null +++ b/internal/app/wwctl/services/root.go @@ -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 +} diff --git a/internal/pkg/node/constructors.go b/internal/pkg/node/constructors.go index 9b143f94..5ac16bd2 100644 --- a/internal/pkg/node/constructors.go +++ b/internal/pkg/node/constructors.go @@ -30,78 +30,80 @@ func New() (nodeYaml, error) { func (self *nodeYaml) FindAllNodes() ([]NodeInfo, error) { var ret []NodeInfo - for groupname, group := range self.NodeGroups { - for nodename, node := range group.Nodes { - var n NodeInfo - var allProfiles []string + 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.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) + if node.Disabled == true || group.Disabled == true { + wwlog.Printf(wwlog.VERBOSE, "Skipping disabled node: %s/%s\n", groupname, nodename) 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) + 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) } - - 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) { var ret []GroupInfo - for groupname, group := range self.NodeGroups { - var g GroupInfo + for controllername, controller := range self.Controllers { + for groupname, group := range controller.NodeGroups { + var g GroupInfo - g.Id = groupname - 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.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 + 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, g) + ret = append(ret, c) } return ret, nil } @@ -159,8 +212,6 @@ func (self *nodeYaml) FindAllProfiles() ([]ProfileInfo, error) { return ret, nil } - - func (self *nodeYaml) FindByHwaddr(hwa string) (NodeInfo, error) { 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) } - - - - - - - func (nodes *nodeYaml) SearchByName(search string) ([]NodeInfo, error) { var ret []NodeInfo diff --git a/internal/pkg/node/datastructure.go b/internal/pkg/node/datastructure.go index 7e23a72e..fed2145c 100644 --- a/internal/pkg/node/datastructure.go +++ b/internal/pkg/node/datastructure.go @@ -6,127 +6,212 @@ import ( "os" ) +/****** + * YAML data representations + ******/ + type nodeYaml struct { - NodeProfiles map[string]*ProfileConf - NodeGroups map[string]*GroupConf + 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"` + 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 + 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 + 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"` + 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 - def string + value string + profile string + group string + controller string + def string } type NodeInfo struct { - Id NodeInfoEntry - Gid NodeInfoEntry - Uid NodeInfoEntry - Comment NodeInfoEntry - GroupName 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 + 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 - Comment string - Vnfs string - Ipxe string - KernelVersion string - KernelArgs string - IpmiUserName string - IpmiPassword string - DomainName string - RuntimeOverlay string - SystemOverlay string - Profiles []string + 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 + 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() { diff --git a/internal/pkg/node/methods.go b/internal/pkg/node/methods.go index 8ccbb6f5..011b9026 100644 --- a/internal/pkg/node/methods.go +++ b/internal/pkg/node/methods.go @@ -14,6 +14,9 @@ func (self *NodeInfoEntry) String() string { if self.profile != "" { return self.profile } + if self.controller != "" { + return self.controller + } if self.def != "" { return self.def } @@ -30,6 +33,9 @@ func (self *NodeInfoEntry) Source() string { if self.profile != "" { return "profile" } + if self.controller != "" { + return "controller" + } if self.def != "" { return "default" } @@ -46,6 +52,9 @@ func (self *NodeInfoEntry) Get() string { if self.profile != "" { return self.profile } + if self.controller != "" { + return self.controller + } if self.def != "" { return self.def } @@ -81,6 +90,13 @@ func (self *NodeInfoEntry) SetProfile(value string) { self.profile = value } +func (self *NodeInfoEntry) SetController(value string) { + if value == "" { + return + } + self.controller = value +} + func (self *NodeInfoEntry) Set(value string) { if value == "" { return diff --git a/internal/pkg/node/modifiers.go b/internal/pkg/node/modifiers.go index 870e69a1..094ab51c 100644 --- a/internal/pkg/node/modifiers.go +++ b/internal/pkg/node/modifiers.go @@ -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 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) } - 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) } - self.NodeGroups[groupID].Nodes[nodeID] = &node - self.NodeGroups[groupID].Nodes[nodeID].Hostname = nodeID + self.Controllers[controllerID].NodeGroups[groupID].Nodes[nodeID] = &node + self.Controllers[controllerID].NodeGroups[groupID].Nodes[nodeID].Hostname = nodeID 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 { - 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.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) - delete(self.NodeGroups[groupID].Nodes, 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.NodeGroups[groupID]; !ok { - return errors.New("Group '" + groupID + "' was not found") - } - if _, ok := self.NodeGroups[groupID].Nodes[nodeID]; !ok { - return errors.New("Node '" + nodeID + "' was not found in group '" + groupID + "'") + if _, ok := self.Controllers[controllerID]; ! ok { + return errors.New("Controller does not exist: " + controllerID) } - self.NodeGroups[groupID].Nodes[nodeID].Hostname = node.HostName.GetReal() - self.NodeGroups[groupID].Nodes[nodeID].Vnfs = node.Vnfs.GetReal() - 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() - self.NodeGroups[groupID].Nodes[nodeID].KernelArgs = node.KernelArgs.GetReal() - 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.NodeGroups[groupID].Nodes[nodeID].RuntimeOverlay = node.RuntimeOverlay.GetReal() - self.NodeGroups[groupID].Nodes[nodeID].SystemOverlay = node.SystemOverlay.GetReal() - self.NodeGroups[groupID].Nodes[nodeID].Profiles = node.Profiles - self.NodeGroups[groupID].Nodes[nodeID].NetDevs = node.NetDevs + 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 } @@ -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 wwlog.Printf(wwlog.VERBOSE, "Adding new group: %s/%s\n", groupID) - if _, ok := self.NodeGroups[groupID]; ok { - return errors.New("Group name already exists: " + groupID) + if _, ok := self.Controllers[controllerID]; ! ok { + return errors.New("Controller does not exist: " + controllerID) } - self.NodeGroups[groupID] = &group - self.NodeGroups[groupID].DomainName = groupID - self.NodeGroups[groupID].Profiles = []string{"default"} + 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(groupID string) error { - if _, ok := self.NodeGroups[groupID]; !ok { +func (self *nodeYaml) DelGroup(controllerID string, groupID string) error { - 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) - delete(self.NodeGroups, 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.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) } - self.NodeGroups[groupID].DomainName = group.DomainName - self.NodeGroups[groupID].Vnfs = group.Vnfs - self.NodeGroups[groupID].KernelVersion = group.KernelVersion - self.NodeGroups[groupID].KernelArgs = group.KernelArgs - self.NodeGroups[groupID].Ipxe = group.Ipxe - self.NodeGroups[groupID].IpmiUserName = group.IpmiUserName - self.NodeGroups[groupID].IpmiPassword = group.IpmiPassword - self.NodeGroups[groupID].RuntimeOverlay = group.RuntimeOverlay - self.NodeGroups[groupID].SystemOverlay = group.SystemOverlay - self.NodeGroups[groupID].Profiles = group.Profiles + 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 } diff --git a/internal/pkg/overlay/overlay.go b/internal/pkg/overlay/overlay.go index 82e6ab73..f2346d68 100644 --- a/internal/pkg/overlay/overlay.go +++ b/internal/pkg/overlay/overlay.go @@ -18,11 +18,14 @@ import ( ) type TemplateStruct struct { - Fqdn string - Hostname string - Groupname string - Vnfs string - Netdev map[string]*node.NetDevs + Self struct { + Fqdn string + Hostname string + GroupName string + Vnfs string + NetDevs map[string]*node.NetDevs + } + AllNodes []node.NodeInfo } func BuildSystemOverlay(nodeList []node.NodeInfo) error { @@ -49,9 +52,6 @@ func RuntimeOverlayInit(name string) error { return overlayInit(name, "runtime") } - - - func findAllOverlays(overlayType string) ([]string, error) { config := config.New() var ret []string @@ -83,7 +83,6 @@ func findAllOverlays(overlayType string) ([]string, error) { return ret, nil } - func overlayInit(name string, overlayType string) error { var path string config := config.New() @@ -100,7 +99,7 @@ func overlayInit(name string, overlayType string) error { } if util.IsDir(path) == true { - return errors.New("Overlay already exists: "+name) + return errors.New("Overlay already exists: " + name) } err := os.MkdirAll(path, 0755) @@ -108,13 +107,10 @@ func overlayInit(name string, overlayType string) error { 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 @@ -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()) - t.Fqdn = node.Fqdn.Get() - t.Hostname = node.HostName.Get() - t.Groupname = node.GroupName.Get() - t.Vnfs = node.Vnfs.Get() - t.Netdev = node.NetDevs + 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()) @@ -230,7 +227,6 @@ func buildOverlay(nodeList []node.NodeInfo, overlayType string) error { 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) diff --git a/internal/pkg/vnfs/vnfs.go b/internal/pkg/vnfs/vnfs.go index 11d67ad0..5bcf49f4 100644 --- a/internal/pkg/vnfs/vnfs.go +++ b/internal/pkg/vnfs/vnfs.go @@ -59,9 +59,9 @@ func CleanName(source string) string { 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 } @@ -75,6 +75,10 @@ func New(source string) (VnfsObject, error) { 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 { @@ -92,10 +96,6 @@ func New(source string) (VnfsObject, error) { ret.Image = config.VnfsImage(pathFriendlyName) ret.Config = path.Join(config.VnfsImageDir(pathFriendlyName), "config.yaml") - if util.IsFile(ret.Config) { - return Load(source) - } - return ret, nil }