From 056e8c99695f9720881ce40e8926eda6d26c96e7 Mon Sep 17 00:00:00 2001 From: Gregory Kurtzer Date: Tue, 1 Dec 2020 17:31:37 -0800 Subject: [PATCH] A bunch of changes around DHCP service, templating, and controller config --- etc/dhcp/static-dhcpd.conf | 4 +- internal/app/wwctl/controller/list/main.go | 36 +++++++++++---- internal/app/wwctl/controller/set/main.go | 20 +++++++++ internal/app/wwctl/controller/set/root.go | 20 +++++---- internal/app/wwctl/service/dhcp/main.go | 44 +++++++++++++------ internal/app/wwctl/service/dhcp/root.go | 4 +- internal/pkg/node/constructors.go | 15 ++++++- internal/pkg/node/datastructure.go | 5 ++- internal/pkg/node/modifiers.go | 51 +++++++++------------- 9 files changed, 132 insertions(+), 67 deletions(-) diff --git a/etc/dhcp/static-dhcpd.conf b/etc/dhcp/static-dhcpd.conf index dd306fe1..61a1592f 100644 --- a/etc/dhcp/static-dhcpd.conf +++ b/etc/dhcp/static-dhcpd.conf @@ -38,8 +38,8 @@ subnet {{$.Network}} netmask {{$.Netmask}} { next-server {{$.Ipaddr}}; } -{{- range $nodes := .Nodes}} -host {{$.Fqdn}} { +{{range $nodes := .Nodes}} +host {{.Fqdn}} { hardware ethernet {{$nodes.NetDevs.eth0.Hwaddr}} filed-address {{$nodes.NetDevs.eth0.Ipaddr}} } diff --git a/internal/app/wwctl/controller/list/main.go b/internal/app/wwctl/controller/list/main.go index ff2e1396..6d6a97a9 100644 --- a/internal/app/wwctl/controller/list/main.go +++ b/internal/app/wwctl/controller/list/main.go @@ -7,7 +7,6 @@ import ( "github.com/hpcng/warewulf/internal/pkg/wwlog" "github.com/spf13/cobra" "os" - "reflect" ) func CobraRunE(cmd *cobra.Command, args []string) error { @@ -23,15 +22,35 @@ func CobraRunE(cmd *cobra.Command, args []string) error { os.Exit(1) } - if ShowAll == true { - for _, controller := range controllers { - v := reflect.ValueOf(controller) - typeOfS := v.Type() + for _, c := range controllers { 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()) + fmt.Printf("%-15s %15s : %s = %s\n", c.Id, "", "IP Address", c.Ipaddr) + fmt.Printf("%-15s %15s : %s = %s\n", c.Id, "", "Domain Name", c.DomainName) + fmt.Printf("%-15s %15s : %s = %s\n", c.Id, "", "FQDN", c.Fqdn) + fmt.Printf("%-15s %15s : %s = %s\n", c.Id, "", "Comment", c.Comment) + fmt.Printf("%-15s %15s : %s = %s\n", c.Id, "Warewulf", "Port", c.Services.Warewulfd.Port) + fmt.Printf("%-15s %15s : %s = %t\n", c.Id, "Warewulf", "Secure", c.Services.Warewulfd.Secure) + fmt.Printf("%-15s %15s : %s = %s\n", c.Id, "Warewulf", "Enable CMD", c.Services.Warewulfd.EnableCmd) + fmt.Printf("%-15s %15s : %s = %s\n", c.Id, "Warewulf", "Restart CMD", c.Services.Warewulfd.RestartCmd) + fmt.Printf("%-15s %15s : %s = %t\n", c.Id, "DHCPD", "Enabled", c.Services.Dhcp.Enabled) + fmt.Printf("%-15s %15s : %s = %s\n", c.Id, "DHCPD", "Template", c.Services.Dhcp.Template) + fmt.Printf("%-15s %15s : %s = %s\n", c.Id, "DHCPD", "ConfigFile", c.Services.Dhcp.ConfigFile) + fmt.Printf("%-15s %15s : %s = %s\n", c.Id, "DHCPD", "RangeStart", c.Services.Dhcp.RangeStart) + fmt.Printf("%-15s %15s : %s = %s\n", c.Id, "DHCPD", "RangeEnd", c.Services.Dhcp.RangeEnd) + fmt.Printf("%-15s %15s : %s = %s\n", c.Id, "DHCPD", "Enable CMD", c.Services.Dhcp.EnableCmd) + fmt.Printf("%-15s %15s : %s = %s\n", c.Id, "DHCPD", "Restart CMD", c.Services.Dhcp.RestartCmd) + fmt.Printf("%-15s %15s : %s = %t\n", c.Id, "TFTP", "Enabled", c.Services.Tftp.Enabled) + fmt.Printf("%-15s %15s : %s = %s\n", c.Id, "TFTP", "TftpRoot", c.Services.Tftp.TftpRoot) + fmt.Printf("%-15s %15s : %s = %s\n", c.Id, "TFTP", "Enable CMD", c.Services.Tftp.EnableCmd) + fmt.Printf("%-15s %15s : %s = %s\n", c.Id, "TFTP", "Restart CMD", c.Services.Tftp.RestartCmd) + fmt.Printf("%-15s %15s : %s = %t\n", c.Id, "NFS", "Enabled", c.Services.Nfs.Enabled) + for _, e := range c.Services.Nfs.Exports { + fmt.Printf("%-15s %15s : %s = %s\n", c.Id, "NFS", "Exports", e) } + fmt.Printf("%-15s %15s : %s = %s\n", c.Id, "NFS", "Enable CMD", c.Services.Nfs.EnableCmd) + fmt.Printf("%-15s %15s : %s = %s\n", c.Id, "NFS", "Restart CMD", c.Services.Nfs.RestartCmd) + } } else { fmt.Printf("%-22s\n", "CONTROLLER NAME") @@ -40,6 +59,5 @@ func CobraRunE(cmd *cobra.Command, args []string) error { } } - return nil -} \ No newline at end of file +} diff --git a/internal/app/wwctl/controller/set/main.go b/internal/app/wwctl/controller/set/main.go index 4740acfe..d38ce4be 100644 --- a/internal/app/wwctl/controller/set/main.go +++ b/internal/app/wwctl/controller/set/main.go @@ -59,6 +59,26 @@ func CobraRunE(cmd *cobra.Command, args []string) error { for _, c := range controllers { + if SetComment != "" { + wwlog.Printf(wwlog.VERBOSE, "Controller: %s, Setting Comment: %s\n", c.Id, SetComment) + + c.Comment = SetComment + err := nodeDB.ControllerUpdate(c) + if err != nil { + wwlog.Printf(wwlog.ERROR, "%s\n", err) + os.Exit(1) + } + } + if SetFqdn != "" { + wwlog.Printf(wwlog.VERBOSE, "Controller: %s, Setting FQDN: %s\n", c.Id, SetFqdn) + + c.Fqdn = SetFqdn + err := nodeDB.ControllerUpdate(c) + if err != nil { + wwlog.Printf(wwlog.ERROR, "%s\n", err) + os.Exit(1) + } + } if SetIpaddr != "" { wwlog.Printf(wwlog.VERBOSE, "Controller: %s, Setting IP Addr to: %s\n", c.Id, SetIpaddr) diff --git a/internal/app/wwctl/controller/set/root.go b/internal/app/wwctl/controller/set/root.go index 5f1b5499..f111ecc6 100644 --- a/internal/app/wwctl/controller/set/root.go +++ b/internal/app/wwctl/controller/set/root.go @@ -4,19 +4,23 @@ import "github.com/spf13/cobra" var ( baseCmd = &cobra.Command{ - Use: "set", - Short: "Set", - Long: "Set", - RunE: CobraRunE, - Args: cobra.MinimumNArgs(1), + Use: "set", + Short: "Set", + Long: "Set", + RunE: CobraRunE, + Args: cobra.MinimumNArgs(1), } - SetAll bool - SetIpaddr string + SetAll bool + SetIpaddr string + SetFqdn string + SetComment 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") + baseCmd.PersistentFlags().StringVarP(&SetIpaddr, "ipaddr", "I", "", "Set the controller's IP address") + baseCmd.PersistentFlags().StringVarP(&SetFqdn, "fqdn", "F", "", "Set the controller's FQDN") + baseCmd.PersistentFlags().StringVarP(&SetComment, "comment", "C", "", "Comments describing this controller") } diff --git a/internal/app/wwctl/service/dhcp/main.go b/internal/app/wwctl/service/dhcp/main.go index e73f36d0..9507af42 100644 --- a/internal/app/wwctl/service/dhcp/main.go +++ b/internal/app/wwctl/service/dhcp/main.go @@ -24,7 +24,10 @@ type dhcpTemplate struct { } func CobraRunE(cmd *cobra.Command, args []string) error { + return ConfigureDHCP() +} +func ConfigureDHCP() error { nodeDB, err := node.New() if err != nil { wwlog.Printf(wwlog.ERROR, "Could not open node configuration: %s\n", err) @@ -39,7 +42,6 @@ func CobraRunE(cmd *cobra.Command, args []string) error { for _, controller := range controllers { var templateFile string - var configWriter *os.File var d dhcpTemplate var configured bool @@ -66,6 +68,15 @@ func CobraRunE(cmd *cobra.Command, args []string) error { } } + hostname, err := os.Hostname() + if err != nil { + wwlog.Printf(wwlog.ERROR, "Could not obtain system's hostname\n") + os.Exit(1) + } + if hostname != controller.Fqdn { + wwlog.Printf(wwlog.WARN, "The system hostname does not match Warewulf config: %s != %s\n", hostname, controller.Fqdn) + } + 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) @@ -107,25 +118,32 @@ func CobraRunE(cmd *cobra.Command, args []string) error { os.Exit(1) } - if ShowConfig == true { - configWriter = os.Stdout - } else { - configWriter, err = os.OpenFile(controller.Services.Dhcp.ConfigFile, os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0640) + if DoConfig == true { + fmt.Printf("Writing the DHCP configuration file\n") + configWriter, err := os.OpenFile(controller.Services.Dhcp.ConfigFile, os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0640) if err != nil { wwlog.Printf(wwlog.ERROR, "%s\n", err) os.Exit(1) } defer configWriter.Close() - } + err = tmpl.Execute(configWriter, d) + if err != nil { + wwlog.Printf(wwlog.ERROR, "%s\n", err) + os.Exit(1) + } - err = tmpl.Execute(configWriter, d) - if err != nil { - wwlog.Printf(wwlog.ERROR, "%s\n", err) - os.Exit(1) - } + fmt.Printf("Enabling and restarting the DHCP services\n") + util.ExecInteractive("/bin/sh", "-c", controller.Services.Dhcp.EnableCmd) + util.ExecInteractive("/bin/sh", "-c", controller.Services.Dhcp.RestartCmd) - util.ExecInteractive("/bin/sh", "-c", controller.Services.Dhcp.EnableCmd) - util.ExecInteractive("/bin/sh", "-c", controller.Services.Dhcp.RestartCmd) + } else { + 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 diff --git a/internal/app/wwctl/service/dhcp/root.go b/internal/app/wwctl/service/dhcp/root.go index cadb2171..1b08cf09 100644 --- a/internal/app/wwctl/service/dhcp/root.go +++ b/internal/app/wwctl/service/dhcp/root.go @@ -11,11 +11,11 @@ var ( Long: "DHCP Config", RunE: CobraRunE, } - ShowConfig bool + DoConfig bool ) func init() { - baseCmd.PersistentFlags().BoolVarP(&ShowConfig, "show", "s", false, "Show configuration rather than writing to files") + baseCmd.PersistentFlags().BoolVarP(&DoConfig, "configure", "c", false, "Do the DHCP Configuration") } diff --git a/internal/pkg/node/constructors.go b/internal/pkg/node/constructors.go index 5e0b98f9..8ddf7042 100644 --- a/internal/pkg/node/constructors.go +++ b/internal/pkg/node/constructors.go @@ -147,11 +147,14 @@ func (self *nodeYaml) FindAllControllers() ([]ControllerInfo, error) { c.Id = controllername c.Ipaddr = controller.Ipaddr + c.Comment = controller.Comment + c.Fqdn = controller.Fqdn + //TODO: Is there a better way to do this, cause EWWW! c.Services = struct { Warewulfd struct { Port string - Secure string + Secure bool StartCmd string RestartCmd string EnableCmd string @@ -182,6 +185,16 @@ func (self *nodeYaml) FindAllControllers() ([]ControllerInfo, error) { } }(controller.Services) + // Validations // + + if c.Ipaddr == "" { + wwlog.Printf(wwlog.WARN, "Controller IP address is unset: %s\n", c.Id) + } + + if c.Services.Warewulfd.Port == "" { + c.Services.Warewulfd.Port = "987" + } + // TODO: Validate or die on all inputs ret = append(ret, c) diff --git a/internal/pkg/node/datastructure.go b/internal/pkg/node/datastructure.go index b136f005..9adad908 100644 --- a/internal/pkg/node/datastructure.go +++ b/internal/pkg/node/datastructure.go @@ -31,10 +31,11 @@ type ProfileConf struct { type ControllerConf struct { Comment string `yaml:"comment"` Ipaddr string `yaml:"ipaddr"` + Fqdn string `yaml:"fqdn"` Services struct { Warewulfd struct { Port string `yaml:"port"` - Secure string `yaml:"secure,omitempty"` + Secure bool `yaml:"secure,omitempty"` StartCmd string `yaml:"start command,omitempty"` RestartCmd string `yaml:"restart command,omitempty"` EnableCmd string `yaml:"enable command,omitempty"` @@ -153,7 +154,7 @@ type ControllerInfo struct { Services struct { Warewulfd struct { Port string - Secure string + Secure bool StartCmd string RestartCmd string EnableCmd string diff --git a/internal/pkg/node/modifiers.go b/internal/pkg/node/modifiers.go index 094ab51c..3b0cef83 100644 --- a/internal/pkg/node/modifiers.go +++ b/internal/pkg/node/modifiers.go @@ -19,11 +19,11 @@ func (self *nodeYaml) AddNode(controllerID string, groupID string, nodeID string wwlog.Printf(wwlog.VERBOSE, "Adding new node: %s/%s\n", groupID, nodeID) - if _, ok := self.Controllers[controllerID]; ! ok { + if _, ok := self.Controllers[controllerID]; !ok { return errors.New("Controller does not exist: " + controllerID) } - if _, ok := self.Controllers[controllerID].NodeGroups[groupID]; ! ok { + if _, ok := self.Controllers[controllerID].NodeGroups[groupID]; !ok { return errors.New("Group does not exist: " + groupID) } @@ -39,11 +39,11 @@ func (self *nodeYaml) AddNode(controllerID string, groupID string, nodeID string func (self *nodeYaml) DelNode(controllerID string, groupID string, nodeID string) error { - if _, ok := self.Controllers[controllerID]; ! ok { + if _, ok := self.Controllers[controllerID]; !ok { return errors.New("Controller does not exist: " + controllerID) } - if _, ok := self.Controllers[controllerID].NodeGroups[groupID]; ! ok { + if _, ok := self.Controllers[controllerID].NodeGroups[groupID]; !ok { return errors.New("Group does not exist: " + groupID) } @@ -57,20 +57,20 @@ func (self *nodeYaml) DelNode(controllerID string, groupID string, nodeID string return nil } -func(self *nodeYaml) NodeUpdate(node NodeInfo) error { +func (self *nodeYaml) NodeUpdate(node NodeInfo) error { controllerID := node.Cid.Get() groupID := node.Gid.Get() nodeID := node.Id.Get() - if _, ok := self.Controllers[controllerID]; ! ok { + if _, ok := self.Controllers[controllerID]; !ok { return errors.New("Controller does not exist: " + controllerID) } - if _, ok := self.Controllers[controllerID].NodeGroups[groupID]; ! ok { + 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 { + if _, ok := self.Controllers[controllerID].NodeGroups[groupID].Nodes[groupID]; !ok { return errors.New("Nodename does not exist in group: " + nodeID) } @@ -91,8 +91,6 @@ func(self *nodeYaml) NodeUpdate(node NodeInfo) error { return nil } - - /**** * * GROUP MODIFIERS @@ -104,7 +102,7 @@ func (self *nodeYaml) AddGroup(controllerID string, groupID string) error { wwlog.Printf(wwlog.VERBOSE, "Adding new group: %s/%s\n", groupID) - if _, ok := self.Controllers[controllerID]; ! ok { + if _, ok := self.Controllers[controllerID]; !ok { return errors.New("Controller does not exist: " + controllerID) } @@ -121,11 +119,11 @@ func (self *nodeYaml) AddGroup(controllerID string, groupID string) error { func (self *nodeYaml) DelGroup(controllerID string, groupID string) error { - if _, ok := self.Controllers[controllerID]; ! ok { + if _, ok := self.Controllers[controllerID]; !ok { return errors.New("Controller does not exist: " + controllerID) } - if _, ok := self.Controllers[controllerID].NodeGroups[groupID]; ! ok { + if _, ok := self.Controllers[controllerID].NodeGroups[groupID]; !ok { return errors.New("Group does not exist: " + groupID) } @@ -135,15 +133,15 @@ func (self *nodeYaml) DelGroup(controllerID string, groupID string) error { return nil } -func(self *nodeYaml) GroupUpdate(group GroupInfo) error { +func (self *nodeYaml) GroupUpdate(group GroupInfo) error { controllerID := group.Cid groupID := group.Id - if _, ok := self.Controllers[controllerID]; ! ok { + if _, ok := self.Controllers[controllerID]; !ok { return errors.New("Controller does not exist: " + controllerID) } - if _, ok := self.Controllers[controllerID].NodeGroups[groupID]; ! ok { + if _, ok := self.Controllers[controllerID].NodeGroups[groupID]; !ok { return errors.New("Group does not exist: " + groupID) } @@ -161,8 +159,6 @@ func(self *nodeYaml) GroupUpdate(group GroupInfo) error { return nil } - - /**** * * CONTROLLER MODIFIERS @@ -188,7 +184,7 @@ func (self *nodeYaml) AddController(controllerID string) error { func (self *nodeYaml) DelController(controllerID string) error { - if _, ok := self.Controllers[controllerID]; ! ok { + if _, ok := self.Controllers[controllerID]; !ok { return errors.New("Controller does not exist: " + controllerID) } @@ -198,15 +194,16 @@ func (self *nodeYaml) DelController(controllerID string) error { return nil } -func(self *nodeYaml) ControllerUpdate(controller ControllerInfo) error { +func (self *nodeYaml) ControllerUpdate(controller ControllerInfo) error { controllerID := controller.Id - if _, ok := self.Controllers[controllerID]; ! ok { + 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].Fqdn = controller.Fqdn self.Controllers[controllerID].Services.Warewulfd.Port = controller.Services.Warewulfd.Port self.Controllers[controllerID].Services.Warewulfd.Secure = controller.Services.Warewulfd.Secure @@ -237,9 +234,6 @@ func(self *nodeYaml) ControllerUpdate(controller ControllerInfo) error { return nil } - - - /**** * * PROFILE MODIFIERS @@ -261,7 +255,7 @@ func (self *nodeYaml) AddProfile(profileID string) error { } func (self *nodeYaml) DelProfile(profileID string) error { - if _, ok := self.NodeProfiles[profileID]; ! ok { + if _, ok := self.NodeProfiles[profileID]; !ok { return errors.New("Group '" + profileID + "' was not found") } @@ -271,10 +265,10 @@ func (self *nodeYaml) DelProfile(profileID string) error { return nil } -func(self *nodeYaml) ProfileUpdate(profile ProfileInfo) error { +func (self *nodeYaml) ProfileUpdate(profile ProfileInfo) error { profileID := profile.Id - if _, ok := self.NodeProfiles[profileID]; ! ok { + if _, ok := self.NodeProfiles[profileID]; !ok { return errors.New("Group '" + profileID + "' was not found") } @@ -290,9 +284,6 @@ func(self *nodeYaml) ProfileUpdate(profile ProfileInfo) error { return nil } - - - /**** * * PERSISTENCE