diff --git a/internal/app/wwctl/kernel/imprt/main.go b/internal/app/wwctl/kernel/imprt/main.go index f8b7f143..f2412240 100644 --- a/internal/app/wwctl/kernel/imprt/main.go +++ b/internal/app/wwctl/kernel/imprt/main.go @@ -18,7 +18,7 @@ func CobraRunE(cmd *cobra.Command, args []string) error { // Checking if container flag was set, then overwriting OptRoot kernelVersion := args[0] kernelName := kernelVersion - if len(args) > 1 { + if len(args) > 1 { kernelName = args[1] } if OptContainer != "" { diff --git a/internal/app/wwctl/node/add/main.go b/internal/app/wwctl/node/add/main.go index 917d5f42..0902be93 100644 --- a/internal/app/wwctl/node/add/main.go +++ b/internal/app/wwctl/node/add/main.go @@ -2,18 +2,23 @@ package add import ( "github.com/hpcng/warewulf/internal/pkg/node" + "github.com/hpcng/warewulf/internal/pkg/util" "github.com/hpcng/warewulf/internal/pkg/wwlog" + "github.com/hpcng/warewulf/pkg/hostlist" "github.com/pkg/errors" "github.com/spf13/cobra" ) func CobraRunE(cmd *cobra.Command, args []string) error { + var count uint nodeDB, err := node.New() if err != nil { return errors.Wrap(err, "failed to open node database") } - for _, a := range args { + node_args := hostlist.Expand(args) + + for _, a := range node_args { n, err := nodeDB.AddNode(a) if err != nil { return errors.Wrap(err, "failed to add node") @@ -34,14 +39,16 @@ func CobraRunE(cmd *cobra.Command, args []string) error { return errors.New("you must include the '--netdev' option") } + NewIpaddr := util.IncrementIPv4(SetIpaddr, count) + if _, ok := n.NetDevs[SetNetDev]; !ok { var netdev node.NetDevEntry n.NetDevs[SetNetDev] = &netdev } - wwlog.Printf(wwlog.VERBOSE, "Node: %s:%s, Setting Ipaddr to: %s\n", n.Id.Get(), SetNetDev, SetIpaddr) + wwlog.Printf(wwlog.VERBOSE, "Node: %s:%s, Setting Ipaddr to: %s\n", n.Id.Get(), SetNetDev, NewIpaddr) - n.NetDevs[SetNetDev].Ipaddr.Set(SetIpaddr) + n.NetDevs[SetNetDev].Ipaddr.Set(NewIpaddr) n.NetDevs[SetNetDev].Default.SetB(true) err := nodeDB.NodeUpdate(n) if err != nil { @@ -123,7 +130,7 @@ func CobraRunE(cmd *cobra.Command, args []string) error { return errors.Wrap(err, "failed to update nodedb") } } - + count++ } return errors.Wrap(nodeDB.Persist(), "failed to persist nodedb") diff --git a/internal/app/wwctl/node/console/power.go b/internal/app/wwctl/node/console/power.go index 2c2bf26f..9332edb7 100644 --- a/internal/app/wwctl/node/console/power.go +++ b/internal/app/wwctl/node/console/power.go @@ -7,6 +7,7 @@ import ( "github.com/hpcng/warewulf/internal/pkg/node" "github.com/hpcng/warewulf/internal/pkg/power" "github.com/hpcng/warewulf/internal/pkg/wwlog" + "github.com/hpcng/warewulf/pkg/hostlist" "github.com/spf13/cobra" ) @@ -25,6 +26,8 @@ func CobraRunE(cmd *cobra.Command, args []string) error { os.Exit(1) } + args = hostlist.Expand(args) + if len(args) > 0 { nodes = node.FilterByName(nodes, args) } else { diff --git a/internal/app/wwctl/node/delete/main.go b/internal/app/wwctl/node/delete/main.go index 9f70e819..ed184291 100644 --- a/internal/app/wwctl/node/delete/main.go +++ b/internal/app/wwctl/node/delete/main.go @@ -6,6 +6,7 @@ import ( "github.com/hpcng/warewulf/internal/pkg/node" "github.com/hpcng/warewulf/internal/pkg/wwlog" + "github.com/hpcng/warewulf/pkg/hostlist" "github.com/manifoldco/promptui" "github.com/pkg/errors" "github.com/spf13/cobra" @@ -27,6 +28,8 @@ func CobraRunE(cmd *cobra.Command, args []string) error { os.Exit(1) } + args = hostlist.Expand(args) + for _, r := range args { var match bool for _, n := range nodes { diff --git a/internal/app/wwctl/node/list/main.go b/internal/app/wwctl/node/list/main.go index 074c0501..31b81eba 100644 --- a/internal/app/wwctl/node/list/main.go +++ b/internal/app/wwctl/node/list/main.go @@ -8,6 +8,7 @@ import ( "github.com/hpcng/warewulf/internal/pkg/node" "github.com/hpcng/warewulf/internal/pkg/wwlog" + "github.com/hpcng/warewulf/pkg/hostlist" "github.com/spf13/cobra" ) @@ -26,6 +27,8 @@ func CobraRunE(cmd *cobra.Command, args []string) error { os.Exit(1) } + args = hostlist.Expand(args) + if ShowAll { for _, node := range node.FilterByName(nodes, args) { fmt.Printf("################################################################################\n") diff --git a/internal/app/wwctl/node/root.go b/internal/app/wwctl/node/root.go index c5c92ca4..7a37b726 100644 --- a/internal/app/wwctl/node/root.go +++ b/internal/app/wwctl/node/root.go @@ -15,7 +15,9 @@ var ( baseCmd = &cobra.Command{ Use: "node", Short: "Node management", - Long: "Management of node settings", + Long: "Management of node settings. All node ranges can use brackets to identify\n" + + "node ranges. For example: n00[00-4].cluster[0-1] will identify the first 5 nodes\n" + + "in cluster0 and cluster1.", } ) diff --git a/internal/app/wwctl/node/sensors/power.go b/internal/app/wwctl/node/sensors/power.go index dc86dc0c..a2c0766e 100644 --- a/internal/app/wwctl/node/sensors/power.go +++ b/internal/app/wwctl/node/sensors/power.go @@ -8,6 +8,7 @@ import ( "github.com/hpcng/warewulf/internal/pkg/node" "github.com/hpcng/warewulf/internal/pkg/power" "github.com/hpcng/warewulf/internal/pkg/wwlog" + "github.com/hpcng/warewulf/pkg/hostlist" "github.com/spf13/cobra" ) @@ -26,6 +27,8 @@ func CobraRunE(cmd *cobra.Command, args []string) error { os.Exit(1) } + args = hostlist.Expand(args) + if len(args) > 0 { nodes = node.FilterByName(nodes, args) } else { diff --git a/internal/app/wwctl/node/set/main.go b/internal/app/wwctl/node/set/main.go index 1e87ce3d..725266aa 100644 --- a/internal/app/wwctl/node/set/main.go +++ b/internal/app/wwctl/node/set/main.go @@ -9,6 +9,7 @@ import ( "github.com/hpcng/warewulf/internal/pkg/util" "github.com/hpcng/warewulf/internal/pkg/warewulfd" "github.com/hpcng/warewulf/internal/pkg/wwlog" + "github.com/hpcng/warewulf/pkg/hostlist" "github.com/manifoldco/promptui" "github.com/pkg/errors" "github.com/spf13/cobra" @@ -16,6 +17,7 @@ import ( func CobraRunE(cmd *cobra.Command, args []string) error { var err error + var count uint var SetProfiles []string nodeDB, err := node.New() @@ -32,7 +34,7 @@ func CobraRunE(cmd *cobra.Command, args []string) error { if !SetNodeAll { if len(args) > 0 { - nodes = node.FilterByName(nodes, args) + nodes = node.FilterByName(nodes, hostlist.Expand(args)) } else { //nolint:errcheck cmd.Usage() @@ -99,8 +101,9 @@ func CobraRunE(cmd *cobra.Command, args []string) error { } if SetIpmiIpaddr != "" { - wwlog.Printf(wwlog.VERBOSE, "Node: %s, Setting IPMI IP address to: %s\n", n.Id.Get(), SetIpmiIpaddr) - n.IpmiIpaddr.Set(SetIpmiIpaddr) + NewIpaddr := util.IncrementIPv4(SetIpmiIpaddr, count) + wwlog.Printf(wwlog.VERBOSE, "Node: %s, Setting IPMI IP address to: %s\n", n.Id.Get(), NewIpaddr) + n.IpmiIpaddr.Set(NewIpaddr) } if SetIpmiNetmask != "" { @@ -182,13 +185,15 @@ func CobraRunE(cmd *cobra.Command, args []string) error { os.Exit(1) } + NewIpaddr := util.IncrementIPv4(SetIpaddr, count) + if _, ok := n.NetDevs[SetNetDev]; !ok { var nd node.NetDevEntry n.NetDevs[SetNetDev] = &nd } - wwlog.Printf(wwlog.VERBOSE, "Node: %s:%s, Setting Ipaddr to: %s\n", n.Id.Get(), SetNetDev, SetIpaddr) - n.NetDevs[SetNetDev].Ipaddr.Set(SetIpaddr) + wwlog.Printf(wwlog.VERBOSE, "Node: %s:%s, Setting Ipaddr to: %s\n", n.Id.Get(), SetNetDev, NewIpaddr) + n.NetDevs[SetNetDev].Ipaddr.Set(NewIpaddr) } if SetNetmask != "" { if SetNetDev == "" { @@ -302,6 +307,8 @@ func CobraRunE(cmd *cobra.Command, args []string) error { wwlog.Printf(wwlog.ERROR, "%s\n", err) os.Exit(1) } + + count++ } if SetYes { diff --git a/internal/app/wwctl/node/set/root.go b/internal/app/wwctl/node/set/root.go index 86ea559e..767bb94c 100644 --- a/internal/app/wwctl/node/set/root.go +++ b/internal/app/wwctl/node/set/root.go @@ -105,13 +105,13 @@ func init() { }); err != nil { log.Println(err) } - baseCmd.PersistentFlags().StringVar(&SetIpmiIpaddr, "ipmi", "", "Set the node's IPMI IP address") + baseCmd.PersistentFlags().StringVar(&SetIpmiIpaddr, "ipmiaddr", "", "Set the node's IPMI IP address") baseCmd.PersistentFlags().StringVar(&SetIpmiNetmask, "ipminetmask", "", "Set the node's IPMI netmask") baseCmd.PersistentFlags().StringVar(&SetIpmiPort, "ipmiport", "", "Set the node's IPMI port") baseCmd.PersistentFlags().StringVar(&SetIpmiGateway, "ipmigateway", "", "Set the node's IPMI gateway") 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(&SetIpmiInterface, "ipmiinterface", "", "Set the node's IPMI interface (defaults to 'lan' if empty)") + baseCmd.PersistentFlags().StringVar(&SetIpmiInterface, "ipmiinterface", "", "Set the node's IPMI interface (defaults: 'lan')") baseCmd.PersistentFlags().StringSliceVar(&SetAddProfile, "addprofile", []string{}, "Add Profile(s) to node") baseCmd.PersistentFlags().StringSliceVar(&SetDelProfile, "delprofile", []string{}, "Remove Profile(s) to node") baseCmd.PersistentFlags().StringVarP(&SetProfile, "profile", "P", "", "Set the node's profile members (comma separated)") diff --git a/internal/app/wwctl/power/cycle/power.go b/internal/app/wwctl/power/cycle/power.go index a846ad7e..728548f8 100644 --- a/internal/app/wwctl/power/cycle/power.go +++ b/internal/app/wwctl/power/cycle/power.go @@ -8,6 +8,7 @@ import ( "github.com/hpcng/warewulf/internal/pkg/node" "github.com/hpcng/warewulf/internal/pkg/power" "github.com/hpcng/warewulf/internal/pkg/wwlog" + "github.com/hpcng/warewulf/pkg/hostlist" "github.com/spf13/cobra" ) @@ -27,7 +28,7 @@ func CobraRunE(cmd *cobra.Command, args []string) error { } if len(args) > 0 { - nodes = node.FilterByName(nodes, args) + nodes = node.FilterByName(nodes, hostlist.Expand(args)) } else { //nolint:errcheck cmd.Usage() diff --git a/internal/app/wwctl/power/off/power.go b/internal/app/wwctl/power/off/power.go index 7f9dc603..2afe8276 100644 --- a/internal/app/wwctl/power/off/power.go +++ b/internal/app/wwctl/power/off/power.go @@ -8,6 +8,7 @@ import ( "github.com/hpcng/warewulf/internal/pkg/node" "github.com/hpcng/warewulf/internal/pkg/power" "github.com/hpcng/warewulf/internal/pkg/wwlog" + "github.com/hpcng/warewulf/pkg/hostlist" "github.com/spf13/cobra" ) @@ -27,7 +28,7 @@ func CobraRunE(cmd *cobra.Command, args []string) error { } if len(args) > 0 { - nodes = node.FilterByName(nodes, args) + nodes = node.FilterByName(nodes, hostlist.Expand(args)) } else { //nolint:errcheck cmd.Usage() diff --git a/internal/app/wwctl/power/on/power.go b/internal/app/wwctl/power/on/power.go index 7f5624a8..a92bf50b 100644 --- a/internal/app/wwctl/power/on/power.go +++ b/internal/app/wwctl/power/on/power.go @@ -8,6 +8,7 @@ import ( "github.com/hpcng/warewulf/internal/pkg/node" "github.com/hpcng/warewulf/internal/pkg/power" "github.com/hpcng/warewulf/internal/pkg/wwlog" + "github.com/hpcng/warewulf/pkg/hostlist" "github.com/spf13/cobra" ) @@ -27,7 +28,7 @@ func CobraRunE(cmd *cobra.Command, args []string) error { } if len(args) > 0 { - nodes = node.FilterByName(nodes, args) + nodes = node.FilterByName(nodes, hostlist.Expand(args)) } else { //nolint:errcheck cmd.Usage() diff --git a/internal/app/wwctl/power/reset/power.go b/internal/app/wwctl/power/reset/power.go index 3996648e..3126a301 100644 --- a/internal/app/wwctl/power/reset/power.go +++ b/internal/app/wwctl/power/reset/power.go @@ -8,6 +8,7 @@ import ( "github.com/hpcng/warewulf/internal/pkg/node" "github.com/hpcng/warewulf/internal/pkg/power" "github.com/hpcng/warewulf/internal/pkg/wwlog" + "github.com/hpcng/warewulf/pkg/hostlist" "github.com/spf13/cobra" ) @@ -27,7 +28,7 @@ func CobraRunE(cmd *cobra.Command, args []string) error { } if len(args) > 0 { - nodes = node.FilterByName(nodes, args) + nodes = node.FilterByName(nodes, hostlist.Expand(args)) } else { //nolint:errcheck cmd.Usage() diff --git a/internal/app/wwctl/power/soft/power.go b/internal/app/wwctl/power/soft/power.go index cdbf8462..7771cbab 100644 --- a/internal/app/wwctl/power/soft/power.go +++ b/internal/app/wwctl/power/soft/power.go @@ -8,6 +8,7 @@ import ( "github.com/hpcng/warewulf/internal/pkg/node" "github.com/hpcng/warewulf/internal/pkg/power" "github.com/hpcng/warewulf/internal/pkg/wwlog" + "github.com/hpcng/warewulf/pkg/hostlist" "github.com/spf13/cobra" ) @@ -27,7 +28,7 @@ func CobraRunE(cmd *cobra.Command, args []string) error { } if len(args) > 0 { - nodes = node.FilterByName(nodes, args) + nodes = node.FilterByName(nodes, hostlist.Expand(args)) } else { //nolint:errcheck cmd.Usage() diff --git a/internal/app/wwctl/power/status/power.go b/internal/app/wwctl/power/status/power.go index b1f15dd6..9d67cd17 100644 --- a/internal/app/wwctl/power/status/power.go +++ b/internal/app/wwctl/power/status/power.go @@ -8,6 +8,7 @@ import ( "github.com/hpcng/warewulf/internal/pkg/node" "github.com/hpcng/warewulf/internal/pkg/power" "github.com/hpcng/warewulf/internal/pkg/wwlog" + "github.com/hpcng/warewulf/pkg/hostlist" "github.com/spf13/cobra" ) @@ -27,7 +28,7 @@ func CobraRunE(cmd *cobra.Command, args []string) error { } if len(args) > 0 { - nodes = node.FilterByName(nodes, args) + nodes = node.FilterByName(nodes, hostlist.Expand(args)) } else { //nolint:errcheck cmd.Usage() diff --git a/internal/pkg/kernel/kernel.go b/internal/pkg/kernel/kernel.go index 7b342a2b..0d1024a8 100644 --- a/internal/pkg/kernel/kernel.go +++ b/internal/pkg/kernel/kernel.go @@ -102,6 +102,7 @@ func ListKernels() ([]string, error) { func Build(kernelVersion string, kernelName string, root string) (string, error) { kernelImage := path.Join(root, "/boot/vmlinuz-"+kernelVersion) kernelDrivers := path.Join(root, "/lib/modules/"+kernelVersion) + kernelDriversRelative := path.Join("/lib/modules/"+kernelVersion) kernelDestination := KernelImage(kernelName) driversDestination := KmodsImage(kernelName) versionDestination := KernelVersion(kernelName) @@ -177,7 +178,7 @@ func Build(kernelVersion string, kernelName string, root string) (string, error) wwlog.Printf(wwlog.VERBOSE, "Using PIGZ to compress the container: %s\n", compressor) } - cmd := fmt.Sprintf("cd /; find .%s | cpio --quiet -o -H newc | %s -c > \"%s\"", kernelDrivers, compressor, driversDestination) + cmd := fmt.Sprintf("cd %s; find .%s | cpio --quiet -o -H newc | %s -c > \"%s\"", root, kernelDriversRelative, compressor, driversDestination) wwlog.Printf(wwlog.DEBUG, "RUNNING: %s\n", cmd) err = exec.Command("/bin/sh", "-c", cmd).Run() diff --git a/internal/pkg/node/datastructure.go b/internal/pkg/node/datastructure.go index e47275e5..a7f55ae6 100644 --- a/internal/pkg/node/datastructure.go +++ b/internal/pkg/node/datastructure.go @@ -106,7 +106,7 @@ type NetDevEntry struct { func init() { //TODO: Check to make sure nodes.conf is found if !util.IsFile(ConfigFile) { - c, err := os.OpenFile(ConfigFile, os.O_RDWR|os.O_CREATE, 0644) + c, err := os.OpenFile(ConfigFile, os.O_RDWR|os.O_CREATE, 0640) if err != nil { wwlog.Printf(wwlog.ERROR, "Could not create new configuration file: %s\n", err) // just return silently, as init is also called for bash_completion diff --git a/internal/pkg/util/util.go b/internal/pkg/util/util.go index a6ebc2c9..dda449e7 100644 --- a/internal/pkg/util/util.go +++ b/internal/pkg/util/util.go @@ -6,6 +6,7 @@ import ( "fmt" "io" "math/rand" + "net" "os" "os/exec" "path" @@ -368,3 +369,16 @@ func SplitValidPaths(input, delim string) []string { return (ret) } + +func IncrementIPv4(start string, inc uint) string { + ip_start := net.ParseIP(start) + ipv4 := ip_start.To4() + v4_int := uint(ipv4[0])<<24 + uint(ipv4[1])<<16 + uint(ipv4[2])<<8 + uint(ipv4[3]) + v4_int += inc + v4_o3 := byte(v4_int & 0xFF) + v4_o2 := byte((v4_int >> 8) & 0xFF) + v4_o1 := byte((v4_int >> 16) & 0xFF) + v4_o0 := byte((v4_int >> 24) & 0xFF) + ipv4_new := net.IPv4(v4_o0, v4_o1, v4_o2, v4_o3) + return ipv4_new.String() +} diff --git a/pkg/hostlist/hostlist.go b/pkg/hostlist/hostlist.go new file mode 100644 index 00000000..3c821f87 --- /dev/null +++ b/pkg/hostlist/hostlist.go @@ -0,0 +1,80 @@ +package hostlist + +import ( + "fmt" + "strconv" + "strings" + "unicode" +) + +func toInt(i string) int { + ret, _ := strconv.Atoi(i) + return ret +} + +func isDigit(s string) bool { + r := []rune(s) + + for i := 0; i < len(r); i++ { + if !unicode.IsDigit(r[i]) { + return false + } + } + + return true +} + +func expand_iterate(list []string) ([]string, int) { + var ret []string + var count int + + for _, i := range list { + + bracketIndex1 := strings.Index(i, "[") + bracketIndex2 := strings.Index(i, "]") + + if bracketIndex1 >= 0 && bracketIndex1 < bracketIndex2 { + prefix := i[:bracketIndex1] + suffix := i[bracketIndex2+1:] + ranges := strings.Split(i[bracketIndex1+1:bracketIndex2], ",") + count++ + + for _, r := range ranges { + iterate := strings.Split(r, "-") + + if len(iterate) == 1 { + if !isDigit(iterate[0]) { + return ret, 0 + } else { + ret = append(ret, prefix+iterate[0]+suffix) + } + } else if len(iterate) == 2 { + if !isDigit(iterate[0]) || !isDigit(iterate[1]) { + return ret, 0 + } else { + sigfigures := len(iterate[0]) + for i := toInt(iterate[0]); i <= toInt(iterate[1]); i++ { + ret = append(ret, fmt.Sprintf(`%s%.`+fmt.Sprintf("%d", sigfigures)+`d%s`, prefix, i, suffix)) + } + } + } + } + } + } + return ret, count +} + +func Expand(list []string) []string { + ret := list + + for { + loop, count := expand_iterate(ret) + + if count == 0 { + break + } + ret = loop + } + + return ret +}