From 5a0c13225e22c3623740f583b51031d8ba115d5b Mon Sep 17 00:00:00 2001 From: Gregory Kurtzer Date: Tue, 15 Feb 2022 06:49:24 +0000 Subject: [PATCH 01/14] Utilize containerized kernel and remove kernel Support --- etc/ipxe/bigimage.ipxe | 6 +- etc/ipxe/default.ipxe | 3 +- internal/app/wwctl/container/list/main.go | 10 +- internal/app/wwctl/kernel/delete/main.go | 41 ---- internal/app/wwctl/kernel/delete/root.go | 33 --- internal/app/wwctl/kernel/imprt/main.go | 92 -------- internal/app/wwctl/kernel/imprt/root.go | 46 ---- internal/app/wwctl/kernel/list/main.go | 35 --- internal/app/wwctl/kernel/list/root.go | 23 -- internal/app/wwctl/kernel/root.go | 28 --- internal/app/wwctl/node/list/main.go | 5 +- internal/app/wwctl/node/set/main.go | 5 - internal/app/wwctl/node/set/root.go | 9 - internal/app/wwctl/profile/list/main.go | 1 - internal/app/wwctl/profile/set/main.go | 7 +- internal/app/wwctl/profile/set/root.go | 9 - internal/app/wwctl/root.go | 20 +- internal/pkg/container/kernel.go | 47 ++++ internal/pkg/kernel/kernel.go | 257 ---------------------- internal/pkg/node/constructors.go | 3 - internal/pkg/node/datastructure.go | 2 - internal/pkg/node/modifiers.go | 2 - internal/pkg/overlay/overlay.go | 1 - internal/pkg/warewulfd/ipxe.go | 1 - internal/pkg/warewulfd/kernel.go | 9 +- internal/pkg/warewulfd/kmods.go | 45 ---- internal/pkg/warewulfd/warewulfd.go | 1 - 27 files changed, 73 insertions(+), 668 deletions(-) delete mode 100644 internal/app/wwctl/kernel/delete/main.go delete mode 100644 internal/app/wwctl/kernel/delete/root.go delete mode 100644 internal/app/wwctl/kernel/imprt/main.go delete mode 100644 internal/app/wwctl/kernel/imprt/root.go delete mode 100644 internal/app/wwctl/kernel/list/main.go delete mode 100644 internal/app/wwctl/kernel/list/root.go delete mode 100644 internal/app/wwctl/kernel/root.go create mode 100644 internal/pkg/container/kernel.go delete mode 100644 internal/pkg/kernel/kernel.go delete mode 100644 internal/pkg/warewulfd/kmods.go diff --git a/etc/ipxe/bigimage.ipxe b/etc/ipxe/bigimage.ipxe index 1308b998..7527fbb9 100644 --- a/etc/ipxe/bigimage.ipxe +++ b/etc/ipxe/bigimage.ipxe @@ -11,13 +11,13 @@ echo set base http://{{.Ipaddr}}:{{.Port}} -kernel --name kernel ${base}/kernel/{{.Hwaddr}}?assetkey=${asset}&uuid=${uuid} || goto reboot +kernel --name kernel ${base}/kernel/{{.Hwaddr}}?assetkey=${asset}&uuid=${uuid} || goto reboot imgextract --name container ${base}/container/{{.Hwaddr}}?assetkey=${asset}&uuid=${uuid} || goto reboot -imgextract --name kmods ${base}/kmods/{{.Hwaddr}}?assetkey=${asset}&uuid=${uuid} || goto reboot imgextract --name system ${base}/overlay-system/{{.Hwaddr}}?assetkey=${asset}&uuid=${uuid} || goto reboot imgextract --name runtime ${base}/overlay-runtime/{{.Hwaddr}}?assetkey=${asset}&uuid=${uuid} || goto reboot +imgextract --name runtime ${base}/overlay-runtime/{{.Hwaddr}}?assetkey=${asset}&uuid=${uuid} || goto reboot -boot kernel initrd=container initrd=kmods initrd=system initrd=runtime wwid={{.Hwaddr}} {{.KernelArgs}} || goto reboot +boot kernel initrd=container initrd=system initrd=runtime wwid={{.Hwaddr}} {{.KernelArgs}} || goto reboot :reboot echo diff --git a/etc/ipxe/default.ipxe b/etc/ipxe/default.ipxe index 5014dec5..ef1d879f 100644 --- a/etc/ipxe/default.ipxe +++ b/etc/ipxe/default.ipxe @@ -13,11 +13,10 @@ set base http://{{.Ipaddr}}:{{.Port}} kernel --name kernel ${base}/kernel/{{.Hwaddr}}?assetkey=${asset}&uuid=${uuid} || goto reboot initrd --name container ${base}/container/{{.Hwaddr}}?assetkey=${asset}&uuid=${uuid} || goto reboot -initrd --name kmods ${base}/kmods/{{.Hwaddr}}?assetkey=${asset}&uuid=${uuid} || goto reboot initrd --name system ${base}/overlay-system/{{.Hwaddr}}?assetkey=${asset}&uuid=${uuid} || goto reboot initrd --name runtime ${base}/overlay-runtime/{{.Hwaddr}}?assetkey=${asset}&uuid=${uuid} || goto reboot -boot kernel initrd=container initrd=kmods initrd=system initrd=runtime wwid={{.Hwaddr}} {{.KernelArgs}} || goto reboot +boot kernel initrd=container initrd=system initrd=runtime wwid={{.Hwaddr}} {{.KernelArgs}} || goto reboot :reboot echo diff --git a/internal/app/wwctl/container/list/main.go b/internal/app/wwctl/container/list/main.go index 6568e192..f228a5f9 100644 --- a/internal/app/wwctl/container/list/main.go +++ b/internal/app/wwctl/container/list/main.go @@ -3,10 +3,10 @@ package list import ( "fmt" "os" + "path" "github.com/hpcng/warewulf/internal/pkg/container" "github.com/hpcng/warewulf/internal/pkg/node" - "github.com/hpcng/warewulf/internal/pkg/util" "github.com/hpcng/warewulf/internal/pkg/wwlog" "github.com/spf13/cobra" ) @@ -27,14 +27,14 @@ func CobraRunE(cmd *cobra.Command, args []string) error { nodemap[n.ContainerName.Get()]++ } - fmt.Printf("%-35s %-6s %-6s\n", "CONTAINER NAME", "BUILT", "NODES") + fmt.Printf("%-25s %-6s %-6s\n", "CONTAINER NAME", "NODES", "KERNEL") for _, source := range sources { - image := container.ImageFile(source) - if nodemap[source] == 0 { nodemap[source] = 0 } - fmt.Printf("%-35s %-6t %-6d\n", source, util.IsFile(image), nodemap[source]) + + kernel := container.KernelFind(source) + fmt.Printf("%-25s %-6d %s\n", source, nodemap[source], path.Base(kernel)) } return nil diff --git a/internal/app/wwctl/kernel/delete/main.go b/internal/app/wwctl/kernel/delete/main.go deleted file mode 100644 index c289a27d..00000000 --- a/internal/app/wwctl/kernel/delete/main.go +++ /dev/null @@ -1,41 +0,0 @@ -package delete - -import ( - "fmt" - "os" - - "github.com/hpcng/warewulf/internal/pkg/kernel" - "github.com/hpcng/warewulf/internal/pkg/node" - "github.com/hpcng/warewulf/internal/pkg/wwlog" - "github.com/spf13/cobra" -) - -func CobraRunE(cmd *cobra.Command, args []string) error { - - nodeDB, err := node.New() - if err != nil { - wwlog.Printf(wwlog.ERROR, "Could not open nodeDB: %s\n", err) - os.Exit(1) - } - - nodes, _ := nodeDB.FindAllNodes() - -ARG_LOOP: - for _, arg := range args { - for _, n := range nodes { - if n.KernelVersion.Get() == arg { - wwlog.Printf(wwlog.ERROR, "Kernel is configured for nodes, skipping: %s\n", arg) - continue ARG_LOOP - } - } - - err := kernel.DeleteKernel(arg) - if err != nil { - wwlog.Printf(wwlog.ERROR, "Could not delete kernel: %s\n", arg) - } else { - fmt.Printf("Kernel has been deleted: %s\n", arg) - } - } - - return nil -} diff --git a/internal/app/wwctl/kernel/delete/root.go b/internal/app/wwctl/kernel/delete/root.go deleted file mode 100644 index 5fc68bea..00000000 --- a/internal/app/wwctl/kernel/delete/root.go +++ /dev/null @@ -1,33 +0,0 @@ -package delete - -import ( - "github.com/hpcng/warewulf/internal/pkg/kernel" - "github.com/spf13/cobra" -) - -var ( - baseCmd = &cobra.Command{ - DisableFlagsInUseLine: true, - Use: "delete [OPTIONS] KERNEL [...]", - Short: "Delete imported kernels", - Long: "This command will delete KERNEL versions that have been imported into Warewulf.", - RunE: CobraRunE, - Args: cobra.MinimumNArgs(1), - ValidArgsFunction: func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { - if len(args) != 0 { - return nil, cobra.ShellCompDirectiveNoFileComp - } - list, _ := kernel.ListKernels() - return list, cobra.ShellCompDirectiveNoFileComp - }, - } -) - -func init() { - -} - -// GetRootCommand returns the root cobra.Command for the application. -func GetCommand() *cobra.Command { - return baseCmd -} diff --git a/internal/app/wwctl/kernel/imprt/main.go b/internal/app/wwctl/kernel/imprt/main.go deleted file mode 100644 index 97e3e219..00000000 --- a/internal/app/wwctl/kernel/imprt/main.go +++ /dev/null @@ -1,92 +0,0 @@ -package imprt - -import ( - "fmt" - "os" - - "github.com/hpcng/warewulf/internal/pkg/container" - "github.com/hpcng/warewulf/internal/pkg/kernel" - "github.com/hpcng/warewulf/internal/pkg/node" - "github.com/hpcng/warewulf/internal/pkg/warewulfd" - "github.com/hpcng/warewulf/internal/pkg/wwlog" - "github.com/pkg/errors" - "github.com/spf13/cobra" -) - -func CobraRunE(cmd *cobra.Command, args []string) error { - if len(args) == 0 && !OptDetect { - wwlog.Printf(wwlog.ERROR, "the '--detect' flag is needed, if no kernel version is suppiled") - os.Exit(1) - } - if OptDetect && (OptRoot == "" || OptContainer == "") { - wwlog.Printf(wwlog.ERROR, "the '--detect flag needs the '--container' or '--root' flag") - os.Exit(1) - } - // Checking if container flag was set, then overwriting OptRoot - if OptContainer != "" { - if container.ValidSource(OptContainer) { - OptRoot = container.RootFsDir(OptContainer) - } else { - wwlog.Printf(wwlog.ERROR, " %s is not a valid container", OptContainer) - os.Exit(1) - } - } - - var kernelVersion string - var err error - if len(args) > 0 { - kernelVersion = args[0] - } else { - kernelVersion, err = kernel.FindKernelVersion(OptRoot) - if err != nil { - wwlog.Printf(wwlog.ERROR, "could not detect kernel under %s\n", OptRoot) - os.Exit(1) - } - } - kernelName := kernelVersion - if len(args) > 1 { - kernelName = args[1] - } else if OptDetect && (OptContainer != "") { - kernelName = OptContainer - } - output, err := kernel.Build(kernelVersion, kernelName, OptRoot) - if err != nil { - wwlog.Printf(wwlog.ERROR, "Failed building kernel: %s\n", err) - os.Exit(1) - } else { - fmt.Printf("%s: %s\n", kernelName, output) - } - - if SetDefault { - - nodeDB, err := node.New() - if err != nil { - wwlog.Printf(wwlog.ERROR, "Could not open node configuration: %s\n", err) - os.Exit(1) - } - //TODO: Don't loop through profiles, instead have a nodeDB function that goes directly to the map - profiles, _ := nodeDB.FindAllProfiles() - for _, profile := range profiles { - wwlog.Printf(wwlog.DEBUG, "Looking for profile default: %s\n", profile.Id.Get()) - if profile.Id.Get() == "default" { - wwlog.Printf(wwlog.DEBUG, "Found profile default, setting kernel version to: %s\n", args[0]) - profile.KernelVersion.Set(args[0]) - err := nodeDB.ProfileUpdate(profile) - if err != nil { - return errors.Wrap(err, "failed to update node profile") - } - } - } - err = nodeDB.Persist() - if err != nil { - return errors.Wrap(err, "failed to persist nodedb") - } - fmt.Printf("Set default kernel version to: %s\n", args[0]) - err = warewulfd.DaemonReload() - if err != nil { - return errors.Wrap(err, "failed to reload warewulf daemon") - } - } - - return nil -} diff --git a/internal/app/wwctl/kernel/imprt/root.go b/internal/app/wwctl/kernel/imprt/root.go deleted file mode 100644 index c8521a7b..00000000 --- a/internal/app/wwctl/kernel/imprt/root.go +++ /dev/null @@ -1,46 +0,0 @@ -package imprt - -import ( - "log" - - "github.com/hpcng/warewulf/internal/pkg/container" - "github.com/spf13/cobra" -) - -var ( - baseCmd = &cobra.Command{ - DisableFlagsInUseLine: true, - Use: "import [OPTIONS] KERNEL", - Short: "Import Kernel version into Warewulf", - Long: "This will import a boot KERNEL version from the control node into Warewulf", - RunE: CobraRunE, - Args: cobra.MinimumNArgs(0), - } - BuildAll bool - ByNode bool - SetDefault bool - OptRoot string - OptContainer string - OptDetect bool -) - -func init() { - baseCmd.PersistentFlags().BoolVarP(&BuildAll, "all", "a", false, "Build all overlays (runtime and system)") - baseCmd.PersistentFlags().BoolVarP(&ByNode, "node", "n", false, "Build overlay for a particular node(s)") - baseCmd.PersistentFlags().BoolVar(&SetDefault, "setdefault", false, "Set this kernel for the default profile") - baseCmd.PersistentFlags().StringVarP(&OptRoot, "root", "r", "/", "Import kernel from root (chroot) directory") - baseCmd.PersistentFlags().StringVarP(&OptContainer, "container", "C", "", "Import kernel from container") - err := baseCmd.RegisterFlagCompletionFunc("container", func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { - list, _ := container.ListSources() - return list, cobra.ShellCompDirectiveNoFileComp - }) - if err != nil { - log.Println(err) - } - baseCmd.PersistentFlags().BoolVarP(&OptDetect, "detect", "D", false, "Try to detect the kernel version in an automated way, needs the -C or -r option") -} - -// GetRootCommand returns the root cobra.Command for the application. -func GetCommand() *cobra.Command { - return baseCmd -} diff --git a/internal/app/wwctl/kernel/list/main.go b/internal/app/wwctl/kernel/list/main.go deleted file mode 100644 index a3a8d4ad..00000000 --- a/internal/app/wwctl/kernel/list/main.go +++ /dev/null @@ -1,35 +0,0 @@ -package list - -import ( - "fmt" - "os" - - "github.com/hpcng/warewulf/internal/pkg/kernel" - "github.com/hpcng/warewulf/internal/pkg/node" - "github.com/hpcng/warewulf/internal/pkg/wwlog" - "github.com/spf13/cobra" -) - -func CobraRunE(cmd *cobra.Command, args []string) error { - - kernels, err := kernel.ListKernels() - if err != nil { - wwlog.Printf(wwlog.ERROR, "%s\n", err) - os.Exit(1) - } - - nconfig, _ := node.New() - nodes, _ := nconfig.FindAllNodes() - nodemap := make(map[string]int) - - for _, n := range nodes { - nodemap[n.KernelVersion.Get()]++ - } - - fmt.Printf("%-35s %-25s %-6s\n", "KERNEL NAME", "KERNEL VERSION", "NODES") - for _, k := range kernels { - fmt.Printf("%-35s %-25s %6d\n", k, kernel.GetKernelVersion(k), nodemap[k]) - } - - return nil -} diff --git a/internal/app/wwctl/kernel/list/root.go b/internal/app/wwctl/kernel/list/root.go deleted file mode 100644 index fba84101..00000000 --- a/internal/app/wwctl/kernel/list/root.go +++ /dev/null @@ -1,23 +0,0 @@ -package list - -import "github.com/spf13/cobra" - -var ( - baseCmd = &cobra.Command{ - DisableFlagsInUseLine: true, - Use: "list [OPTIONS]", - Short: "List imported Kernel images", - Long: "This command will list the kernels that have been imported into Warewulf.", - RunE: CobraRunE, - Args: cobra.ExactArgs(0), - Aliases: []string{"ls"}, - } -) - -func init() { -} - -// GetRootCommand returns the root cobra.Command for the application. -func GetCommand() *cobra.Command { - return baseCmd -} diff --git a/internal/app/wwctl/kernel/root.go b/internal/app/wwctl/kernel/root.go deleted file mode 100644 index bb0cdb8d..00000000 --- a/internal/app/wwctl/kernel/root.go +++ /dev/null @@ -1,28 +0,0 @@ -package kernel - -import ( - "github.com/hpcng/warewulf/internal/app/wwctl/kernel/delete" - "github.com/hpcng/warewulf/internal/app/wwctl/kernel/imprt" - "github.com/hpcng/warewulf/internal/app/wwctl/kernel/list" - "github.com/spf13/cobra" -) - -var ( - baseCmd = &cobra.Command{ - DisableFlagsInUseLine: true, - Use: "kernel COMMAND [OPTIONS]", - Short: "Kernel Image Management", - Long: "This command manages Warewulf Kernels used for bootstrapping nodes", - } -) - -func init() { - baseCmd.AddCommand(imprt.GetCommand()) - baseCmd.AddCommand(list.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/node/list/main.go b/internal/app/wwctl/node/list/main.go index 0e6845c8..76db8201 100644 --- a/internal/app/wwctl/node/list/main.go +++ b/internal/app/wwctl/node/list/main.go @@ -41,7 +41,6 @@ func CobraRunE(cmd *cobra.Command, args []string) error { fmt.Printf("%-20s %-18s %-12s %t\n", node.Id.Get(), "Discoverable", node.Discoverable.Source(), node.Discoverable.PrintB()) fmt.Printf("%-20s %-18s %-12s %s\n", node.Id.Get(), "Container", node.ContainerName.Source(), node.ContainerName.Print()) - fmt.Printf("%-20s %-18s %-12s %s\n", node.Id.Get(), "Kernel", node.KernelVersion.Source(), node.KernelVersion.Print()) fmt.Printf("%-20s %-18s %-12s %s\n", node.Id.Get(), "KernelArgs", node.KernelArgs.Source(), node.KernelArgs.Print()) fmt.Printf("%-20s %-18s %-12s %s\n", node.Id.Get(), "SystemOverlay", node.SystemOverlay.Source(), node.SystemOverlay.Print()) fmt.Printf("%-20s %-18s %-12s %s\n", node.Id.Get(), "RuntimeOverlay", node.RuntimeOverlay.Source(), node.RuntimeOverlay.Print()) @@ -97,11 +96,11 @@ func CobraRunE(cmd *cobra.Command, args []string) error { } } else if ShowLong { - fmt.Printf("%-22s %-26s %-35s %s\n", "NODE NAME", "KERNEL", "CONTAINER", "OVERLAYS (S/R)") + fmt.Printf("%-22s %-35s %s\n", "NODE NAME", "CONTAINER", "OVERLAYS (S/R)") fmt.Println(strings.Repeat("=", 120)) for _, node := range node.FilterByName(nodes, args) { - fmt.Printf("%-22s %-26s %-35s %s\n", node.Id.Get(), node.KernelVersion.Print(), node.ContainerName.Print(), node.SystemOverlay.Print()+"/"+node.RuntimeOverlay.Print()) + fmt.Printf("%-22s %-35s %s\n", node.Id.Get(), node.ContainerName.Print(), node.SystemOverlay.Print()+"/"+node.RuntimeOverlay.Print()) } } else { diff --git a/internal/app/wwctl/node/set/main.go b/internal/app/wwctl/node/set/main.go index 59f3e7c5..2e2c4861 100644 --- a/internal/app/wwctl/node/set/main.go +++ b/internal/app/wwctl/node/set/main.go @@ -70,11 +70,6 @@ func CobraRunE(cmd *cobra.Command, args []string) error { n.AssetKey.Set(SetAssetKey) } - if SetKernel != "" { - wwlog.Printf(wwlog.VERBOSE, "Node: %s, Setting kernel to: %s\n", n.Id.Get(), SetKernel) - n.KernelVersion.Set(SetKernel) - } - if SetKernelArgs != "" { wwlog.Printf(wwlog.VERBOSE, "Node: %s, Setting kernel args to: %s\n", n.Id.Get(), SetKernelArgs) n.KernelArgs.Set(SetKernelArgs) diff --git a/internal/app/wwctl/node/set/root.go b/internal/app/wwctl/node/set/root.go index a3feec62..0dcbc865 100644 --- a/internal/app/wwctl/node/set/root.go +++ b/internal/app/wwctl/node/set/root.go @@ -4,7 +4,6 @@ import ( "log" "github.com/hpcng/warewulf/internal/pkg/container" - "github.com/hpcng/warewulf/internal/pkg/kernel" "github.com/hpcng/warewulf/internal/pkg/node" "github.com/hpcng/warewulf/internal/pkg/overlay" "github.com/spf13/cobra" @@ -34,7 +33,6 @@ var ( } SetComment string SetContainer string - SetKernel string SetKernelArgs string SetNetName string SetNetDev string @@ -82,13 +80,6 @@ func init() { }); err != nil { log.Println(err) } - baseCmd.PersistentFlags().StringVarP(&SetKernel, "kernel", "K", "", "Set Kernel version for nodes") - if err := baseCmd.RegisterFlagCompletionFunc("kernel", func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { - list, _ := kernel.ListKernels() - return list, cobra.ShellCompDirectiveNoFileComp - }); err != nil { - log.Println(err) - } baseCmd.PersistentFlags().StringVarP(&SetKernelArgs, "kernelargs", "A", "", "Set Kernel argument for nodes") baseCmd.PersistentFlags().StringVarP(&SetClusterName, "cluster", "c", "", "Set the node's cluster group") baseCmd.PersistentFlags().StringVar(&SetIpxe, "ipxe", "", "Set the node's iPXE template name") diff --git a/internal/app/wwctl/profile/list/main.go b/internal/app/wwctl/profile/list/main.go index a419952e..d1120cbc 100644 --- a/internal/app/wwctl/profile/list/main.go +++ b/internal/app/wwctl/profile/list/main.go @@ -33,7 +33,6 @@ func CobraRunE(cmd *cobra.Command, args []string) error { fmt.Printf("%-20s %-18s %s\n", profile.Id.Get(), "Cluster", profile.ClusterName.Print()) fmt.Printf("%-20s %-18s %s\n", profile.Id.Get(), "Container", profile.ContainerName.Print()) - fmt.Printf("%-20s %-18s %s\n", profile.Id.Get(), "Kernel", profile.KernelVersion.Print()) fmt.Printf("%-20s %-18s %s\n", profile.Id.Get(), "KernelArgs", profile.KernelArgs.Print()) fmt.Printf("%-20s %-18s %s\n", profile.Id.Get(), "Init", profile.Init.Print()) fmt.Printf("%-20s %-18s %s\n", profile.Id.Get(), "Root", profile.Root.Print()) diff --git a/internal/app/wwctl/profile/set/main.go b/internal/app/wwctl/profile/set/main.go index 09d4c288..e4957be3 100644 --- a/internal/app/wwctl/profile/set/main.go +++ b/internal/app/wwctl/profile/set/main.go @@ -75,13 +75,8 @@ func CobraRunE(cmd *cobra.Command, args []string) error { p.AssetKey.Set(SetAssetKey) } - if SetKernel != "" { - wwlog.Printf(wwlog.VERBOSE, "Profile: %s, Setting Kernel to: %s\n", p.Id.Get(), SetKernel) - p.KernelVersion.Set(SetKernel) - } - if SetKernelArgs != "" { - wwlog.Printf(wwlog.VERBOSE, "Profile: %s, Setting Kernel args to: %s\n", p.Id.Get(), SetKernelArgs) + wwlog.Printf(wwlog.VERBOSE, "Profile: %s, Setting kernel args to: %s\n", p.Id.Get(), SetKernelArgs) p.KernelArgs.Set(SetKernelArgs) } diff --git a/internal/app/wwctl/profile/set/root.go b/internal/app/wwctl/profile/set/root.go index d8b08dc6..e7da4c20 100644 --- a/internal/app/wwctl/profile/set/root.go +++ b/internal/app/wwctl/profile/set/root.go @@ -4,7 +4,6 @@ import ( "log" "github.com/hpcng/warewulf/internal/pkg/container" - "github.com/hpcng/warewulf/internal/pkg/kernel" "github.com/hpcng/warewulf/internal/pkg/node" "github.com/hpcng/warewulf/internal/pkg/overlay" "github.com/spf13/cobra" @@ -37,7 +36,6 @@ var ( SetForce bool SetComment string SetContainer string - SetKernel string SetKernelArgs string SetClusterName string SetIpxe string @@ -79,13 +77,6 @@ func init() { }); err != nil { log.Println(err) } - baseCmd.PersistentFlags().StringVarP(&SetKernel, "kernel", "K", "", "Set Kernel version for nodes") - if err := baseCmd.RegisterFlagCompletionFunc("kernel", func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { - list, _ := kernel.ListKernels() - return list, cobra.ShellCompDirectiveNoFileComp - }); err != nil { - log.Println(err) - } baseCmd.PersistentFlags().StringVarP(&SetKernelArgs, "kernelargs", "A", "", "Set Kernel argument for nodes") baseCmd.PersistentFlags().StringVarP(&SetClusterName, "cluster", "c", "", "Set the node's cluster group") baseCmd.PersistentFlags().StringVarP(&SetIpxe, "ipxe", "P", "", "Set the node's iPXE template name") diff --git a/internal/app/wwctl/root.go b/internal/app/wwctl/root.go index 059b38db..f6e7137d 100644 --- a/internal/app/wwctl/root.go +++ b/internal/app/wwctl/root.go @@ -3,15 +3,14 @@ package wwctl import ( "github.com/hpcng/warewulf/internal/app/wwctl/configure" "github.com/hpcng/warewulf/internal/app/wwctl/container" - "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/power" "github.com/hpcng/warewulf/internal/app/wwctl/profile" "github.com/hpcng/warewulf/internal/app/wwctl/server" "github.com/hpcng/warewulf/internal/app/wwctl/version" - "github.com/hpcng/warewulf/internal/pkg/wwlog" "github.com/hpcng/warewulf/internal/pkg/help" + "github.com/hpcng/warewulf/internal/pkg/wwlog" "github.com/spf13/cobra" "github.com/spf13/cobra/doc" @@ -21,12 +20,12 @@ import ( var ( rootCmd = &cobra.Command{ DisableFlagsInUseLine: true, - Use: "wwctl COMMAND [OPTIONS]", - Short: "Warewulf Control", - Long: "Control interface to the Warewulf Cluster Provisioning System.", - PersistentPreRunE: rootPersistentPreRunE, - SilenceUsage: true, - SilenceErrors: true, + Use: "wwctl COMMAND [OPTIONS]", + Short: "Warewulf Control", + Long: "Control interface to the Warewulf Cluster Provisioning System.", + PersistentPreRunE: rootPersistentPreRunE, + SilenceUsage: true, + SilenceErrors: true, } verboseArg bool DebugFlag bool @@ -36,13 +35,12 @@ func init() { rootCmd.PersistentFlags().BoolVarP(&verboseArg, "verbose", "v", false, "Run with increased verbosity.") rootCmd.PersistentFlags().BoolVarP(&DebugFlag, "debug", "d", false, "Run with debugging messages enabled.") - rootCmd.SetUsageTemplate(help.UsageTemplate) - rootCmd.SetHelpTemplate(help.HelpTemplate) + rootCmd.SetUsageTemplate(help.UsageTemplate) + rootCmd.SetHelpTemplate(help.HelpTemplate) rootCmd.AddCommand(overlay.GetCommand()) rootCmd.AddCommand(container.GetCommand()) rootCmd.AddCommand(node.GetCommand()) - rootCmd.AddCommand(kernel.GetCommand()) rootCmd.AddCommand(power.GetCommand()) rootCmd.AddCommand(profile.GetCommand()) rootCmd.AddCommand(configure.GetCommand()) diff --git a/internal/pkg/container/kernel.go b/internal/pkg/container/kernel.go new file mode 100644 index 00000000..e1279e60 --- /dev/null +++ b/internal/pkg/container/kernel.go @@ -0,0 +1,47 @@ +package container + +import ( + "path" + "path/filepath" + "sort" + + "github.com/hpcng/warewulf/internal/pkg/wwlog" +) + +var ( + kernelSearchPaths = []string{ + // This is a printf format where the %s will be the kernel version + "/boot/vmlinuz-*", + "/lib/modules/*/vmlinuz*", + } +) + +func KernelFind(container string) string { + container_path := RootFsDir(container) + if container_path == "" { + return "" + } + + for _, searchPath := range kernelSearchPaths { + + check_path := path.Join(container_path, searchPath) + + wwlog.Printf(wwlog.DEBUG, "Searching for kernel(s) at: %s\n", check_path) + kernels, err := filepath.Glob(check_path) + if err != nil { + return "" + } + + if len(kernels) > 1 { + sort.Slice(kernels, func(i, j int) bool { + return kernels[i] > kernels[j] + }) + wwlog.Printf(wwlog.VERBOSE, "Multiple kernels found in container: %s\n", container) + return kernels[0] + } else if len(kernels) == 1 { + return kernels[0] + } + + } + return "NOT_FOUND" +} diff --git a/internal/pkg/kernel/kernel.go b/internal/pkg/kernel/kernel.go deleted file mode 100644 index 37941032..00000000 --- a/internal/pkg/kernel/kernel.go +++ /dev/null @@ -1,257 +0,0 @@ -package kernel - -import ( - "compress/gzip" - "fmt" - "io" - "io/ioutil" - "os" - "os/exec" - "path" - "path/filepath" - "regexp" - - "github.com/pkg/errors" - - "github.com/hpcng/warewulf/internal/pkg/buildconfig" - "github.com/hpcng/warewulf/internal/pkg/util" - "github.com/hpcng/warewulf/internal/pkg/wwlog" -) - -var ( - kernelSearchPaths = []string{ - // This is a printf format where the %s will be the kernel version - "/boot/vmlinuz-%s", - "/boot/vmlinuz-%s.gz", - "/lib/mmodules/%s/vmlinuz", - "/lib/mmodules/%s/vmlinuz.gz", - } -) - -func KernelImageTopDir() string { - return path.Join(buildconfig.WWPROVISIONDIR(), "kernel") -} - -func KernelImage(kernelName string) string { - if kernelName == "" { - wwlog.Printf(wwlog.ERROR, "Kernel Name is not defined\n") - return "" - } - - if !util.ValidString(kernelName, "^[a-zA-Z0-9-._]+$") { - wwlog.Printf(wwlog.ERROR, "Runtime overlay name contains illegal characters: %s\n", kernelName) - return "" - } - - return path.Join(KernelImageTopDir(), kernelName, "vmlinuz") -} - -func GetKernelVersion(kernelName string) string { - if kernelName == "" { - wwlog.Printf(wwlog.ERROR, "Kernel Name is not defined\n") - return "" - } - kernelVersion, err := ioutil.ReadFile(KernelVersionFile(kernelName)) - if err != nil { - return "" - } - return string(kernelVersion) -} - -func KmodsImage(kernelName string) string { - if kernelName == "" { - wwlog.Printf(wwlog.ERROR, "Kernel Name is not defined\n") - return "" - } - - if !util.ValidString(kernelName, "^[a-zA-Z0-9-._]+$") { - wwlog.Printf(wwlog.ERROR, "Runtime overlay name contains illegal characters: %s\n", kernelName) - return "" - } - - return path.Join(KernelImageTopDir(), kernelName, "kmods.img") -} - -func KernelVersionFile(kernelName string) string { - if kernelName == "" { - wwlog.Printf(wwlog.ERROR, "Kernel Name is not defined\n") - return "" - } - - if !util.ValidString(kernelName, "^[a-zA-Z0-9-._]+$") { - wwlog.Printf(wwlog.ERROR, "Runtime overlay name contains illegal characters: %s\n", kernelName) - return "" - } - - return path.Join(KernelImageTopDir(), kernelName, "version") -} - -func ListKernels() ([]string, error) { - var ret []string - - err := os.MkdirAll(KernelImageTopDir(), 0755) - if err != nil { - return ret, errors.New("Could not create Kernel parent directory: " + KernelImageTopDir()) - } - - wwlog.Printf(wwlog.DEBUG, "Searching for Kernel image directories: %s\n", KernelImageTopDir()) - - kernels, err := ioutil.ReadDir(KernelImageTopDir()) - if err != nil { - return ret, err - } - - for _, kernel := range kernels { - wwlog.Printf(wwlog.VERBOSE, "Found Kernel: %s\n", kernel.Name()) - - ret = append(ret, kernel.Name()) - - } - - return ret, nil -} - -func Build(kernelVersion, kernelName, root string) (string, error) { - kernelDrivers := path.Join(root, "/lib/modules/", kernelVersion) - kernelDriversRelative := path.Join("/lib/modules/", kernelVersion) - kernelDestination := KernelImage(kernelName) - driversDestination := KmodsImage(kernelName) - versionDestination := KernelVersionFile(kernelName) - var kernelSource string - - // Create the destination paths just in case it doesn't exist - err := os.MkdirAll(path.Dir(kernelDestination), 0755) - if err != nil { - return "", errors.Wrap(err, "failed to create kernel dest") - } - - err = os.MkdirAll(path.Dir(driversDestination), 0755) - if err != nil { - return "", errors.Wrap(err, "failed to create driver dest") - } - - err = os.MkdirAll(path.Dir(versionDestination), 0755) - if err != nil { - return "", fmt.Errorf("failed to create version dest: %s", err) - } - - for _, searchPath := range kernelSearchPaths { - testPath := fmt.Sprintf(path.Join(root, searchPath), kernelVersion) - wwlog.Printf(wwlog.VERBOSE, "Looking for kernel at: %s\n", testPath) - if util.IsFile(testPath) { - kernelSource = testPath - break - } - } - - if kernelSource == "" { - wwlog.Printf(wwlog.ERROR, "Could not locate kernel image\n") - return "", errors.New("could not locate kernel image") - } else { - wwlog.Printf(wwlog.INFO, "Found kernel at: %s\n", kernelSource) - } - - if !util.IsDir(kernelDrivers) { - return "", errors.New("Could not locate kernel drivers") - } - - wwlog.Printf(wwlog.VERBOSE, "Setting up Kernel\n") - if _, err := os.Stat(kernelSource); err == nil { - kernel, err := os.Open(kernelSource) - if err != nil { - return "", errors.Wrap(err, "could not open kernel") - } - defer kernel.Close() - - gzipreader, err := gzip.NewReader(kernel) - if err == nil { - defer gzipreader.Close() - - writer, err := os.Create(kernelDestination) - if err != nil { - return "", errors.Wrap(err, "could not decompress kernel") - } - defer writer.Close() - - _, err = io.Copy(writer, gzipreader) - if err != nil { - return "", errors.Wrap(err, "could not write decompressed kernel") - } - - } else { - - err := util.CopyFile(kernelSource, kernelDestination) - if err != nil { - return "", errors.Wrap(err, "could not copy kernel") - } - } - - } - - wwlog.Printf(wwlog.VERBOSE, "Building Kernel driver image\n") - if _, err := os.Stat(kernelDrivers); err == nil { - compressor, err := exec.LookPath("pigz") - if err != nil { - wwlog.Printf(wwlog.VERBOSE, "Could not locate PIGZ, using GZIP\n") - compressor = "gzip" - } else { - wwlog.Printf(wwlog.VERBOSE, "Using PIGZ to compress the container: %s\n", compressor) - } - - cmd := fmt.Sprintf("cd %s; find .%s | cpio --quiet -o -L -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() - if err != nil { - return "", err - } - } - - wwlog.Printf(wwlog.VERBOSE, "Creating version file\n") - file, err := os.Create(versionDestination) - if err != nil { - return "", errors.Wrap(err, "Failed to create version file") - } - defer file.Close() - _, err = io.WriteString(file, kernelVersion) - if err != nil { - return "", errors.Wrap(err, "Could not write kernel version") - } - err = file.Sync() - if err != nil { - return "", errors.Wrap(err, "Could not sync kernel version") - } - return "Done", nil -} - -func DeleteKernel(name string) error { - fullPath := path.Join(KernelImageTopDir(), name) - - wwlog.Printf(wwlog.VERBOSE, "Removing path: %s\n", fullPath) - return os.RemoveAll(fullPath) -} - -func FindKernelVersion(root string) (string, error) { - for _, searchPath := range kernelSearchPaths { - testPattern := fmt.Sprintf(path.Join(root, searchPath), `*`) - wwlog.Printf(wwlog.VERBOSE, "Looking for kernel version with pattern at: %s\n", testPattern) - potentialKernel, _ := filepath.Glob(testPattern) - if len(potentialKernel) == 0 { - continue - } - for _, foundKernel := range potentialKernel { - wwlog.Printf(wwlog.VERBOSE, "Parsing out kernel version for %s\n", foundKernel) - re := regexp.MustCompile(fmt.Sprintf(path.Join(root, searchPath), `([\w\d-\.]*)`)) - version := re.FindAllStringSubmatch(foundKernel, -1) - if version == nil { - return "", fmt.Errorf("could not parse kernel version") - } - wwlog.Printf(wwlog.VERBOSE, "found kernel version %s\n", version) - return version[0][1], nil - - } - - } - return "", fmt.Errorf("could not find kernel version") - -} diff --git a/internal/pkg/node/constructors.go b/internal/pkg/node/constructors.go index ebf35397..1f73bd98 100644 --- a/internal/pkg/node/constructors.go +++ b/internal/pkg/node/constructors.go @@ -72,7 +72,6 @@ func (config *nodeYaml) FindAllNodes() ([]NodeInfo, error) { n.Id.Set(nodename) n.Comment.Set(node.Comment) n.ContainerName.Set(node.ContainerName) - n.KernelVersion.Set(node.KernelVersion) n.KernelArgs.Set(node.KernelArgs) n.ClusterName.Set(node.ClusterName) n.Ipxe.Set(node.Ipxe) @@ -134,7 +133,6 @@ func (config *nodeYaml) FindAllNodes() ([]NodeInfo, error) { n.Comment.SetAlt(config.NodeProfiles[p].Comment, p) n.ClusterName.SetAlt(config.NodeProfiles[p].ClusterName, p) n.ContainerName.SetAlt(config.NodeProfiles[p].ContainerName, p) - n.KernelVersion.SetAlt(config.NodeProfiles[p].KernelVersion, p) n.KernelArgs.SetAlt(config.NodeProfiles[p].KernelArgs, p) n.Ipxe.SetAlt(config.NodeProfiles[p].Ipxe, p) n.Init.SetAlt(config.NodeProfiles[p].Init, p) @@ -218,7 +216,6 @@ func (config *nodeYaml) FindAllProfiles() ([]NodeInfo, error) { p.ContainerName.Set(profile.ContainerName) p.Ipxe.Set(profile.Ipxe) p.Init.Set(profile.Init) - p.KernelVersion.Set(profile.KernelVersion) p.KernelArgs.Set(profile.KernelArgs) p.IpmiNetmask.Set(profile.IpmiNetmask) p.IpmiPort.Set(profile.IpmiPort) diff --git a/internal/pkg/node/datastructure.go b/internal/pkg/node/datastructure.go index 7b273f82..a55b71f1 100644 --- a/internal/pkg/node/datastructure.go +++ b/internal/pkg/node/datastructure.go @@ -19,7 +19,6 @@ type NodeConf struct { ClusterName string `yaml:"cluster name,omitempty"` ContainerName string `yaml:"container name,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"` @@ -71,7 +70,6 @@ type NodeInfo struct { ClusterName Entry ContainerName Entry Ipxe Entry - KernelVersion Entry KernelArgs Entry IpmiIpaddr Entry IpmiNetmask Entry diff --git a/internal/pkg/node/modifiers.go b/internal/pkg/node/modifiers.go index 6502be84..2a147a5d 100644 --- a/internal/pkg/node/modifiers.go +++ b/internal/pkg/node/modifiers.go @@ -60,7 +60,6 @@ func (config *nodeYaml) NodeUpdate(node NodeInfo) error { config.Nodes[nodeID].ClusterName = node.ClusterName.GetReal() config.Nodes[nodeID].Ipxe = node.Ipxe.GetReal() config.Nodes[nodeID].Init = node.Init.GetReal() - config.Nodes[nodeID].KernelVersion = node.KernelVersion.GetReal() config.Nodes[nodeID].KernelArgs = node.KernelArgs.GetReal() config.Nodes[nodeID].IpmiIpaddr = node.IpmiIpaddr.GetReal() config.Nodes[nodeID].IpmiNetmask = node.IpmiNetmask.GetReal() @@ -148,7 +147,6 @@ func (config *nodeYaml) ProfileUpdate(profile NodeInfo) error { config.NodeProfiles[profileID].Ipxe = profile.Ipxe.GetReal() config.NodeProfiles[profileID].Init = profile.Init.GetReal() config.NodeProfiles[profileID].ClusterName = profile.ClusterName.GetReal() - config.NodeProfiles[profileID].KernelVersion = profile.KernelVersion.GetReal() config.NodeProfiles[profileID].KernelArgs = profile.KernelArgs.GetReal() config.NodeProfiles[profileID].IpmiIpaddr = profile.IpmiIpaddr.GetReal() config.NodeProfiles[profileID].IpmiNetmask = profile.IpmiNetmask.GetReal() diff --git a/internal/pkg/overlay/overlay.go b/internal/pkg/overlay/overlay.go index 36083519..08a72065 100644 --- a/internal/pkg/overlay/overlay.go +++ b/internal/pkg/overlay/overlay.go @@ -174,7 +174,6 @@ func BuildOverlay(nodeInfo node.NodeInfo, overlayName string) error { tstruct.Hostname = nodeInfo.Id.Get() tstruct.ClusterName = nodeInfo.ClusterName.Get() tstruct.Container = nodeInfo.ContainerName.Get() - tstruct.KernelVersion = nodeInfo.KernelVersion.Get() tstruct.KernelArgs = nodeInfo.KernelArgs.Get() tstruct.Init = nodeInfo.Init.Get() tstruct.Root = nodeInfo.Root.Get() diff --git a/internal/pkg/warewulfd/ipxe.go b/internal/pkg/warewulfd/ipxe.go index 84c11808..1cb3d605 100644 --- a/internal/pkg/warewulfd/ipxe.go +++ b/internal/pkg/warewulfd/ipxe.go @@ -140,7 +140,6 @@ func IpxeSend(w http.ResponseWriter, req *http.Request) { replace.Hwaddr = rinfo.hwaddr replace.ContainerName = node.ContainerName.Get() replace.KernelArgs = node.KernelArgs.Get() - replace.KernelVersion = node.KernelVersion.Get() err = tmpl.Execute(w, replace) if err != nil { diff --git a/internal/pkg/warewulfd/kernel.go b/internal/pkg/warewulfd/kernel.go index 22958f5f..74286ee7 100644 --- a/internal/pkg/warewulfd/kernel.go +++ b/internal/pkg/warewulfd/kernel.go @@ -2,9 +2,10 @@ package warewulfd import ( "net/http" + "path" "strings" - "github.com/hpcng/warewulf/internal/pkg/kernel" + "github.com/hpcng/warewulf/internal/pkg/container" ) func KernelSend(w http.ResponseWriter, req *http.Request) { @@ -28,10 +29,10 @@ func KernelSend(w http.ResponseWriter, req *http.Request) { return } - if node.KernelVersion.Defined() { - fileName := kernel.KernelImage(node.KernelVersion.Get()) + if node.ContainerName.Defined() { + fileName := container.KernelFind(node.ContainerName.Get()) - updateStatus(node.Id.Get(), "KERNEL", node.KernelVersion.Get(), strings.Split(req.RemoteAddr, ":")[0]) + updateStatus(node.Id.Get(), "KERNEL", path.Base(fileName), strings.Split(req.RemoteAddr, ":")[0]) err := sendFile(w, fileName, node.Id.Get()) if err != nil { diff --git a/internal/pkg/warewulfd/kmods.go b/internal/pkg/warewulfd/kmods.go deleted file mode 100644 index 13ace42b..00000000 --- a/internal/pkg/warewulfd/kmods.go +++ /dev/null @@ -1,45 +0,0 @@ -package warewulfd - -import ( - "net/http" - "strings" - - "github.com/hpcng/warewulf/internal/pkg/kernel" -) - -func KmodsSend(w http.ResponseWriter, req *http.Request) { - rinfo, err := parseReq(req) - if err != nil { - w.WriteHeader(404) - daemonLogf("ERROR: %s\n", err) - return - } - node, err := GetNode(rinfo.hwaddr) - if err != nil { - w.WriteHeader(403) - daemonLogf("ERROR(%s): %s\n", rinfo.hwaddr, err) - return - } - - if node.AssetKey.Defined() && node.AssetKey.Get() != rinfo.assetkey { - w.WriteHeader(404) - daemonLogf("ERROR: Incorrect asset key for node: %s\n", node.Id.Get()) - updateStatus(node.Id.Get(), "KMODS_OVERLAY", "BAD_ASSET", rinfo.ipaddr) - return - } - - if node.KernelVersion.Defined() { - fileName := kernel.KmodsImage(node.KernelVersion.Get()) - - updateStatus(node.Id.Get(), "KMODS_OVERLAY", node.KernelVersion.Get()+".img", strings.Split(req.RemoteAddr, ":")[0]) - - err := sendFile(w, fileName, node.Id.Get()) - if err != nil { - daemonLogf("ERROR: %s\n", err) - } - - } else { - w.WriteHeader(503) - daemonLogf("WARNING: No 'kernel version' set for node %s\n", node.Id.Get()) - } -} diff --git a/internal/pkg/warewulfd/warewulfd.go b/internal/pkg/warewulfd/warewulfd.go index 1600a637..7406d782 100644 --- a/internal/pkg/warewulfd/warewulfd.go +++ b/internal/pkg/warewulfd/warewulfd.go @@ -48,7 +48,6 @@ func RunServer() error { http.HandleFunc("/ipxe/", IpxeSend) http.HandleFunc("/kernel/", KernelSend) - http.HandleFunc("/kmods/", KmodsSend) http.HandleFunc("/container/", ContainerSend) http.HandleFunc("/overlay-system/", SystemOverlaySend) http.HandleFunc("/overlay-runtime/", RuntimeOverlaySend) From a6c793cacaa32ea566704c4cafe4f2e441486465 Mon Sep 17 00:00:00 2001 From: Gregory Kurtzer Date: Wed, 16 Feb 2022 04:48:17 +0000 Subject: [PATCH 02/14] Fixes for kernel identification within the container --- internal/app/wwctl/container/list/main.go | 7 +-- internal/pkg/container/kernel.go | 72 +++++++++++++++-------- 2 files changed, 52 insertions(+), 27 deletions(-) diff --git a/internal/app/wwctl/container/list/main.go b/internal/app/wwctl/container/list/main.go index f228a5f9..b9fce309 100644 --- a/internal/app/wwctl/container/list/main.go +++ b/internal/app/wwctl/container/list/main.go @@ -3,7 +3,6 @@ package list import ( "fmt" "os" - "path" "github.com/hpcng/warewulf/internal/pkg/container" "github.com/hpcng/warewulf/internal/pkg/node" @@ -27,14 +26,14 @@ func CobraRunE(cmd *cobra.Command, args []string) error { nodemap[n.ContainerName.Get()]++ } - fmt.Printf("%-25s %-6s %-6s\n", "CONTAINER NAME", "NODES", "KERNEL") + fmt.Printf("%-25s %-6s %-6s\n", "CONTAINER NAME", "NODES", "KERNEL VERSION") for _, source := range sources { if nodemap[source] == 0 { nodemap[source] = 0 } - kernel := container.KernelFind(source) - fmt.Printf("%-25s %-6d %s\n", source, nodemap[source], path.Base(kernel)) + kernelVersion := container.KernelVersion(source) + fmt.Printf("%-25s %-6d %s\n", source, nodemap[source], kernelVersion) } return nil diff --git a/internal/pkg/container/kernel.go b/internal/pkg/container/kernel.go index e1279e60..9a9cd8c2 100644 --- a/internal/pkg/container/kernel.go +++ b/internal/pkg/container/kernel.go @@ -1,18 +1,22 @@ package container import ( + "fmt" "path" "path/filepath" "sort" + "github.com/hpcng/warewulf/internal/pkg/util" "github.com/hpcng/warewulf/internal/pkg/wwlog" ) var ( kernelSearchPaths = []string{ // This is a printf format where the %s will be the kernel version - "/boot/vmlinuz-*", - "/lib/modules/*/vmlinuz*", + `/boot/vmlinuz-%s`, + `/boot/vmlinuz-%s.gz`, + `/lib/modules/%s/vmlinuz`, + `/lib/modules/%s/vmlinuz.gz`, } ) @@ -22,26 +26,48 @@ func KernelFind(container string) string { return "" } - for _, searchPath := range kernelSearchPaths { - - check_path := path.Join(container_path, searchPath) - - wwlog.Printf(wwlog.DEBUG, "Searching for kernel(s) at: %s\n", check_path) - kernels, err := filepath.Glob(check_path) - if err != nil { - return "" - } - - if len(kernels) > 1 { - sort.Slice(kernels, func(i, j int) bool { - return kernels[i] > kernels[j] - }) - wwlog.Printf(wwlog.VERBOSE, "Multiple kernels found in container: %s\n", container) - return kernels[0] - } else if len(kernels) == 1 { - return kernels[0] - } - + kernelVersion := KernelVersion(container) + if kernelVersion == "" { + return "" } - return "NOT_FOUND" + + for _, searchPath := range kernelSearchPaths { + testPath := fmt.Sprintf(searchPath, kernelVersion) + wwlog.Printf(wwlog.VERBOSE, "Looking for kernel at: '%s'\n", testPath) + if util.IsFile(path.Join(container_path, testPath)) { + return path.Join(container_path, testPath) + } + } + + return "" +} + +func KernelVersion(container string) string { + container_path := RootFsDir(container) + if container_path == "" { + return "" + } + + module_lib_path := path.Join(container_path, "/lib/modules/*") + wwlog.Printf(wwlog.DEBUG, "Searching for kernel modules at: %s\n", module_lib_path) + kernelversions, err := filepath.Glob(module_lib_path) + if err != nil { + return "" + } + + if len(kernelversions) > 1 { + sort.Slice(kernelversions, func(i, j int) bool { + return kernelversions[i] > kernelversions[j] + }) + wwlog.Printf(wwlog.VERBOSE, "Multiple kernels found in container: %s\n", container) + + wwlog.Printf(wwlog.DEBUG, "Found lib path: '%s'\n", kernelversions[0]) + return path.Base(kernelversions[0]) + } else if len(kernelversions) == 1 { + wwlog.Printf(wwlog.DEBUG, "Found lib path: '%s'\n", kernelversions[0]) + + return path.Base(kernelversions[0]) + } + + return "" } From 5f56e69dbb26483cc961bdb1be7b4841254a2866 Mon Sep 17 00:00:00 2001 From: Gregory Kurtzer Date: Wed, 16 Feb 2022 04:49:19 +0000 Subject: [PATCH 03/14] Leverage the upstream containers and add kernel to container --- containers/Docker/centos-8 | 36 ++++++++++++++++++++++++++++++++++++ containers/Docker/rocky-8 | 36 ++++++++++++++++++++++++++++++++++++ 2 files changed, 72 insertions(+) create mode 100644 containers/Docker/centos-8 create mode 100644 containers/Docker/rocky-8 diff --git a/containers/Docker/centos-8 b/containers/Docker/centos-8 new file mode 100644 index 00000000..4df5070e --- /dev/null +++ b/containers/Docker/centos-8 @@ -0,0 +1,36 @@ +FROM docker.io/library/centos:8 + +RUN dnf install -y --allowerasing coreutils \ + cpio \ + dhclient \ + e2fsprogs \ + ethtool \ + findutils \ + initscripts \ + ipmitool \ + iproute \ + kernel-core \ + net-tools \ + network-scripts \ + nfs-utils \ + openssh-clients \ + openssh-server \ + pciutils \ + psmisc \ + rsync \ + rsyslog \ + strace \ + wget \ + which \ + words + +RUN sed -i 's/^root:.:/root::/g' /etc/passwd + +# These changes make it possible for users to ssh into nodes even +# if there is no shadow entry for the user +RUN sed -i -e '/^account.*pam_unix\.so\s*$/s/\s*$/\ broken_shadow/' /etc/pam.d/system-auth +RUN sed -i -e '/^account.*pam_unix\.so\s*$/s/\s*$/\ broken_shadow/' /etc/pam.d/password-auth + +RUN systemctl unmask console-getty.service dev-hugepages.mount \ + getty.target sys-fs-fuse-connections.mount systemd-logind.service \ + systemd-remount-fs.service diff --git a/containers/Docker/rocky-8 b/containers/Docker/rocky-8 new file mode 100644 index 00000000..9c500913 --- /dev/null +++ b/containers/Docker/rocky-8 @@ -0,0 +1,36 @@ +FROM docker.io/library/rockylinux:8 + +RUN dnf install -y --allowerasing coreutils \ + cpio \ + dhclient \ + e2fsprogs \ + ethtool \ + findutils \ + initscripts \ + ipmitool \ + iproute \ + kernel-core \ + net-tools \ + network-scripts \ + nfs-utils \ + openssh-clients \ + openssh-server \ + pciutils \ + psmisc \ + rsync \ + rsyslog \ + strace \ + wget \ + which \ + words + +RUN sed -i 's/^root:.:/root::/g' /etc/passwd + +# These changes make it possible for users to ssh into nodes even +# if there is no shadow entry for the user +RUN sed -i -e '/^account.*pam_unix\.so\s*$/s/\s*$/\ broken_shadow/' /etc/pam.d/system-auth +RUN sed -i -e '/^account.*pam_unix\.so\s*$/s/\s*$/\ broken_shadow/' /etc/pam.d/password-auth + +RUN systemctl unmask console-getty.service dev-hugepages.mount \ + getty.target sys-fs-fuse-connections.mount systemd-logind.service \ + systemd-remount-fs.service From b06322bfbbf54d7ec4d39f95089a638a66a959ae Mon Sep 17 00:00:00 2001 From: Gregory Kurtzer Date: Wed, 16 Feb 2022 04:50:08 +0000 Subject: [PATCH 04/14] rename openhpc to lowercase --- containers/Docker/{OpenHPC => openhpc} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename containers/Docker/{OpenHPC => openhpc} (100%) diff --git a/containers/Docker/OpenHPC b/containers/Docker/openhpc similarity index 100% rename from containers/Docker/OpenHPC rename to containers/Docker/openhpc From e88f18cb3fd31dfd998f720a6cb8511dbfaf54a0 Mon Sep 17 00:00:00 2001 From: Gregory Kurtzer Date: Wed, 16 Feb 2022 04:51:11 +0000 Subject: [PATCH 05/14] Specify full host URI --- containers/Docker/openhpc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/containers/Docker/openhpc b/containers/Docker/openhpc index 8263f766..a8d0ea5d 100644 --- a/containers/Docker/openhpc +++ b/containers/Docker/openhpc @@ -1,4 +1,4 @@ -FROM warewulf/rocky:8 +FROM docker.io/warewulf/rocky:8 RUN dnf -y install http://repos.openhpc.community/OpenHPC/2/CentOS_8/x86_64/ohpc-release-2-1.el8.x86_64.rpm; \ sed -i -e 's/^enabled=0/enabled=1/g' /etc/yum.repos.d/*-PowerTools.repo; \ From 104bc7527df150adbc30c812c57cfb20d4356da5 Mon Sep 17 00:00:00 2001 From: Gregory Kurtzer Date: Thu, 17 Feb 2022 06:21:40 +0000 Subject: [PATCH 06/14] Restored deleted kernel components for overrides --- internal/app/wwctl/kernel/delete/main.go | 41 ++++ internal/app/wwctl/kernel/delete/root.go | 33 +++ internal/app/wwctl/kernel/imprt/main.go | 92 ++++++++ internal/app/wwctl/kernel/imprt/root.go | 46 ++++ internal/app/wwctl/kernel/list/main.go | 35 +++ internal/app/wwctl/kernel/list/root.go | 23 ++ internal/app/wwctl/kernel/root.go | 28 +++ internal/app/wwctl/node/list/main.go | 5 +- internal/app/wwctl/node/set/main.go | 5 + internal/app/wwctl/node/set/root.go | 9 + internal/app/wwctl/profile/list/main.go | 1 + internal/app/wwctl/profile/set/main.go | 7 +- internal/app/wwctl/profile/set/root.go | 9 + internal/app/wwctl/root.go | 20 +- internal/pkg/kernel/kernel.go | 257 +++++++++++++++++++++++ internal/pkg/node/constructors.go | 3 + internal/pkg/node/datastructure.go | 2 + internal/pkg/node/modifiers.go | 2 + internal/pkg/overlay/overlay.go | 1 + internal/pkg/warewulfd/ipxe.go | 1 + internal/pkg/warewulfd/kmods.go | 45 ++++ internal/pkg/warewulfd/warewulfd.go | 1 + 22 files changed, 654 insertions(+), 12 deletions(-) create mode 100644 internal/app/wwctl/kernel/delete/main.go create mode 100644 internal/app/wwctl/kernel/delete/root.go create mode 100644 internal/app/wwctl/kernel/imprt/main.go create mode 100644 internal/app/wwctl/kernel/imprt/root.go create mode 100644 internal/app/wwctl/kernel/list/main.go create mode 100644 internal/app/wwctl/kernel/list/root.go create mode 100644 internal/app/wwctl/kernel/root.go create mode 100644 internal/pkg/kernel/kernel.go create mode 100644 internal/pkg/warewulfd/kmods.go diff --git a/internal/app/wwctl/kernel/delete/main.go b/internal/app/wwctl/kernel/delete/main.go new file mode 100644 index 00000000..c289a27d --- /dev/null +++ b/internal/app/wwctl/kernel/delete/main.go @@ -0,0 +1,41 @@ +package delete + +import ( + "fmt" + "os" + + "github.com/hpcng/warewulf/internal/pkg/kernel" + "github.com/hpcng/warewulf/internal/pkg/node" + "github.com/hpcng/warewulf/internal/pkg/wwlog" + "github.com/spf13/cobra" +) + +func CobraRunE(cmd *cobra.Command, args []string) error { + + nodeDB, err := node.New() + if err != nil { + wwlog.Printf(wwlog.ERROR, "Could not open nodeDB: %s\n", err) + os.Exit(1) + } + + nodes, _ := nodeDB.FindAllNodes() + +ARG_LOOP: + for _, arg := range args { + for _, n := range nodes { + if n.KernelVersion.Get() == arg { + wwlog.Printf(wwlog.ERROR, "Kernel is configured for nodes, skipping: %s\n", arg) + continue ARG_LOOP + } + } + + err := kernel.DeleteKernel(arg) + if err != nil { + wwlog.Printf(wwlog.ERROR, "Could not delete kernel: %s\n", arg) + } else { + fmt.Printf("Kernel has been deleted: %s\n", arg) + } + } + + return nil +} diff --git a/internal/app/wwctl/kernel/delete/root.go b/internal/app/wwctl/kernel/delete/root.go new file mode 100644 index 00000000..5fc68bea --- /dev/null +++ b/internal/app/wwctl/kernel/delete/root.go @@ -0,0 +1,33 @@ +package delete + +import ( + "github.com/hpcng/warewulf/internal/pkg/kernel" + "github.com/spf13/cobra" +) + +var ( + baseCmd = &cobra.Command{ + DisableFlagsInUseLine: true, + Use: "delete [OPTIONS] KERNEL [...]", + Short: "Delete imported kernels", + Long: "This command will delete KERNEL versions that have been imported into Warewulf.", + RunE: CobraRunE, + Args: cobra.MinimumNArgs(1), + ValidArgsFunction: func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { + if len(args) != 0 { + return nil, cobra.ShellCompDirectiveNoFileComp + } + list, _ := kernel.ListKernels() + return list, cobra.ShellCompDirectiveNoFileComp + }, + } +) + +func init() { + +} + +// GetRootCommand returns the root cobra.Command for the application. +func GetCommand() *cobra.Command { + return baseCmd +} diff --git a/internal/app/wwctl/kernel/imprt/main.go b/internal/app/wwctl/kernel/imprt/main.go new file mode 100644 index 00000000..97e3e219 --- /dev/null +++ b/internal/app/wwctl/kernel/imprt/main.go @@ -0,0 +1,92 @@ +package imprt + +import ( + "fmt" + "os" + + "github.com/hpcng/warewulf/internal/pkg/container" + "github.com/hpcng/warewulf/internal/pkg/kernel" + "github.com/hpcng/warewulf/internal/pkg/node" + "github.com/hpcng/warewulf/internal/pkg/warewulfd" + "github.com/hpcng/warewulf/internal/pkg/wwlog" + "github.com/pkg/errors" + "github.com/spf13/cobra" +) + +func CobraRunE(cmd *cobra.Command, args []string) error { + if len(args) == 0 && !OptDetect { + wwlog.Printf(wwlog.ERROR, "the '--detect' flag is needed, if no kernel version is suppiled") + os.Exit(1) + } + if OptDetect && (OptRoot == "" || OptContainer == "") { + wwlog.Printf(wwlog.ERROR, "the '--detect flag needs the '--container' or '--root' flag") + os.Exit(1) + } + // Checking if container flag was set, then overwriting OptRoot + if OptContainer != "" { + if container.ValidSource(OptContainer) { + OptRoot = container.RootFsDir(OptContainer) + } else { + wwlog.Printf(wwlog.ERROR, " %s is not a valid container", OptContainer) + os.Exit(1) + } + } + + var kernelVersion string + var err error + if len(args) > 0 { + kernelVersion = args[0] + } else { + kernelVersion, err = kernel.FindKernelVersion(OptRoot) + if err != nil { + wwlog.Printf(wwlog.ERROR, "could not detect kernel under %s\n", OptRoot) + os.Exit(1) + } + } + kernelName := kernelVersion + if len(args) > 1 { + kernelName = args[1] + } else if OptDetect && (OptContainer != "") { + kernelName = OptContainer + } + output, err := kernel.Build(kernelVersion, kernelName, OptRoot) + if err != nil { + wwlog.Printf(wwlog.ERROR, "Failed building kernel: %s\n", err) + os.Exit(1) + } else { + fmt.Printf("%s: %s\n", kernelName, output) + } + + if SetDefault { + + nodeDB, err := node.New() + if err != nil { + wwlog.Printf(wwlog.ERROR, "Could not open node configuration: %s\n", err) + os.Exit(1) + } + //TODO: Don't loop through profiles, instead have a nodeDB function that goes directly to the map + profiles, _ := nodeDB.FindAllProfiles() + for _, profile := range profiles { + wwlog.Printf(wwlog.DEBUG, "Looking for profile default: %s\n", profile.Id.Get()) + if profile.Id.Get() == "default" { + wwlog.Printf(wwlog.DEBUG, "Found profile default, setting kernel version to: %s\n", args[0]) + profile.KernelVersion.Set(args[0]) + err := nodeDB.ProfileUpdate(profile) + if err != nil { + return errors.Wrap(err, "failed to update node profile") + } + } + } + err = nodeDB.Persist() + if err != nil { + return errors.Wrap(err, "failed to persist nodedb") + } + fmt.Printf("Set default kernel version to: %s\n", args[0]) + err = warewulfd.DaemonReload() + if err != nil { + return errors.Wrap(err, "failed to reload warewulf daemon") + } + } + + return nil +} diff --git a/internal/app/wwctl/kernel/imprt/root.go b/internal/app/wwctl/kernel/imprt/root.go new file mode 100644 index 00000000..c8521a7b --- /dev/null +++ b/internal/app/wwctl/kernel/imprt/root.go @@ -0,0 +1,46 @@ +package imprt + +import ( + "log" + + "github.com/hpcng/warewulf/internal/pkg/container" + "github.com/spf13/cobra" +) + +var ( + baseCmd = &cobra.Command{ + DisableFlagsInUseLine: true, + Use: "import [OPTIONS] KERNEL", + Short: "Import Kernel version into Warewulf", + Long: "This will import a boot KERNEL version from the control node into Warewulf", + RunE: CobraRunE, + Args: cobra.MinimumNArgs(0), + } + BuildAll bool + ByNode bool + SetDefault bool + OptRoot string + OptContainer string + OptDetect bool +) + +func init() { + baseCmd.PersistentFlags().BoolVarP(&BuildAll, "all", "a", false, "Build all overlays (runtime and system)") + baseCmd.PersistentFlags().BoolVarP(&ByNode, "node", "n", false, "Build overlay for a particular node(s)") + baseCmd.PersistentFlags().BoolVar(&SetDefault, "setdefault", false, "Set this kernel for the default profile") + baseCmd.PersistentFlags().StringVarP(&OptRoot, "root", "r", "/", "Import kernel from root (chroot) directory") + baseCmd.PersistentFlags().StringVarP(&OptContainer, "container", "C", "", "Import kernel from container") + err := baseCmd.RegisterFlagCompletionFunc("container", func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { + list, _ := container.ListSources() + return list, cobra.ShellCompDirectiveNoFileComp + }) + if err != nil { + log.Println(err) + } + baseCmd.PersistentFlags().BoolVarP(&OptDetect, "detect", "D", false, "Try to detect the kernel version in an automated way, needs the -C or -r option") +} + +// GetRootCommand returns the root cobra.Command for the application. +func GetCommand() *cobra.Command { + return baseCmd +} diff --git a/internal/app/wwctl/kernel/list/main.go b/internal/app/wwctl/kernel/list/main.go new file mode 100644 index 00000000..a3a8d4ad --- /dev/null +++ b/internal/app/wwctl/kernel/list/main.go @@ -0,0 +1,35 @@ +package list + +import ( + "fmt" + "os" + + "github.com/hpcng/warewulf/internal/pkg/kernel" + "github.com/hpcng/warewulf/internal/pkg/node" + "github.com/hpcng/warewulf/internal/pkg/wwlog" + "github.com/spf13/cobra" +) + +func CobraRunE(cmd *cobra.Command, args []string) error { + + kernels, err := kernel.ListKernels() + if err != nil { + wwlog.Printf(wwlog.ERROR, "%s\n", err) + os.Exit(1) + } + + nconfig, _ := node.New() + nodes, _ := nconfig.FindAllNodes() + nodemap := make(map[string]int) + + for _, n := range nodes { + nodemap[n.KernelVersion.Get()]++ + } + + fmt.Printf("%-35s %-25s %-6s\n", "KERNEL NAME", "KERNEL VERSION", "NODES") + for _, k := range kernels { + fmt.Printf("%-35s %-25s %6d\n", k, kernel.GetKernelVersion(k), nodemap[k]) + } + + return nil +} diff --git a/internal/app/wwctl/kernel/list/root.go b/internal/app/wwctl/kernel/list/root.go new file mode 100644 index 00000000..fba84101 --- /dev/null +++ b/internal/app/wwctl/kernel/list/root.go @@ -0,0 +1,23 @@ +package list + +import "github.com/spf13/cobra" + +var ( + baseCmd = &cobra.Command{ + DisableFlagsInUseLine: true, + Use: "list [OPTIONS]", + Short: "List imported Kernel images", + Long: "This command will list the kernels that have been imported into Warewulf.", + RunE: CobraRunE, + Args: cobra.ExactArgs(0), + Aliases: []string{"ls"}, + } +) + +func init() { +} + +// GetRootCommand returns the root cobra.Command for the application. +func GetCommand() *cobra.Command { + return baseCmd +} diff --git a/internal/app/wwctl/kernel/root.go b/internal/app/wwctl/kernel/root.go new file mode 100644 index 00000000..bb0cdb8d --- /dev/null +++ b/internal/app/wwctl/kernel/root.go @@ -0,0 +1,28 @@ +package kernel + +import ( + "github.com/hpcng/warewulf/internal/app/wwctl/kernel/delete" + "github.com/hpcng/warewulf/internal/app/wwctl/kernel/imprt" + "github.com/hpcng/warewulf/internal/app/wwctl/kernel/list" + "github.com/spf13/cobra" +) + +var ( + baseCmd = &cobra.Command{ + DisableFlagsInUseLine: true, + Use: "kernel COMMAND [OPTIONS]", + Short: "Kernel Image Management", + Long: "This command manages Warewulf Kernels used for bootstrapping nodes", + } +) + +func init() { + baseCmd.AddCommand(imprt.GetCommand()) + baseCmd.AddCommand(list.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/node/list/main.go b/internal/app/wwctl/node/list/main.go index 76db8201..0e6845c8 100644 --- a/internal/app/wwctl/node/list/main.go +++ b/internal/app/wwctl/node/list/main.go @@ -41,6 +41,7 @@ func CobraRunE(cmd *cobra.Command, args []string) error { fmt.Printf("%-20s %-18s %-12s %t\n", node.Id.Get(), "Discoverable", node.Discoverable.Source(), node.Discoverable.PrintB()) fmt.Printf("%-20s %-18s %-12s %s\n", node.Id.Get(), "Container", node.ContainerName.Source(), node.ContainerName.Print()) + fmt.Printf("%-20s %-18s %-12s %s\n", node.Id.Get(), "Kernel", node.KernelVersion.Source(), node.KernelVersion.Print()) fmt.Printf("%-20s %-18s %-12s %s\n", node.Id.Get(), "KernelArgs", node.KernelArgs.Source(), node.KernelArgs.Print()) fmt.Printf("%-20s %-18s %-12s %s\n", node.Id.Get(), "SystemOverlay", node.SystemOverlay.Source(), node.SystemOverlay.Print()) fmt.Printf("%-20s %-18s %-12s %s\n", node.Id.Get(), "RuntimeOverlay", node.RuntimeOverlay.Source(), node.RuntimeOverlay.Print()) @@ -96,11 +97,11 @@ func CobraRunE(cmd *cobra.Command, args []string) error { } } else if ShowLong { - fmt.Printf("%-22s %-35s %s\n", "NODE NAME", "CONTAINER", "OVERLAYS (S/R)") + fmt.Printf("%-22s %-26s %-35s %s\n", "NODE NAME", "KERNEL", "CONTAINER", "OVERLAYS (S/R)") fmt.Println(strings.Repeat("=", 120)) for _, node := range node.FilterByName(nodes, args) { - fmt.Printf("%-22s %-35s %s\n", node.Id.Get(), node.ContainerName.Print(), node.SystemOverlay.Print()+"/"+node.RuntimeOverlay.Print()) + fmt.Printf("%-22s %-26s %-35s %s\n", node.Id.Get(), node.KernelVersion.Print(), node.ContainerName.Print(), node.SystemOverlay.Print()+"/"+node.RuntimeOverlay.Print()) } } else { diff --git a/internal/app/wwctl/node/set/main.go b/internal/app/wwctl/node/set/main.go index 2e2c4861..59f3e7c5 100644 --- a/internal/app/wwctl/node/set/main.go +++ b/internal/app/wwctl/node/set/main.go @@ -70,6 +70,11 @@ func CobraRunE(cmd *cobra.Command, args []string) error { n.AssetKey.Set(SetAssetKey) } + if SetKernel != "" { + wwlog.Printf(wwlog.VERBOSE, "Node: %s, Setting kernel to: %s\n", n.Id.Get(), SetKernel) + n.KernelVersion.Set(SetKernel) + } + if SetKernelArgs != "" { wwlog.Printf(wwlog.VERBOSE, "Node: %s, Setting kernel args to: %s\n", n.Id.Get(), SetKernelArgs) n.KernelArgs.Set(SetKernelArgs) diff --git a/internal/app/wwctl/node/set/root.go b/internal/app/wwctl/node/set/root.go index 0dcbc865..a3feec62 100644 --- a/internal/app/wwctl/node/set/root.go +++ b/internal/app/wwctl/node/set/root.go @@ -4,6 +4,7 @@ import ( "log" "github.com/hpcng/warewulf/internal/pkg/container" + "github.com/hpcng/warewulf/internal/pkg/kernel" "github.com/hpcng/warewulf/internal/pkg/node" "github.com/hpcng/warewulf/internal/pkg/overlay" "github.com/spf13/cobra" @@ -33,6 +34,7 @@ var ( } SetComment string SetContainer string + SetKernel string SetKernelArgs string SetNetName string SetNetDev string @@ -80,6 +82,13 @@ func init() { }); err != nil { log.Println(err) } + baseCmd.PersistentFlags().StringVarP(&SetKernel, "kernel", "K", "", "Set Kernel version for nodes") + if err := baseCmd.RegisterFlagCompletionFunc("kernel", func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { + list, _ := kernel.ListKernels() + return list, cobra.ShellCompDirectiveNoFileComp + }); err != nil { + log.Println(err) + } baseCmd.PersistentFlags().StringVarP(&SetKernelArgs, "kernelargs", "A", "", "Set Kernel argument for nodes") baseCmd.PersistentFlags().StringVarP(&SetClusterName, "cluster", "c", "", "Set the node's cluster group") baseCmd.PersistentFlags().StringVar(&SetIpxe, "ipxe", "", "Set the node's iPXE template name") diff --git a/internal/app/wwctl/profile/list/main.go b/internal/app/wwctl/profile/list/main.go index d1120cbc..a419952e 100644 --- a/internal/app/wwctl/profile/list/main.go +++ b/internal/app/wwctl/profile/list/main.go @@ -33,6 +33,7 @@ func CobraRunE(cmd *cobra.Command, args []string) error { fmt.Printf("%-20s %-18s %s\n", profile.Id.Get(), "Cluster", profile.ClusterName.Print()) fmt.Printf("%-20s %-18s %s\n", profile.Id.Get(), "Container", profile.ContainerName.Print()) + fmt.Printf("%-20s %-18s %s\n", profile.Id.Get(), "Kernel", profile.KernelVersion.Print()) fmt.Printf("%-20s %-18s %s\n", profile.Id.Get(), "KernelArgs", profile.KernelArgs.Print()) fmt.Printf("%-20s %-18s %s\n", profile.Id.Get(), "Init", profile.Init.Print()) fmt.Printf("%-20s %-18s %s\n", profile.Id.Get(), "Root", profile.Root.Print()) diff --git a/internal/app/wwctl/profile/set/main.go b/internal/app/wwctl/profile/set/main.go index e4957be3..09d4c288 100644 --- a/internal/app/wwctl/profile/set/main.go +++ b/internal/app/wwctl/profile/set/main.go @@ -75,8 +75,13 @@ func CobraRunE(cmd *cobra.Command, args []string) error { p.AssetKey.Set(SetAssetKey) } + if SetKernel != "" { + wwlog.Printf(wwlog.VERBOSE, "Profile: %s, Setting Kernel to: %s\n", p.Id.Get(), SetKernel) + p.KernelVersion.Set(SetKernel) + } + if SetKernelArgs != "" { - wwlog.Printf(wwlog.VERBOSE, "Profile: %s, Setting kernel args to: %s\n", p.Id.Get(), SetKernelArgs) + wwlog.Printf(wwlog.VERBOSE, "Profile: %s, Setting Kernel args to: %s\n", p.Id.Get(), SetKernelArgs) p.KernelArgs.Set(SetKernelArgs) } diff --git a/internal/app/wwctl/profile/set/root.go b/internal/app/wwctl/profile/set/root.go index e7da4c20..d8b08dc6 100644 --- a/internal/app/wwctl/profile/set/root.go +++ b/internal/app/wwctl/profile/set/root.go @@ -4,6 +4,7 @@ import ( "log" "github.com/hpcng/warewulf/internal/pkg/container" + "github.com/hpcng/warewulf/internal/pkg/kernel" "github.com/hpcng/warewulf/internal/pkg/node" "github.com/hpcng/warewulf/internal/pkg/overlay" "github.com/spf13/cobra" @@ -36,6 +37,7 @@ var ( SetForce bool SetComment string SetContainer string + SetKernel string SetKernelArgs string SetClusterName string SetIpxe string @@ -77,6 +79,13 @@ func init() { }); err != nil { log.Println(err) } + baseCmd.PersistentFlags().StringVarP(&SetKernel, "kernel", "K", "", "Set Kernel version for nodes") + if err := baseCmd.RegisterFlagCompletionFunc("kernel", func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { + list, _ := kernel.ListKernels() + return list, cobra.ShellCompDirectiveNoFileComp + }); err != nil { + log.Println(err) + } baseCmd.PersistentFlags().StringVarP(&SetKernelArgs, "kernelargs", "A", "", "Set Kernel argument for nodes") baseCmd.PersistentFlags().StringVarP(&SetClusterName, "cluster", "c", "", "Set the node's cluster group") baseCmd.PersistentFlags().StringVarP(&SetIpxe, "ipxe", "P", "", "Set the node's iPXE template name") diff --git a/internal/app/wwctl/root.go b/internal/app/wwctl/root.go index f6e7137d..059b38db 100644 --- a/internal/app/wwctl/root.go +++ b/internal/app/wwctl/root.go @@ -3,14 +3,15 @@ package wwctl import ( "github.com/hpcng/warewulf/internal/app/wwctl/configure" "github.com/hpcng/warewulf/internal/app/wwctl/container" + "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/power" "github.com/hpcng/warewulf/internal/app/wwctl/profile" "github.com/hpcng/warewulf/internal/app/wwctl/server" "github.com/hpcng/warewulf/internal/app/wwctl/version" - "github.com/hpcng/warewulf/internal/pkg/help" "github.com/hpcng/warewulf/internal/pkg/wwlog" + "github.com/hpcng/warewulf/internal/pkg/help" "github.com/spf13/cobra" "github.com/spf13/cobra/doc" @@ -20,12 +21,12 @@ import ( var ( rootCmd = &cobra.Command{ DisableFlagsInUseLine: true, - Use: "wwctl COMMAND [OPTIONS]", - Short: "Warewulf Control", - Long: "Control interface to the Warewulf Cluster Provisioning System.", - PersistentPreRunE: rootPersistentPreRunE, - SilenceUsage: true, - SilenceErrors: true, + Use: "wwctl COMMAND [OPTIONS]", + Short: "Warewulf Control", + Long: "Control interface to the Warewulf Cluster Provisioning System.", + PersistentPreRunE: rootPersistentPreRunE, + SilenceUsage: true, + SilenceErrors: true, } verboseArg bool DebugFlag bool @@ -35,12 +36,13 @@ func init() { rootCmd.PersistentFlags().BoolVarP(&verboseArg, "verbose", "v", false, "Run with increased verbosity.") rootCmd.PersistentFlags().BoolVarP(&DebugFlag, "debug", "d", false, "Run with debugging messages enabled.") - rootCmd.SetUsageTemplate(help.UsageTemplate) - rootCmd.SetHelpTemplate(help.HelpTemplate) + rootCmd.SetUsageTemplate(help.UsageTemplate) + rootCmd.SetHelpTemplate(help.HelpTemplate) rootCmd.AddCommand(overlay.GetCommand()) rootCmd.AddCommand(container.GetCommand()) rootCmd.AddCommand(node.GetCommand()) + rootCmd.AddCommand(kernel.GetCommand()) rootCmd.AddCommand(power.GetCommand()) rootCmd.AddCommand(profile.GetCommand()) rootCmd.AddCommand(configure.GetCommand()) diff --git a/internal/pkg/kernel/kernel.go b/internal/pkg/kernel/kernel.go new file mode 100644 index 00000000..37941032 --- /dev/null +++ b/internal/pkg/kernel/kernel.go @@ -0,0 +1,257 @@ +package kernel + +import ( + "compress/gzip" + "fmt" + "io" + "io/ioutil" + "os" + "os/exec" + "path" + "path/filepath" + "regexp" + + "github.com/pkg/errors" + + "github.com/hpcng/warewulf/internal/pkg/buildconfig" + "github.com/hpcng/warewulf/internal/pkg/util" + "github.com/hpcng/warewulf/internal/pkg/wwlog" +) + +var ( + kernelSearchPaths = []string{ + // This is a printf format where the %s will be the kernel version + "/boot/vmlinuz-%s", + "/boot/vmlinuz-%s.gz", + "/lib/mmodules/%s/vmlinuz", + "/lib/mmodules/%s/vmlinuz.gz", + } +) + +func KernelImageTopDir() string { + return path.Join(buildconfig.WWPROVISIONDIR(), "kernel") +} + +func KernelImage(kernelName string) string { + if kernelName == "" { + wwlog.Printf(wwlog.ERROR, "Kernel Name is not defined\n") + return "" + } + + if !util.ValidString(kernelName, "^[a-zA-Z0-9-._]+$") { + wwlog.Printf(wwlog.ERROR, "Runtime overlay name contains illegal characters: %s\n", kernelName) + return "" + } + + return path.Join(KernelImageTopDir(), kernelName, "vmlinuz") +} + +func GetKernelVersion(kernelName string) string { + if kernelName == "" { + wwlog.Printf(wwlog.ERROR, "Kernel Name is not defined\n") + return "" + } + kernelVersion, err := ioutil.ReadFile(KernelVersionFile(kernelName)) + if err != nil { + return "" + } + return string(kernelVersion) +} + +func KmodsImage(kernelName string) string { + if kernelName == "" { + wwlog.Printf(wwlog.ERROR, "Kernel Name is not defined\n") + return "" + } + + if !util.ValidString(kernelName, "^[a-zA-Z0-9-._]+$") { + wwlog.Printf(wwlog.ERROR, "Runtime overlay name contains illegal characters: %s\n", kernelName) + return "" + } + + return path.Join(KernelImageTopDir(), kernelName, "kmods.img") +} + +func KernelVersionFile(kernelName string) string { + if kernelName == "" { + wwlog.Printf(wwlog.ERROR, "Kernel Name is not defined\n") + return "" + } + + if !util.ValidString(kernelName, "^[a-zA-Z0-9-._]+$") { + wwlog.Printf(wwlog.ERROR, "Runtime overlay name contains illegal characters: %s\n", kernelName) + return "" + } + + return path.Join(KernelImageTopDir(), kernelName, "version") +} + +func ListKernels() ([]string, error) { + var ret []string + + err := os.MkdirAll(KernelImageTopDir(), 0755) + if err != nil { + return ret, errors.New("Could not create Kernel parent directory: " + KernelImageTopDir()) + } + + wwlog.Printf(wwlog.DEBUG, "Searching for Kernel image directories: %s\n", KernelImageTopDir()) + + kernels, err := ioutil.ReadDir(KernelImageTopDir()) + if err != nil { + return ret, err + } + + for _, kernel := range kernels { + wwlog.Printf(wwlog.VERBOSE, "Found Kernel: %s\n", kernel.Name()) + + ret = append(ret, kernel.Name()) + + } + + return ret, nil +} + +func Build(kernelVersion, kernelName, root string) (string, error) { + kernelDrivers := path.Join(root, "/lib/modules/", kernelVersion) + kernelDriversRelative := path.Join("/lib/modules/", kernelVersion) + kernelDestination := KernelImage(kernelName) + driversDestination := KmodsImage(kernelName) + versionDestination := KernelVersionFile(kernelName) + var kernelSource string + + // Create the destination paths just in case it doesn't exist + err := os.MkdirAll(path.Dir(kernelDestination), 0755) + if err != nil { + return "", errors.Wrap(err, "failed to create kernel dest") + } + + err = os.MkdirAll(path.Dir(driversDestination), 0755) + if err != nil { + return "", errors.Wrap(err, "failed to create driver dest") + } + + err = os.MkdirAll(path.Dir(versionDestination), 0755) + if err != nil { + return "", fmt.Errorf("failed to create version dest: %s", err) + } + + for _, searchPath := range kernelSearchPaths { + testPath := fmt.Sprintf(path.Join(root, searchPath), kernelVersion) + wwlog.Printf(wwlog.VERBOSE, "Looking for kernel at: %s\n", testPath) + if util.IsFile(testPath) { + kernelSource = testPath + break + } + } + + if kernelSource == "" { + wwlog.Printf(wwlog.ERROR, "Could not locate kernel image\n") + return "", errors.New("could not locate kernel image") + } else { + wwlog.Printf(wwlog.INFO, "Found kernel at: %s\n", kernelSource) + } + + if !util.IsDir(kernelDrivers) { + return "", errors.New("Could not locate kernel drivers") + } + + wwlog.Printf(wwlog.VERBOSE, "Setting up Kernel\n") + if _, err := os.Stat(kernelSource); err == nil { + kernel, err := os.Open(kernelSource) + if err != nil { + return "", errors.Wrap(err, "could not open kernel") + } + defer kernel.Close() + + gzipreader, err := gzip.NewReader(kernel) + if err == nil { + defer gzipreader.Close() + + writer, err := os.Create(kernelDestination) + if err != nil { + return "", errors.Wrap(err, "could not decompress kernel") + } + defer writer.Close() + + _, err = io.Copy(writer, gzipreader) + if err != nil { + return "", errors.Wrap(err, "could not write decompressed kernel") + } + + } else { + + err := util.CopyFile(kernelSource, kernelDestination) + if err != nil { + return "", errors.Wrap(err, "could not copy kernel") + } + } + + } + + wwlog.Printf(wwlog.VERBOSE, "Building Kernel driver image\n") + if _, err := os.Stat(kernelDrivers); err == nil { + compressor, err := exec.LookPath("pigz") + if err != nil { + wwlog.Printf(wwlog.VERBOSE, "Could not locate PIGZ, using GZIP\n") + compressor = "gzip" + } else { + wwlog.Printf(wwlog.VERBOSE, "Using PIGZ to compress the container: %s\n", compressor) + } + + cmd := fmt.Sprintf("cd %s; find .%s | cpio --quiet -o -L -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() + if err != nil { + return "", err + } + } + + wwlog.Printf(wwlog.VERBOSE, "Creating version file\n") + file, err := os.Create(versionDestination) + if err != nil { + return "", errors.Wrap(err, "Failed to create version file") + } + defer file.Close() + _, err = io.WriteString(file, kernelVersion) + if err != nil { + return "", errors.Wrap(err, "Could not write kernel version") + } + err = file.Sync() + if err != nil { + return "", errors.Wrap(err, "Could not sync kernel version") + } + return "Done", nil +} + +func DeleteKernel(name string) error { + fullPath := path.Join(KernelImageTopDir(), name) + + wwlog.Printf(wwlog.VERBOSE, "Removing path: %s\n", fullPath) + return os.RemoveAll(fullPath) +} + +func FindKernelVersion(root string) (string, error) { + for _, searchPath := range kernelSearchPaths { + testPattern := fmt.Sprintf(path.Join(root, searchPath), `*`) + wwlog.Printf(wwlog.VERBOSE, "Looking for kernel version with pattern at: %s\n", testPattern) + potentialKernel, _ := filepath.Glob(testPattern) + if len(potentialKernel) == 0 { + continue + } + for _, foundKernel := range potentialKernel { + wwlog.Printf(wwlog.VERBOSE, "Parsing out kernel version for %s\n", foundKernel) + re := regexp.MustCompile(fmt.Sprintf(path.Join(root, searchPath), `([\w\d-\.]*)`)) + version := re.FindAllStringSubmatch(foundKernel, -1) + if version == nil { + return "", fmt.Errorf("could not parse kernel version") + } + wwlog.Printf(wwlog.VERBOSE, "found kernel version %s\n", version) + return version[0][1], nil + + } + + } + return "", fmt.Errorf("could not find kernel version") + +} diff --git a/internal/pkg/node/constructors.go b/internal/pkg/node/constructors.go index 1f73bd98..ebf35397 100644 --- a/internal/pkg/node/constructors.go +++ b/internal/pkg/node/constructors.go @@ -72,6 +72,7 @@ func (config *nodeYaml) FindAllNodes() ([]NodeInfo, error) { n.Id.Set(nodename) n.Comment.Set(node.Comment) n.ContainerName.Set(node.ContainerName) + n.KernelVersion.Set(node.KernelVersion) n.KernelArgs.Set(node.KernelArgs) n.ClusterName.Set(node.ClusterName) n.Ipxe.Set(node.Ipxe) @@ -133,6 +134,7 @@ func (config *nodeYaml) FindAllNodes() ([]NodeInfo, error) { n.Comment.SetAlt(config.NodeProfiles[p].Comment, p) n.ClusterName.SetAlt(config.NodeProfiles[p].ClusterName, p) n.ContainerName.SetAlt(config.NodeProfiles[p].ContainerName, p) + n.KernelVersion.SetAlt(config.NodeProfiles[p].KernelVersion, p) n.KernelArgs.SetAlt(config.NodeProfiles[p].KernelArgs, p) n.Ipxe.SetAlt(config.NodeProfiles[p].Ipxe, p) n.Init.SetAlt(config.NodeProfiles[p].Init, p) @@ -216,6 +218,7 @@ func (config *nodeYaml) FindAllProfiles() ([]NodeInfo, error) { p.ContainerName.Set(profile.ContainerName) p.Ipxe.Set(profile.Ipxe) p.Init.Set(profile.Init) + p.KernelVersion.Set(profile.KernelVersion) p.KernelArgs.Set(profile.KernelArgs) p.IpmiNetmask.Set(profile.IpmiNetmask) p.IpmiPort.Set(profile.IpmiPort) diff --git a/internal/pkg/node/datastructure.go b/internal/pkg/node/datastructure.go index a55b71f1..7b273f82 100644 --- a/internal/pkg/node/datastructure.go +++ b/internal/pkg/node/datastructure.go @@ -19,6 +19,7 @@ type NodeConf struct { ClusterName string `yaml:"cluster name,omitempty"` ContainerName string `yaml:"container name,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"` @@ -70,6 +71,7 @@ type NodeInfo struct { ClusterName Entry ContainerName Entry Ipxe Entry + KernelVersion Entry KernelArgs Entry IpmiIpaddr Entry IpmiNetmask Entry diff --git a/internal/pkg/node/modifiers.go b/internal/pkg/node/modifiers.go index 2a147a5d..6502be84 100644 --- a/internal/pkg/node/modifiers.go +++ b/internal/pkg/node/modifiers.go @@ -60,6 +60,7 @@ func (config *nodeYaml) NodeUpdate(node NodeInfo) error { config.Nodes[nodeID].ClusterName = node.ClusterName.GetReal() config.Nodes[nodeID].Ipxe = node.Ipxe.GetReal() config.Nodes[nodeID].Init = node.Init.GetReal() + config.Nodes[nodeID].KernelVersion = node.KernelVersion.GetReal() config.Nodes[nodeID].KernelArgs = node.KernelArgs.GetReal() config.Nodes[nodeID].IpmiIpaddr = node.IpmiIpaddr.GetReal() config.Nodes[nodeID].IpmiNetmask = node.IpmiNetmask.GetReal() @@ -147,6 +148,7 @@ func (config *nodeYaml) ProfileUpdate(profile NodeInfo) error { config.NodeProfiles[profileID].Ipxe = profile.Ipxe.GetReal() config.NodeProfiles[profileID].Init = profile.Init.GetReal() config.NodeProfiles[profileID].ClusterName = profile.ClusterName.GetReal() + config.NodeProfiles[profileID].KernelVersion = profile.KernelVersion.GetReal() config.NodeProfiles[profileID].KernelArgs = profile.KernelArgs.GetReal() config.NodeProfiles[profileID].IpmiIpaddr = profile.IpmiIpaddr.GetReal() config.NodeProfiles[profileID].IpmiNetmask = profile.IpmiNetmask.GetReal() diff --git a/internal/pkg/overlay/overlay.go b/internal/pkg/overlay/overlay.go index 08a72065..36083519 100644 --- a/internal/pkg/overlay/overlay.go +++ b/internal/pkg/overlay/overlay.go @@ -174,6 +174,7 @@ func BuildOverlay(nodeInfo node.NodeInfo, overlayName string) error { tstruct.Hostname = nodeInfo.Id.Get() tstruct.ClusterName = nodeInfo.ClusterName.Get() tstruct.Container = nodeInfo.ContainerName.Get() + tstruct.KernelVersion = nodeInfo.KernelVersion.Get() tstruct.KernelArgs = nodeInfo.KernelArgs.Get() tstruct.Init = nodeInfo.Init.Get() tstruct.Root = nodeInfo.Root.Get() diff --git a/internal/pkg/warewulfd/ipxe.go b/internal/pkg/warewulfd/ipxe.go index 1cb3d605..84c11808 100644 --- a/internal/pkg/warewulfd/ipxe.go +++ b/internal/pkg/warewulfd/ipxe.go @@ -140,6 +140,7 @@ func IpxeSend(w http.ResponseWriter, req *http.Request) { replace.Hwaddr = rinfo.hwaddr replace.ContainerName = node.ContainerName.Get() replace.KernelArgs = node.KernelArgs.Get() + replace.KernelVersion = node.KernelVersion.Get() err = tmpl.Execute(w, replace) if err != nil { diff --git a/internal/pkg/warewulfd/kmods.go b/internal/pkg/warewulfd/kmods.go new file mode 100644 index 00000000..13ace42b --- /dev/null +++ b/internal/pkg/warewulfd/kmods.go @@ -0,0 +1,45 @@ +package warewulfd + +import ( + "net/http" + "strings" + + "github.com/hpcng/warewulf/internal/pkg/kernel" +) + +func KmodsSend(w http.ResponseWriter, req *http.Request) { + rinfo, err := parseReq(req) + if err != nil { + w.WriteHeader(404) + daemonLogf("ERROR: %s\n", err) + return + } + node, err := GetNode(rinfo.hwaddr) + if err != nil { + w.WriteHeader(403) + daemonLogf("ERROR(%s): %s\n", rinfo.hwaddr, err) + return + } + + if node.AssetKey.Defined() && node.AssetKey.Get() != rinfo.assetkey { + w.WriteHeader(404) + daemonLogf("ERROR: Incorrect asset key for node: %s\n", node.Id.Get()) + updateStatus(node.Id.Get(), "KMODS_OVERLAY", "BAD_ASSET", rinfo.ipaddr) + return + } + + if node.KernelVersion.Defined() { + fileName := kernel.KmodsImage(node.KernelVersion.Get()) + + updateStatus(node.Id.Get(), "KMODS_OVERLAY", node.KernelVersion.Get()+".img", strings.Split(req.RemoteAddr, ":")[0]) + + err := sendFile(w, fileName, node.Id.Get()) + if err != nil { + daemonLogf("ERROR: %s\n", err) + } + + } else { + w.WriteHeader(503) + daemonLogf("WARNING: No 'kernel version' set for node %s\n", node.Id.Get()) + } +} diff --git a/internal/pkg/warewulfd/warewulfd.go b/internal/pkg/warewulfd/warewulfd.go index 7406d782..1600a637 100644 --- a/internal/pkg/warewulfd/warewulfd.go +++ b/internal/pkg/warewulfd/warewulfd.go @@ -48,6 +48,7 @@ func RunServer() error { http.HandleFunc("/ipxe/", IpxeSend) http.HandleFunc("/kernel/", KernelSend) + http.HandleFunc("/kmods/", KmodsSend) http.HandleFunc("/container/", ContainerSend) http.HandleFunc("/overlay-system/", SystemOverlaySend) http.HandleFunc("/overlay-runtime/", RuntimeOverlaySend) From 120318619403e90122b8b48548660acb4c4b16d9 Mon Sep 17 00:00:00 2001 From: Gregory Kurtzer Date: Thu, 17 Feb 2022 07:37:04 +0000 Subject: [PATCH 07/14] Support kernel overrides from the host or other containers --- internal/app/wwctl/kernel/delete/main.go | 2 +- internal/app/wwctl/kernel/delete/root.go | 10 ++++----- internal/app/wwctl/kernel/imprt/main.go | 2 +- internal/app/wwctl/kernel/list/main.go | 2 +- internal/app/wwctl/kernel/list/root.go | 12 +++++------ internal/app/wwctl/kernel/root.go | 6 +++--- internal/app/wwctl/node/list/main.go | 6 +++--- internal/app/wwctl/node/set/main.go | 6 +++--- internal/app/wwctl/node/set/root.go | 6 +++--- internal/app/wwctl/profile/list/main.go | 2 +- internal/app/wwctl/profile/set/main.go | 6 +++--- internal/app/wwctl/profile/set/root.go | 6 +++--- internal/pkg/node/constructors.go | 21 ++++++++++++++++--- internal/pkg/node/datastructure.go | 3 ++- internal/pkg/node/modifiers.go | 4 ++-- internal/pkg/overlay/overlay.go | 4 +++- internal/pkg/warewulfd/ipxe.go | 26 ++++++++++++------------ internal/pkg/warewulfd/kernel.go | 24 ++++++++++++++-------- internal/pkg/warewulfd/kmods.go | 10 +++------ 19 files changed, 90 insertions(+), 68 deletions(-) diff --git a/internal/app/wwctl/kernel/delete/main.go b/internal/app/wwctl/kernel/delete/main.go index c289a27d..ab2efe70 100644 --- a/internal/app/wwctl/kernel/delete/main.go +++ b/internal/app/wwctl/kernel/delete/main.go @@ -23,7 +23,7 @@ func CobraRunE(cmd *cobra.Command, args []string) error { ARG_LOOP: for _, arg := range args { for _, n := range nodes { - if n.KernelVersion.Get() == arg { + if n.KernelOverride.Get() == arg { wwlog.Printf(wwlog.ERROR, "Kernel is configured for nodes, skipping: %s\n", arg) continue ARG_LOOP } diff --git a/internal/app/wwctl/kernel/delete/root.go b/internal/app/wwctl/kernel/delete/root.go index 5fc68bea..1ae1c8b9 100644 --- a/internal/app/wwctl/kernel/delete/root.go +++ b/internal/app/wwctl/kernel/delete/root.go @@ -8,11 +8,11 @@ import ( var ( baseCmd = &cobra.Command{ DisableFlagsInUseLine: true, - Use: "delete [OPTIONS] KERNEL [...]", - Short: "Delete imported kernels", - Long: "This command will delete KERNEL versions that have been imported into Warewulf.", - RunE: CobraRunE, - Args: cobra.MinimumNArgs(1), + Use: "delete [OPTIONS] KERNEL [...]", + Short: "Delete imported kernels", + Long: "This command will delete KERNEL versions that have been imported into Warewulf.", + RunE: CobraRunE, + Args: cobra.MinimumNArgs(1), ValidArgsFunction: func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { if len(args) != 0 { return nil, cobra.ShellCompDirectiveNoFileComp diff --git a/internal/app/wwctl/kernel/imprt/main.go b/internal/app/wwctl/kernel/imprt/main.go index 97e3e219..d9513eff 100644 --- a/internal/app/wwctl/kernel/imprt/main.go +++ b/internal/app/wwctl/kernel/imprt/main.go @@ -70,7 +70,7 @@ func CobraRunE(cmd *cobra.Command, args []string) error { wwlog.Printf(wwlog.DEBUG, "Looking for profile default: %s\n", profile.Id.Get()) if profile.Id.Get() == "default" { wwlog.Printf(wwlog.DEBUG, "Found profile default, setting kernel version to: %s\n", args[0]) - profile.KernelVersion.Set(args[0]) + profile.KernelOverride.Set(args[0]) err := nodeDB.ProfileUpdate(profile) if err != nil { return errors.Wrap(err, "failed to update node profile") diff --git a/internal/app/wwctl/kernel/list/main.go b/internal/app/wwctl/kernel/list/main.go index a3a8d4ad..628a63b3 100644 --- a/internal/app/wwctl/kernel/list/main.go +++ b/internal/app/wwctl/kernel/list/main.go @@ -23,7 +23,7 @@ func CobraRunE(cmd *cobra.Command, args []string) error { nodemap := make(map[string]int) for _, n := range nodes { - nodemap[n.KernelVersion.Get()]++ + nodemap[n.KernelOverride.Get()]++ } fmt.Printf("%-35s %-25s %-6s\n", "KERNEL NAME", "KERNEL VERSION", "NODES") diff --git a/internal/app/wwctl/kernel/list/root.go b/internal/app/wwctl/kernel/list/root.go index fba84101..08fdbd09 100644 --- a/internal/app/wwctl/kernel/list/root.go +++ b/internal/app/wwctl/kernel/list/root.go @@ -5,12 +5,12 @@ import "github.com/spf13/cobra" var ( baseCmd = &cobra.Command{ DisableFlagsInUseLine: true, - Use: "list [OPTIONS]", - Short: "List imported Kernel images", - Long: "This command will list the kernels that have been imported into Warewulf.", - RunE: CobraRunE, - Args: cobra.ExactArgs(0), - Aliases: []string{"ls"}, + Use: "list [OPTIONS]", + Short: "List imported Kernel images", + Long: "This command will list the kernels that have been imported into Warewulf.", + RunE: CobraRunE, + Args: cobra.ExactArgs(0), + Aliases: []string{"ls"}, } ) diff --git a/internal/app/wwctl/kernel/root.go b/internal/app/wwctl/kernel/root.go index bb0cdb8d..3717a3b0 100644 --- a/internal/app/wwctl/kernel/root.go +++ b/internal/app/wwctl/kernel/root.go @@ -10,9 +10,9 @@ import ( var ( baseCmd = &cobra.Command{ DisableFlagsInUseLine: true, - Use: "kernel COMMAND [OPTIONS]", - Short: "Kernel Image Management", - Long: "This command manages Warewulf Kernels used for bootstrapping nodes", + Use: "kernel COMMAND [OPTIONS]", + Short: "Kernel Image Management", + Long: "This command manages Warewulf Kernels used for bootstrapping nodes", } ) diff --git a/internal/app/wwctl/node/list/main.go b/internal/app/wwctl/node/list/main.go index 0e6845c8..4fe66890 100644 --- a/internal/app/wwctl/node/list/main.go +++ b/internal/app/wwctl/node/list/main.go @@ -41,7 +41,7 @@ func CobraRunE(cmd *cobra.Command, args []string) error { fmt.Printf("%-20s %-18s %-12s %t\n", node.Id.Get(), "Discoverable", node.Discoverable.Source(), node.Discoverable.PrintB()) fmt.Printf("%-20s %-18s %-12s %s\n", node.Id.Get(), "Container", node.ContainerName.Source(), node.ContainerName.Print()) - fmt.Printf("%-20s %-18s %-12s %s\n", node.Id.Get(), "Kernel", node.KernelVersion.Source(), node.KernelVersion.Print()) + fmt.Printf("%-20s %-18s %-12s %s\n", node.Id.Get(), "KernelOverride", node.KernelOverride.Source(), node.KernelOverride.Print()) fmt.Printf("%-20s %-18s %-12s %s\n", node.Id.Get(), "KernelArgs", node.KernelArgs.Source(), node.KernelArgs.Print()) fmt.Printf("%-20s %-18s %-12s %s\n", node.Id.Get(), "SystemOverlay", node.SystemOverlay.Source(), node.SystemOverlay.Print()) fmt.Printf("%-20s %-18s %-12s %s\n", node.Id.Get(), "RuntimeOverlay", node.RuntimeOverlay.Source(), node.RuntimeOverlay.Print()) @@ -97,11 +97,11 @@ func CobraRunE(cmd *cobra.Command, args []string) error { } } else if ShowLong { - fmt.Printf("%-22s %-26s %-35s %s\n", "NODE NAME", "KERNEL", "CONTAINER", "OVERLAYS (S/R)") + fmt.Printf("%-22s %-26s %-35s %s\n", "NODE NAME", "KERNEL OVERRIDE", "CONTAINER", "OVERLAYS (S/R)") fmt.Println(strings.Repeat("=", 120)) for _, node := range node.FilterByName(nodes, args) { - fmt.Printf("%-22s %-26s %-35s %s\n", node.Id.Get(), node.KernelVersion.Print(), node.ContainerName.Print(), node.SystemOverlay.Print()+"/"+node.RuntimeOverlay.Print()) + fmt.Printf("%-22s %-26s %-35s %s\n", node.Id.Get(), node.KernelOverride.Print(), node.ContainerName.Print(), node.SystemOverlay.Print()+"/"+node.RuntimeOverlay.Print()) } } else { diff --git a/internal/app/wwctl/node/set/main.go b/internal/app/wwctl/node/set/main.go index 59f3e7c5..66324ea9 100644 --- a/internal/app/wwctl/node/set/main.go +++ b/internal/app/wwctl/node/set/main.go @@ -70,9 +70,9 @@ func CobraRunE(cmd *cobra.Command, args []string) error { n.AssetKey.Set(SetAssetKey) } - if SetKernel != "" { - wwlog.Printf(wwlog.VERBOSE, "Node: %s, Setting kernel to: %s\n", n.Id.Get(), SetKernel) - n.KernelVersion.Set(SetKernel) + if SetKernelOverride != "" { + wwlog.Printf(wwlog.VERBOSE, "Node: %s, Setting kernel override to: %s\n", n.Id.Get(), SetKernelOverride) + n.KernelOverride.Set(SetKernelOverride) } if SetKernelArgs != "" { diff --git a/internal/app/wwctl/node/set/root.go b/internal/app/wwctl/node/set/root.go index a3feec62..f405aebf 100644 --- a/internal/app/wwctl/node/set/root.go +++ b/internal/app/wwctl/node/set/root.go @@ -34,7 +34,7 @@ var ( } SetComment string SetContainer string - SetKernel string + SetKernelOverride string SetKernelArgs string SetNetName string SetNetDev string @@ -82,8 +82,8 @@ func init() { }); err != nil { log.Println(err) } - baseCmd.PersistentFlags().StringVarP(&SetKernel, "kernel", "K", "", "Set Kernel version for nodes") - if err := baseCmd.RegisterFlagCompletionFunc("kernel", func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { + baseCmd.PersistentFlags().StringVarP(&SetKernelOverride, "kerneloverride", "K", "", "Set kernel override version for nodes") + if err := baseCmd.RegisterFlagCompletionFunc("kerneloverride", func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { list, _ := kernel.ListKernels() return list, cobra.ShellCompDirectiveNoFileComp }); err != nil { diff --git a/internal/app/wwctl/profile/list/main.go b/internal/app/wwctl/profile/list/main.go index a419952e..03219706 100644 --- a/internal/app/wwctl/profile/list/main.go +++ b/internal/app/wwctl/profile/list/main.go @@ -33,7 +33,7 @@ func CobraRunE(cmd *cobra.Command, args []string) error { fmt.Printf("%-20s %-18s %s\n", profile.Id.Get(), "Cluster", profile.ClusterName.Print()) fmt.Printf("%-20s %-18s %s\n", profile.Id.Get(), "Container", profile.ContainerName.Print()) - fmt.Printf("%-20s %-18s %s\n", profile.Id.Get(), "Kernel", profile.KernelVersion.Print()) + fmt.Printf("%-20s %-18s %s\n", profile.Id.Get(), "KernelOverride", profile.KernelOverride.Print()) fmt.Printf("%-20s %-18s %s\n", profile.Id.Get(), "KernelArgs", profile.KernelArgs.Print()) fmt.Printf("%-20s %-18s %s\n", profile.Id.Get(), "Init", profile.Init.Print()) fmt.Printf("%-20s %-18s %s\n", profile.Id.Get(), "Root", profile.Root.Print()) diff --git a/internal/app/wwctl/profile/set/main.go b/internal/app/wwctl/profile/set/main.go index 09d4c288..18158196 100644 --- a/internal/app/wwctl/profile/set/main.go +++ b/internal/app/wwctl/profile/set/main.go @@ -75,9 +75,9 @@ func CobraRunE(cmd *cobra.Command, args []string) error { p.AssetKey.Set(SetAssetKey) } - if SetKernel != "" { - wwlog.Printf(wwlog.VERBOSE, "Profile: %s, Setting Kernel to: %s\n", p.Id.Get(), SetKernel) - p.KernelVersion.Set(SetKernel) + if SetKernelOverride != "" { + wwlog.Printf(wwlog.VERBOSE, "Profile: %s, Setting Kernel override version to: %s\n", p.Id.Get(), SetKernelOverride) + p.KernelOverride.Set(SetKernelOverride) } if SetKernelArgs != "" { diff --git a/internal/app/wwctl/profile/set/root.go b/internal/app/wwctl/profile/set/root.go index d8b08dc6..48782e63 100644 --- a/internal/app/wwctl/profile/set/root.go +++ b/internal/app/wwctl/profile/set/root.go @@ -37,7 +37,7 @@ var ( SetForce bool SetComment string SetContainer string - SetKernel string + SetKernelOverride string SetKernelArgs string SetClusterName string SetIpxe string @@ -79,8 +79,8 @@ func init() { }); err != nil { log.Println(err) } - baseCmd.PersistentFlags().StringVarP(&SetKernel, "kernel", "K", "", "Set Kernel version for nodes") - if err := baseCmd.RegisterFlagCompletionFunc("kernel", func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { + baseCmd.PersistentFlags().StringVarP(&SetKernelOverride, "kerneloverride", "K", "", "Set kernel override version for nodes") + if err := baseCmd.RegisterFlagCompletionFunc("kerneloverride", func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { list, _ := kernel.ListKernels() return list, cobra.ShellCompDirectiveNoFileComp }); err != nil { diff --git a/internal/pkg/node/constructors.go b/internal/pkg/node/constructors.go index ebf35397..ec8211be 100644 --- a/internal/pkg/node/constructors.go +++ b/internal/pkg/node/constructors.go @@ -72,7 +72,6 @@ func (config *nodeYaml) FindAllNodes() ([]NodeInfo, error) { n.Id.Set(nodename) n.Comment.Set(node.Comment) n.ContainerName.Set(node.ContainerName) - n.KernelVersion.Set(node.KernelVersion) n.KernelArgs.Set(node.KernelArgs) n.ClusterName.Set(node.ClusterName) n.Ipxe.Set(node.Ipxe) @@ -90,6 +89,12 @@ func (config *nodeYaml) FindAllNodes() ([]NodeInfo, error) { n.AssetKey.Set(node.AssetKey) n.Discoverable.Set(node.Discoverable) + if node.KernelOverride != "" { + n.KernelOverride.Set(node.KernelOverride) + } else if node.KernelVersion != "" { + n.KernelOverride.Set(node.KernelVersion) + } + for devname, netdev := range node.NetDevs { if _, ok := n.NetDevs[devname]; !ok { var netdev NetDevEntry @@ -134,7 +139,6 @@ func (config *nodeYaml) FindAllNodes() ([]NodeInfo, error) { n.Comment.SetAlt(config.NodeProfiles[p].Comment, p) n.ClusterName.SetAlt(config.NodeProfiles[p].ClusterName, p) n.ContainerName.SetAlt(config.NodeProfiles[p].ContainerName, p) - n.KernelVersion.SetAlt(config.NodeProfiles[p].KernelVersion, p) n.KernelArgs.SetAlt(config.NodeProfiles[p].KernelArgs, p) n.Ipxe.SetAlt(config.NodeProfiles[p].Ipxe, p) n.Init.SetAlt(config.NodeProfiles[p].Init, p) @@ -151,6 +155,12 @@ func (config *nodeYaml) FindAllNodes() ([]NodeInfo, error) { n.AssetKey.SetAlt(config.NodeProfiles[p].AssetKey, p) n.Discoverable.SetAlt(config.NodeProfiles[p].Discoverable, p) + if config.NodeProfiles[p].KernelOverride != "" { + n.KernelOverride.SetAlt(config.NodeProfiles[p].KernelOverride, p) + } else if config.NodeProfiles[p].KernelVersion != "" { + n.KernelOverride.SetAlt(config.NodeProfiles[p].KernelVersion, p) + } + for devname, netdev := range config.NodeProfiles[p].NetDevs { if _, ok := n.NetDevs[devname]; !ok { var netdev NetDevEntry @@ -218,7 +228,6 @@ func (config *nodeYaml) FindAllProfiles() ([]NodeInfo, error) { p.ContainerName.Set(profile.ContainerName) p.Ipxe.Set(profile.Ipxe) p.Init.Set(profile.Init) - p.KernelVersion.Set(profile.KernelVersion) p.KernelArgs.Set(profile.KernelArgs) p.IpmiNetmask.Set(profile.IpmiNetmask) p.IpmiPort.Set(profile.IpmiPort) @@ -232,6 +241,12 @@ func (config *nodeYaml) FindAllProfiles() ([]NodeInfo, error) { p.AssetKey.Set(profile.AssetKey) p.Discoverable.Set(profile.Discoverable) + if profile.KernelOverride != "" { + p.KernelOverride.Set(profile.KernelOverride) + } else if profile.KernelVersion != "" { + p.KernelOverride.Set(profile.KernelVersion) + } + for devname, netdev := range profile.NetDevs { if _, ok := p.NetDevs[devname]; !ok { var netdev NetDevEntry diff --git a/internal/pkg/node/datastructure.go b/internal/pkg/node/datastructure.go index 7b273f82..fed82f39 100644 --- a/internal/pkg/node/datastructure.go +++ b/internal/pkg/node/datastructure.go @@ -20,6 +20,7 @@ type NodeConf struct { ContainerName string `yaml:"container name,omitempty"` Ipxe string `yaml:"ipxe template,omitempty"` KernelVersion string `yaml:"kernel version,omitempty"` + KernelOverride string `yaml:"kernel override,omitempty"` KernelArgs string `yaml:"kernel args,omitempty"` IpmiUserName string `yaml:"ipmi username,omitempty"` IpmiPassword string `yaml:"ipmi password,omitempty"` @@ -71,7 +72,7 @@ type NodeInfo struct { ClusterName Entry ContainerName Entry Ipxe Entry - KernelVersion Entry + KernelOverride Entry KernelArgs Entry IpmiIpaddr Entry IpmiNetmask Entry diff --git a/internal/pkg/node/modifiers.go b/internal/pkg/node/modifiers.go index 6502be84..92628592 100644 --- a/internal/pkg/node/modifiers.go +++ b/internal/pkg/node/modifiers.go @@ -60,7 +60,7 @@ func (config *nodeYaml) NodeUpdate(node NodeInfo) error { config.Nodes[nodeID].ClusterName = node.ClusterName.GetReal() config.Nodes[nodeID].Ipxe = node.Ipxe.GetReal() config.Nodes[nodeID].Init = node.Init.GetReal() - config.Nodes[nodeID].KernelVersion = node.KernelVersion.GetReal() + config.Nodes[nodeID].KernelOverride = node.KernelOverride.GetReal() config.Nodes[nodeID].KernelArgs = node.KernelArgs.GetReal() config.Nodes[nodeID].IpmiIpaddr = node.IpmiIpaddr.GetReal() config.Nodes[nodeID].IpmiNetmask = node.IpmiNetmask.GetReal() @@ -148,7 +148,7 @@ func (config *nodeYaml) ProfileUpdate(profile NodeInfo) error { config.NodeProfiles[profileID].Ipxe = profile.Ipxe.GetReal() config.NodeProfiles[profileID].Init = profile.Init.GetReal() config.NodeProfiles[profileID].ClusterName = profile.ClusterName.GetReal() - config.NodeProfiles[profileID].KernelVersion = profile.KernelVersion.GetReal() + config.NodeProfiles[profileID].KernelOverride = profile.KernelOverride.GetReal() config.NodeProfiles[profileID].KernelArgs = profile.KernelArgs.GetReal() config.NodeProfiles[profileID].IpmiIpaddr = profile.IpmiIpaddr.GetReal() config.NodeProfiles[profileID].IpmiNetmask = profile.IpmiNetmask.GetReal() diff --git a/internal/pkg/overlay/overlay.go b/internal/pkg/overlay/overlay.go index 36083519..2a80ba97 100644 --- a/internal/pkg/overlay/overlay.go +++ b/internal/pkg/overlay/overlay.go @@ -25,6 +25,7 @@ type TemplateStruct struct { ClusterName string Container string KernelVersion string + KernelOverride string KernelArgs string Init string Root string @@ -174,7 +175,8 @@ func BuildOverlay(nodeInfo node.NodeInfo, overlayName string) error { tstruct.Hostname = nodeInfo.Id.Get() tstruct.ClusterName = nodeInfo.ClusterName.Get() tstruct.Container = nodeInfo.ContainerName.Get() - tstruct.KernelVersion = nodeInfo.KernelVersion.Get() + tstruct.KernelVersion = nodeInfo.KernelOverride.Get() + tstruct.KernelOverride = nodeInfo.KernelOverride.Get() tstruct.KernelArgs = nodeInfo.KernelArgs.Get() tstruct.Init = nodeInfo.Init.Get() tstruct.Root = nodeInfo.Root.Get() diff --git a/internal/pkg/warewulfd/ipxe.go b/internal/pkg/warewulfd/ipxe.go index 84c11808..e3fe9419 100644 --- a/internal/pkg/warewulfd/ipxe.go +++ b/internal/pkg/warewulfd/ipxe.go @@ -15,18 +15,18 @@ import ( ) type iPxeTemplate struct { - Message string - WaitTime string - Hostname string - Fqdn string - Id string - Cluster string - ContainerName string - Hwaddr string - Ipaddr string - Port string - KernelArgs string - KernelVersion string + Message string + WaitTime string + Hostname string + Fqdn string + Id string + Cluster string + ContainerName string + Hwaddr string + Ipaddr string + Port string + KernelArgs string + KernelOverride string } func IpxeSend(w http.ResponseWriter, req *http.Request) { @@ -140,7 +140,7 @@ func IpxeSend(w http.ResponseWriter, req *http.Request) { replace.Hwaddr = rinfo.hwaddr replace.ContainerName = node.ContainerName.Get() replace.KernelArgs = node.KernelArgs.Get() - replace.KernelVersion = node.KernelVersion.Get() + replace.KernelOverride = node.KernelOverride.Get() err = tmpl.Execute(w, replace) if err != nil { diff --git a/internal/pkg/warewulfd/kernel.go b/internal/pkg/warewulfd/kernel.go index 74286ee7..f386852d 100644 --- a/internal/pkg/warewulfd/kernel.go +++ b/internal/pkg/warewulfd/kernel.go @@ -6,6 +6,7 @@ import ( "strings" "github.com/hpcng/warewulf/internal/pkg/container" + "github.com/hpcng/warewulf/internal/pkg/kernel" ) func KernelSend(w http.ResponseWriter, req *http.Request) { @@ -29,18 +30,25 @@ func KernelSend(w http.ResponseWriter, req *http.Request) { return } - if node.ContainerName.Defined() { - fileName := container.KernelFind(node.ContainerName.Get()) + var fileName string + if node.KernelOverride.Defined() { + fileName = kernel.KernelImage(node.KernelOverride.Get()) - updateStatus(node.Id.Get(), "KERNEL", path.Base(fileName), strings.Split(req.RemoteAddr, ":")[0]) - - err := sendFile(w, fileName, node.Id.Get()) - if err != nil { - daemonLogf("ERROR: %s\n", err) - } + } else if node.ContainerName.Defined() { + fileName = container.KernelFind(node.ContainerName.Get()) } else { w.WriteHeader(503) daemonLogf("WARNING: No 'kernel version' set for node %s\n", node.Id.Get()) + + return } + + updateStatus(node.Id.Get(), "KERNEL", path.Base(fileName), strings.Split(req.RemoteAddr, ":")[0]) + + err = sendFile(w, fileName, node.Id.Get()) + if err != nil { + daemonLogf("ERROR: %s\n", err) + } + } diff --git a/internal/pkg/warewulfd/kmods.go b/internal/pkg/warewulfd/kmods.go index 13ace42b..a8378699 100644 --- a/internal/pkg/warewulfd/kmods.go +++ b/internal/pkg/warewulfd/kmods.go @@ -28,18 +28,14 @@ func KmodsSend(w http.ResponseWriter, req *http.Request) { return } - if node.KernelVersion.Defined() { - fileName := kernel.KmodsImage(node.KernelVersion.Get()) + if node.KernelOverride.Defined() { + fileName := kernel.KmodsImage(node.KernelOverride.Get()) - updateStatus(node.Id.Get(), "KMODS_OVERLAY", node.KernelVersion.Get()+".img", strings.Split(req.RemoteAddr, ":")[0]) + updateStatus(node.Id.Get(), "KMODS_OVERLAY", node.KernelOverride.Get()+".img", strings.Split(req.RemoteAddr, ":")[0]) err := sendFile(w, fileName, node.Id.Get()) if err != nil { daemonLogf("ERROR: %s\n", err) } - - } else { - w.WriteHeader(503) - daemonLogf("WARNING: No 'kernel version' set for node %s\n", node.Id.Get()) } } From 99952b90b7cd847ab32b8a8d1384aeb375ff5efe Mon Sep 17 00:00:00 2001 From: Gregory Kurtzer Date: Thu, 17 Feb 2022 07:50:39 +0000 Subject: [PATCH 08/14] Updated container recipes to include kernel and use upstream base containers --- containers/Docker/centos-8 | 5 +-- containers/Docker/rocky-8 | 5 +-- containers/Singularity/centos-8.def | 49 ++++++++++++++++++++--------- containers/Singularity/rocky-8.def | 49 ++++++++++++++++++++--------- 4 files changed, 74 insertions(+), 34 deletions(-) diff --git a/containers/Docker/centos-8 b/containers/Docker/centos-8 index 4df5070e..f1fe0f65 100644 --- a/containers/Docker/centos-8 +++ b/containers/Docker/centos-8 @@ -24,8 +24,6 @@ RUN dnf install -y --allowerasing coreutils \ which \ words -RUN sed -i 's/^root:.:/root::/g' /etc/passwd - # These changes make it possible for users to ssh into nodes even # if there is no shadow entry for the user RUN sed -i -e '/^account.*pam_unix\.so\s*$/s/\s*$/\ broken_shadow/' /etc/pam.d/system-auth @@ -34,3 +32,6 @@ RUN sed -i -e '/^account.*pam_unix\.so\s*$/s/\s*$/\ broken_shadow/' /etc/pam.d/p RUN systemctl unmask console-getty.service dev-hugepages.mount \ getty.target sys-fs-fuse-connections.mount systemd-logind.service \ systemd-remount-fs.service + +RUN systemctl enable network +RUN touch /etc/sysconfig/disable-deprecation-warnings diff --git a/containers/Docker/rocky-8 b/containers/Docker/rocky-8 index 9c500913..2e0a9969 100644 --- a/containers/Docker/rocky-8 +++ b/containers/Docker/rocky-8 @@ -24,8 +24,6 @@ RUN dnf install -y --allowerasing coreutils \ which \ words -RUN sed -i 's/^root:.:/root::/g' /etc/passwd - # These changes make it possible for users to ssh into nodes even # if there is no shadow entry for the user RUN sed -i -e '/^account.*pam_unix\.so\s*$/s/\s*$/\ broken_shadow/' /etc/pam.d/system-auth @@ -34,3 +32,6 @@ RUN sed -i -e '/^account.*pam_unix\.so\s*$/s/\s*$/\ broken_shadow/' /etc/pam.d/p RUN systemctl unmask console-getty.service dev-hugepages.mount \ getty.target sys-fs-fuse-connections.mount systemd-logind.service \ systemd-remount-fs.service + +RUN systemctl enable network +RUN touch /etc/sysconfig/disable-deprecation-warnings diff --git a/containers/Singularity/centos-8.def b/containers/Singularity/centos-8.def index a3a6e66f..8ed203ab 100644 --- a/containers/Singularity/centos-8.def +++ b/containers/Singularity/centos-8.def @@ -1,21 +1,40 @@ -BootStrap: yum -OSVersion: 8 -MirrorURL: http://mirror.centos.org/centos-%{OSVERSION}/%{OSVERSION}/BaseOS/x86_64/os -Include: dnf - +BootStrap: docker +From: centos:8 %post +dnf install -y --allowerasing coreutils \ + cpio \ + dhclient \ + e2fsprogs \ + ethtool \ + findutils \ + initscripts \ + ipmitool \ + iproute \ + kernel-core \ + net-tools \ + network-scripts \ + nfs-utils \ + openssh-clients \ + openssh-server \ + pciutils \ + psmisc \ + rsync \ + rsyslog \ + strace \ + wget \ + which \ + words - sed -i 's/^root:.:/root::/g' /etc/passwd +# These changes make it possible for users to ssh into nodes even +# if there is no shadow entry for the user +sed -i -e '/^account.*pam_unix\.so\s*$/s/\s*$/\ broken_shadow/' /etc/pam.d/system-auth +sed -i -e '/^account.*pam_unix\.so\s*$/s/\s*$/\ broken_shadow/' /etc/pam.d/password-auth - dnf install -y basesystem bash chkconfig coreutils e2fsprogs \ - ethtool filesystem findutils gawk grep initscripts iproute \ - iputils net-tools nfs-utils pam psmisc rsync sed setup \ - shadow-utils rsyslog tzdata util-linux words zlib tar less \ - gzip which util-linux openssh-clients openssh-server dhclient \ - pciutils vim-minimal shadow-utils strace cronie crontabs cpio \ - wget centos-release ipmitool yum network-scripts +systemctl unmask console-getty.service dev-hugepages.mount \ + getty.target sys-fs-fuse-connections.mount systemd-logind.service \ + systemd-remount-fs.service - systemctl enable network +systemctl enable network - touch /etc/sysconfig/disable-deprecation-warnings \ No newline at end of file +touch /etc/sysconfig/disable-deprecation-warnings \ No newline at end of file diff --git a/containers/Singularity/rocky-8.def b/containers/Singularity/rocky-8.def index 1f37857f..eb924369 100644 --- a/containers/Singularity/rocky-8.def +++ b/containers/Singularity/rocky-8.def @@ -1,21 +1,40 @@ -BootStrap: yum -OSVersion: 8 -MirrorURL: http://dl.rockylinux.org/pub/rocky/%{OSVERSION}/BaseOS/x86_64/os/ -Include: dnf - +BootStrap: docker +From: rockylinux:8 %post +dnf install -y --allowerasing coreutils \ + cpio \ + dhclient \ + e2fsprogs \ + ethtool \ + findutils \ + initscripts \ + ipmitool \ + iproute \ + kernel-core \ + net-tools \ + network-scripts \ + nfs-utils \ + openssh-clients \ + openssh-server \ + pciutils \ + psmisc \ + rsync \ + rsyslog \ + strace \ + wget \ + which \ + words - sed -i 's/^root:.:/root::/g' /etc/passwd +# These changes make it possible for users to ssh into nodes even +# if there is no shadow entry for the user +sed -i -e '/^account.*pam_unix\.so\s*$/s/\s*$/\ broken_shadow/' /etc/pam.d/system-auth +sed -i -e '/^account.*pam_unix\.so\s*$/s/\s*$/\ broken_shadow/' /etc/pam.d/password-auth - dnf install -y basesystem bash chkconfig coreutils e2fsprogs \ - ethtool filesystem findutils gawk grep initscripts iproute \ - iputils net-tools nfs-utils pam psmisc rsync sed setup \ - shadow-utils rsyslog tzdata util-linux words zlib tar less \ - gzip which util-linux openssh-clients openssh-server dhclient \ - pciutils vim-minimal shadow-utils strace cronie crontabs cpio \ - wget rocky-release ipmitool yum network-scripts +systemctl unmask console-getty.service dev-hugepages.mount \ + getty.target sys-fs-fuse-connections.mount systemd-logind.service \ + systemd-remount-fs.service - systemctl enable network +systemctl enable network - touch /etc/sysconfig/disable-deprecation-warnings \ No newline at end of file +touch /etc/sysconfig/disable-deprecation-warnings \ No newline at end of file From 93bcd14e0d70c0686f75ae5909d99b555f399d5a Mon Sep 17 00:00:00 2001 From: Gregory Kurtzer Date: Thu, 24 Feb 2022 22:01:06 -0800 Subject: [PATCH 09/14] Added a debugging comment --- internal/app/wwctl/container/list/main.go | 1 + 1 file changed, 1 insertion(+) diff --git a/internal/app/wwctl/container/list/main.go b/internal/app/wwctl/container/list/main.go index b9fce309..523dbb12 100644 --- a/internal/app/wwctl/container/list/main.go +++ b/internal/app/wwctl/container/list/main.go @@ -32,6 +32,7 @@ func CobraRunE(cmd *cobra.Command, args []string) error { nodemap[source] = 0 } + wwlog.Printf(wwlog.DEBUG, "Finding kernel version for: %s\n", source) kernelVersion := container.KernelVersion(source) fmt.Printf("%-25s %-6d %s\n", source, nodemap[source], kernelVersion) From 99bdc8a35aaadcfda3689e191ec76709c5b301e9 Mon Sep 17 00:00:00 2001 From: Gregory Kurtzer Date: Thu, 24 Feb 2022 22:01:46 -0800 Subject: [PATCH 10/14] Fix issue with improper kernel version probe --- internal/pkg/container/kernel.go | 63 +++++++++++--------------------- 1 file changed, 21 insertions(+), 42 deletions(-) diff --git a/internal/pkg/container/kernel.go b/internal/pkg/container/kernel.go index 9a9cd8c2..b86aad03 100644 --- a/internal/pkg/container/kernel.go +++ b/internal/pkg/container/kernel.go @@ -1,41 +1,40 @@ package container import ( - "fmt" "path" "path/filepath" - "sort" "github.com/hpcng/warewulf/internal/pkg/util" "github.com/hpcng/warewulf/internal/pkg/wwlog" ) var ( - kernelSearchPaths = []string{ - // This is a printf format where the %s will be the kernel version - `/boot/vmlinuz-%s`, - `/boot/vmlinuz-%s.gz`, - `/lib/modules/%s/vmlinuz`, - `/lib/modules/%s/vmlinuz.gz`, + kernelNames = []string{ + `vmlinux`, + `vmlinuz`, + `vmlinuz.gz`, } + modulePath = "/lib/modules/" ) func KernelFind(container string) string { + wwlog.Printf(wwlog.DEBUG, "Finding kernel\n") container_path := RootFsDir(container) if container_path == "" { return "" } - kernelVersion := KernelVersion(container) - if kernelVersion == "" { - return "" - } - - for _, searchPath := range kernelSearchPaths { - testPath := fmt.Sprintf(searchPath, kernelVersion) - wwlog.Printf(wwlog.VERBOSE, "Looking for kernel at: '%s'\n", testPath) - if util.IsFile(path.Join(container_path, testPath)) { - return path.Join(container_path, testPath) + for _, kname := range kernelNames { + wwlog.Printf(wwlog.DEBUG, "Checking for kernel name within module path: %s\n", kname) + kernelPaths, err := filepath.Glob(path.Join(container_path, modulePath, "/*/", kname)) + if err != nil { + return "" + } + for _, kernelPath := range kernelPaths { + wwlog.Printf(wwlog.DEBUG, "Checking for kernel path: %s\n", kernelPath) + if util.IsFile(kernelPath) { + return kernelPath + } } } @@ -43,31 +42,11 @@ func KernelFind(container string) string { } func KernelVersion(container string) string { - container_path := RootFsDir(container) - if container_path == "" { + wwlog.Printf(wwlog.DEBUG, "Finding kernel version inside container: %s\n", container) + kernel := KernelFind(container) + if kernel == "" { return "" } - module_lib_path := path.Join(container_path, "/lib/modules/*") - wwlog.Printf(wwlog.DEBUG, "Searching for kernel modules at: %s\n", module_lib_path) - kernelversions, err := filepath.Glob(module_lib_path) - if err != nil { - return "" - } - - if len(kernelversions) > 1 { - sort.Slice(kernelversions, func(i, j int) bool { - return kernelversions[i] > kernelversions[j] - }) - wwlog.Printf(wwlog.VERBOSE, "Multiple kernels found in container: %s\n", container) - - wwlog.Printf(wwlog.DEBUG, "Found lib path: '%s'\n", kernelversions[0]) - return path.Base(kernelversions[0]) - } else if len(kernelversions) == 1 { - wwlog.Printf(wwlog.DEBUG, "Found lib path: '%s'\n", kernelversions[0]) - - return path.Base(kernelversions[0]) - } - - return "" + return path.Base(path.Dir(kernel)) } From fa925d632c79a2d6154da65ce91e545da945db4d Mon Sep 17 00:00:00 2001 From: Gregory Kurtzer Date: Thu, 24 Feb 2022 22:02:22 -0800 Subject: [PATCH 11/14] Update container files to include exit script, excludes, and HEREDOCs --- containers/Docker/centos-8 | 33 ++++++++++++++++++++++++--------- containers/Docker/rocky-8 | 34 +++++++++++++++++++++++++--------- 2 files changed, 49 insertions(+), 18 deletions(-) diff --git a/containers/Docker/centos-8 b/containers/Docker/centos-8 index f1fe0f65..da6fc27f 100644 --- a/containers/Docker/centos-8 +++ b/containers/Docker/centos-8 @@ -24,14 +24,29 @@ RUN dnf install -y --allowerasing coreutils \ which \ words -# These changes make it possible for users to ssh into nodes even -# if there is no shadow entry for the user -RUN sed -i -e '/^account.*pam_unix\.so\s*$/s/\s*$/\ broken_shadow/' /etc/pam.d/system-auth -RUN sed -i -e '/^account.*pam_unix\.so\s*$/s/\s*$/\ broken_shadow/' /etc/pam.d/password-auth +RUN < Date: Thu, 24 Feb 2022 22:03:01 -0800 Subject: [PATCH 12/14] Change exclude name to plural --- internal/pkg/container/build.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/internal/pkg/container/build.go b/internal/pkg/container/build.go index 6be782f9..05e98ef4 100644 --- a/internal/pkg/container/build.go +++ b/internal/pkg/container/build.go @@ -55,7 +55,7 @@ func Build(name string, buildForce bool) error { cmd = fmt.Sprintf("cd %s; find . -xdev -xautofs | cpio --quiet -o -H newc | %s -c > \"%s\"", rootfsPath, compressor, imagePath) } else { wwlog.Printf(wwlog.DEBUG, "Building VNFS image with excludes: '%s' -> '%s'\n", rootfsPath, imagePath) - cmd = fmt.Sprintf("cd %s; find . -xdev -xautofs | grep -v -f ./etc/warewulf/exclude | cpio --quiet -o -H newc | %s -c > \"%s\"", rootfsPath, compressor, imagePath) + cmd = fmt.Sprintf("cd %s; find . -xdev -xautofs | grep -v -f ./etc/warewulf/excludes | cpio --quiet -o -H newc | %s -c > \"%s\"", rootfsPath, compressor, imagePath) } wwlog.Printf(wwlog.DEBUG, "RUNNING: %s\n", cmd) err = exec.Command("/bin/sh", "-c", cmd).Run() From a72942590ff54f47c04ba2e30e0864172c67bc6d Mon Sep 17 00:00:00 2001 From: Gregory Kurtzer Date: Thu, 24 Feb 2022 22:05:45 -0800 Subject: [PATCH 13/14] include /lib/firmware in kernel build --- internal/pkg/kernel/kernel.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/internal/pkg/kernel/kernel.go b/internal/pkg/kernel/kernel.go index 37941032..53a58538 100644 --- a/internal/pkg/kernel/kernel.go +++ b/internal/pkg/kernel/kernel.go @@ -198,7 +198,7 @@ func Build(kernelVersion, kernelName, root string) (string, error) { wwlog.Printf(wwlog.VERBOSE, "Using PIGZ to compress the container: %s\n", compressor) } - cmd := fmt.Sprintf("cd %s; find .%s | cpio --quiet -o -L -H newc | %s -c > \"%s\"", root, kernelDriversRelative, compressor, driversDestination) + cmd := fmt.Sprintf("cd %s; find .%s ./lib/firmware | cpio --quiet -o -L -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() From ca6a8057311a9390f956b11b78e9965c630fd988 Mon Sep 17 00:00:00 2001 From: Gregory Kurtzer Date: Thu, 24 Feb 2022 22:10:28 -0800 Subject: [PATCH 14/14] Sort kernel paths to find the biggest version. Note we can do better as this is an alpha sort, so 9 is always bigger than 10. --- internal/pkg/container/kernel.go | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/internal/pkg/container/kernel.go b/internal/pkg/container/kernel.go index b86aad03..9d74ee21 100644 --- a/internal/pkg/container/kernel.go +++ b/internal/pkg/container/kernel.go @@ -3,6 +3,7 @@ package container import ( "path" "path/filepath" + "sort" "github.com/hpcng/warewulf/internal/pkg/util" "github.com/hpcng/warewulf/internal/pkg/wwlog" @@ -30,6 +31,11 @@ func KernelFind(container string) string { if err != nil { return "" } + + sort.Slice(kernelPaths, func(i, j int) bool { + return kernelPaths[i] > kernelPaths[j] + }) + for _, kernelPath := range kernelPaths { wwlog.Printf(wwlog.DEBUG, "Checking for kernel path: %s\n", kernelPath) if util.IsFile(kernelPath) {