diff --git a/internal/app/wwctl/profile/add/main.go b/internal/app/wwctl/profile/add/main.go new file mode 100644 index 00000000..b5c61387 --- /dev/null +++ b/internal/app/wwctl/profile/add/main.go @@ -0,0 +1,28 @@ +package add + +import ( + "github.com/hpcng/warewulf/internal/pkg/node" + "github.com/hpcng/warewulf/internal/pkg/wwlog" + "github.com/spf13/cobra" + "os" +) + +func CobraRunE(cmd *cobra.Command, args []string) error { + nodeDB, err := node.New() + if err != nil { + wwlog.Printf(wwlog.ERROR, "Failed opening node database: %s\n", err) + os.Exit(1) + } + + for _, p := range args { + err = nodeDB.AddProfile(p) + if err != nil { + wwlog.Printf(wwlog.ERROR, "%s\n", err) + os.Exit(1) + } + } + + nodeDB.Persist() + + return nil +} \ No newline at end of file diff --git a/internal/app/wwctl/profile/add/root.go b/internal/app/wwctl/profile/add/root.go new file mode 100644 index 00000000..756e829f --- /dev/null +++ b/internal/app/wwctl/profile/add/root.go @@ -0,0 +1,20 @@ +package add + +import "github.com/spf13/cobra" + +var ( + baseCmd = &cobra.Command{ + Use: "add", + Short: "Add profiles", + Long: "Profile configurations ", + RunE: CobraRunE, + } +) + +func init() { +} + +// GetRootCommand returns the root cobra.Command for the application. +func GetCommand() *cobra.Command { + return baseCmd +} diff --git a/internal/app/wwctl/profile/delete/main.go b/internal/app/wwctl/profile/delete/main.go new file mode 100644 index 00000000..ffab3be5 --- /dev/null +++ b/internal/app/wwctl/profile/delete/main.go @@ -0,0 +1,85 @@ +package delete + +import ( + "fmt" + "github.com/hpcng/warewulf/internal/pkg/node" + "github.com/hpcng/warewulf/internal/pkg/util" + "github.com/hpcng/warewulf/internal/pkg/wwlog" + "github.com/manifoldco/promptui" + "github.com/spf13/cobra" + "os" +) + +func CobraRunE(cmd *cobra.Command, args []string) error { + var count int + var numNodes int + var numGroups int + + + nodeDB, err := node.New() + if err != nil { + wwlog.Printf(wwlog.ERROR, "Failed to open node database: %s\n", err) + os.Exit(1) + } + + nodes, err := nodeDB.FindAllNodes() + if err != nil { + wwlog.Printf(wwlog.ERROR, "Could not load all nodes: %s\n", err) + os.Exit(1) + } + groups, err := nodeDB.FindAllGroups() + if err != nil { + wwlog.Printf(wwlog.ERROR, "Could not load all groups: %s\n", err) + os.Exit(1) + } + + + for _, p := range args { + err := nodeDB.DelProfile(p) + if err != nil { + wwlog.Printf(wwlog.ERROR, "%s\n", err) + continue + } + for _, n := range nodes { + for _, np := range n.Profiles { + if np == p { + numNodes++ + wwlog.Printf(wwlog.VERBOSE, "Removing profile from node %s: %s\n", n.Fqdn.Get(), p) + n.Profiles = util.SliceRemoveElement(n.Profiles, p) + nodeDB.NodeUpdate(n) + } + } + } + for _, g := range groups { + for _, np := range g.Profiles { + if np == p { + numGroups++ + wwlog.Printf(wwlog.VERBOSE, "Removing profile from group %s: %s\n", g.Id, p) + g.Profiles = util.SliceRemoveElement(g.Profiles, p) + nodeDB.GroupUpdate(g) + } + } + } + count++ + } + + if count > 0 { + q := fmt.Sprintf("Are you sure you want to delete %d profile(s) (%d groups, %d nodes)", count, numGroups, numNodes) + + prompt := promptui.Prompt{ + Label: q, + IsConfirm: true, + } + + result, _ := prompt.Run() + + if result == "y" || result == "yes" { + nodeDB.Persist() + } + + } else { + wwlog.Printf(wwlog.INFO, "No groups found\n") + } + + return nil +} diff --git a/internal/app/wwctl/profile/delete/root.go b/internal/app/wwctl/profile/delete/root.go new file mode 100644 index 00000000..c2a0cccf --- /dev/null +++ b/internal/app/wwctl/profile/delete/root.go @@ -0,0 +1,20 @@ +package delete + +import "github.com/spf13/cobra" + +var ( + baseCmd = &cobra.Command{ + Use: "delete", + Short: "Delete profiles", + Long: "Profile configurations ", + RunE: CobraRunE, + } +) + +func init() { +} + +// GetRootCommand returns the root cobra.Command for the application. +func GetCommand() *cobra.Command { + return baseCmd +} diff --git a/internal/app/wwctl/profile/list/main.go b/internal/app/wwctl/profile/list/main.go new file mode 100644 index 00000000..93a78486 --- /dev/null +++ b/internal/app/wwctl/profile/list/main.go @@ -0,0 +1,36 @@ +package list + +import ( + "fmt" + "github.com/hpcng/warewulf/internal/pkg/node" + "github.com/hpcng/warewulf/internal/pkg/wwlog" + "github.com/spf13/cobra" + "os" + "reflect" +) + +func CobraRunE(cmd *cobra.Command, args []string) error { + + nodeDB, err := node.New() + if err != nil { + wwlog.Printf(wwlog.ERROR, "Could not open node configuration: %s\n", err) + os.Exit(1) + } + + profiles, err := nodeDB.FindAllProfiles() + if err != nil { + wwlog.Printf(wwlog.ERROR, "Could not find all nodes: %s\n", err) + os.Exit(1) + } + + for _, group := range profiles { + v := reflect.ValueOf(group) + typeOfS := v.Type() + fmt.Printf("################################################################################\n") + for i := 0; i< v.NumField(); i++ { + fmt.Printf("%-25s %s = %v\n", group.Id, typeOfS.Field(i).Name, v.Field(i).Interface()) + } + } + + return nil +} \ No newline at end of file diff --git a/internal/app/wwctl/profile/list/root.go b/internal/app/wwctl/profile/list/root.go new file mode 100644 index 00000000..1d3a8b8a --- /dev/null +++ b/internal/app/wwctl/profile/list/root.go @@ -0,0 +1,20 @@ +package list + +import "github.com/spf13/cobra" + +var ( + baseCmd = &cobra.Command{ + Use: "list", + Short: "List profiles", + Long: "Profile configurations ", + RunE: CobraRunE, + } +) + +func init() { +} + +// GetRootCommand returns the root cobra.Command for the application. +func GetCommand() *cobra.Command { + return baseCmd +} diff --git a/internal/app/wwctl/profile/root.go b/internal/app/wwctl/profile/root.go new file mode 100644 index 00000000..83922375 --- /dev/null +++ b/internal/app/wwctl/profile/root.go @@ -0,0 +1,30 @@ +package profile + +import ( + "github.com/hpcng/warewulf/internal/app/wwctl/profile/add" + "github.com/hpcng/warewulf/internal/app/wwctl/profile/delete" + "github.com/hpcng/warewulf/internal/app/wwctl/profile/list" + "github.com/hpcng/warewulf/internal/app/wwctl/profile/set" + "github.com/spf13/cobra" +) + +var ( + baseCmd = &cobra.Command{ + Use: "profile", + Short: "Management of node configuration profiles", + Long: "Warewulf profiles...", + } + test bool +) + +func init() { + baseCmd.AddCommand(list.GetCommand()) + baseCmd.AddCommand(set.GetCommand()) + baseCmd.AddCommand(add.GetCommand()) + baseCmd.AddCommand(delete.GetCommand()) +} + +// GetRootCommand returns the root cobra.Command for the application. +func GetCommand() *cobra.Command { + return baseCmd +} diff --git a/internal/app/wwctl/profile/set/main.go b/internal/app/wwctl/profile/set/main.go new file mode 100644 index 00000000..548b53c2 --- /dev/null +++ b/internal/app/wwctl/profile/set/main.go @@ -0,0 +1,164 @@ +package set + +import ( + "fmt" + "github.com/hpcng/warewulf/internal/pkg/node" + "github.com/hpcng/warewulf/internal/pkg/wwlog" + "github.com/manifoldco/promptui" + "github.com/spf13/cobra" + "os" +) + +func CobraRunE(cmd *cobra.Command, args []string) error { + var err error + var profiles []node.ProfileInfo + + nodeDB, err := node.New() + if err != nil { + wwlog.Printf(wwlog.ERROR, "Could not open node configuration: %s\n", err) + os.Exit(1) + } + + if err != nil { + wwlog.Printf(wwlog.ERROR, "Cloud not get nodeList: %s\n", err) + os.Exit(1) + } + + if SetAll == true { + var tmp []node.ProfileInfo + tmp, err = nodeDB.FindAllProfiles() + if err != nil { + wwlog.Printf(wwlog.ERROR, "%s\n", err) + os.Exit(1) + } + + for _, p := range tmp { + profiles = append(profiles, p) + } + + } else if len(args) > 0 { + var tmp []node.ProfileInfo + tmp, err = nodeDB.FindAllProfiles() + if err != nil { + wwlog.Printf(wwlog.ERROR, "%s\n", err) + os.Exit(1) + } + + for _, a := range args { + for _, p := range tmp { + if p.Id == a { + profiles = append(profiles, p) + } + } + } + + } else { + cmd.Usage() + os.Exit(1) + } + + for _, p := range profiles { + + if SetDomainName != "" { + wwlog.Printf(wwlog.VERBOSE, "Profile: %s, Setting domain name to: %s\n", p.Id, SetDomainName) + + p.DomainName = SetDomainName + err := nodeDB.ProfileUpdate(p) + if err != nil { + wwlog.Printf(wwlog.ERROR, "%s\n", err) + os.Exit(1) + } + } + if SetVnfs != "" { + wwlog.Printf(wwlog.VERBOSE, "Profile: %s, Setting VNFS to: %s\n", p.Id, SetVnfs) + + p.Vnfs = SetVnfs + err := nodeDB.ProfileUpdate(p) + if err != nil { + wwlog.Printf(wwlog.ERROR, "%s\n", err) + os.Exit(1) + } + } + if SetKernel != "" { + wwlog.Printf(wwlog.VERBOSE, "Profile: %s, Setting Kernel version to: %s\n", p.Id, SetKernel) + + p.KernelVersion = SetKernel + err := nodeDB.ProfileUpdate(p) + if err != nil { + wwlog.Printf(wwlog.ERROR, "%s\n", err) + os.Exit(1) + } + } + if SetIpxe != "" { + wwlog.Printf(wwlog.VERBOSE, "Profile: %s, Setting iPXE template to: %s\n", p.Id, SetIpxe) + + p.Ipxe = SetIpxe + err := nodeDB.ProfileUpdate(p) + if err != nil { + wwlog.Printf(wwlog.ERROR, "%s\n", err) + os.Exit(1) + } + } + if SetRuntimeOverlay != "" { + wwlog.Printf(wwlog.VERBOSE, "Profile: %s, Setting runtime overlay to: %s\n", p.Id, SetRuntimeOverlay) + + p.RuntimeOverlay = SetRuntimeOverlay + err := nodeDB.ProfileUpdate(p) + if err != nil { + wwlog.Printf(wwlog.ERROR, "%s\n", err) + os.Exit(1) + } + } + if SetSystemOverlay != "" { + wwlog.Printf(wwlog.VERBOSE, "Profile: %s, Setting system overlay to: %s\n", p.Id, SetSystemOverlay) + + p.SystemOverlay = SetSystemOverlay + err := nodeDB.ProfileUpdate(p) + if err != nil { + wwlog.Printf(wwlog.ERROR, "%s\n", err) + os.Exit(1) + } + } + if SetIpmiUsername != "" { + wwlog.Printf(wwlog.VERBOSE, "Profile: %s, Setting IPMI username to: %s\n", p.Id, SetIpmiUsername) + + p.IpmiUserName = SetIpmiUsername + err := nodeDB.ProfileUpdate(p) + if err != nil { + wwlog.Printf(wwlog.ERROR, "%s\n", err) + os.Exit(1) + } + } + if SetIpmiPassword != "" { + wwlog.Printf(wwlog.VERBOSE, "Profile: %s, Setting IPMI username to: %s\n", p.Id, SetIpmiPassword) + + p.IpmiPassword = SetIpmiPassword + err := nodeDB.ProfileUpdate(p) + if err != nil { + wwlog.Printf(wwlog.ERROR, "%s\n", err) + os.Exit(1) + } + } + + } + + if len(profiles) > 0 { + q := fmt.Sprintf("Are you sure you want to modify %d group(s)", len(profiles)) + + prompt := promptui.Prompt{ + Label: q, + IsConfirm: true, + } + + result, _ := prompt.Run() + + if result == "y" || result == "yes" { + nodeDB.Persist() + } + + } else { + fmt.Printf("No profiles found\n") + } + + return nil +} \ No newline at end of file diff --git a/internal/app/wwctl/profile/set/root.go b/internal/app/wwctl/profile/set/root.go new file mode 100644 index 00000000..9f32cb39 --- /dev/null +++ b/internal/app/wwctl/profile/set/root.go @@ -0,0 +1,40 @@ +package set + +import "github.com/spf13/cobra" + +var ( + baseCmd = &cobra.Command{ + Use: "set", + Short: "Set profile configurations", + Long: "Profile configurations ", + RunE: CobraRunE, + } + SetAll bool + SetVnfs string + SetKernel string + SetDomainName string + SetIpxe string + SetRuntimeOverlay string + SetSystemOverlay string + SetIpmiUsername string + SetIpmiPassword string + +) + +func init() { + baseCmd.PersistentFlags().StringVarP(&SetVnfs, "vnfs", "V", "", "Set node Virtual Node File System (VNFS)") + baseCmd.PersistentFlags().StringVarP(&SetKernel, "kernel", "K", "", "Set Kernel version for nodes") + baseCmd.PersistentFlags().StringVarP(&SetDomainName, "domain", "D", "", "Set the node's domain name") + baseCmd.PersistentFlags().StringVarP(&SetIpxe, "ipxe", "P", "", "Set the node's iPXE template name") + baseCmd.PersistentFlags().StringVarP(&SetRuntimeOverlay, "runtime", "R", "", "Set the node's runtime overlay") + baseCmd.PersistentFlags().StringVarP(&SetSystemOverlay, "system", "S", "", "Set the node's system overlay") + baseCmd.PersistentFlags().StringVar(&SetIpmiUsername, "ipmiuser", "", "Set the node's IPMI username") + baseCmd.PersistentFlags().StringVar(&SetIpmiPassword, "ipmipass", "", "Set the node's IPMI password") + + baseCmd.PersistentFlags().BoolVarP(&SetAll, "all", "a", false, "Set all profiles") +} + +// GetRootCommand returns the root cobra.Command for the application. +func GetCommand() *cobra.Command { + return baseCmd +} diff --git a/internal/app/wwctl/root.go b/internal/app/wwctl/root.go index 3aeb3733..ee52e7dd 100644 --- a/internal/app/wwctl/root.go +++ b/internal/app/wwctl/root.go @@ -5,6 +5,7 @@ import ( "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/vnfs" "github.com/hpcng/warewulf/internal/pkg/wwlog" @@ -32,6 +33,7 @@ func init() { rootCmd.AddCommand(node.GetCommand()) rootCmd.AddCommand(kernel.GetCommand()) rootCmd.AddCommand(group.GetCommand()) + rootCmd.AddCommand(profile.GetCommand()) }