From 03ef7447e901f039391c12fdfda582a14cd71ebd Mon Sep 17 00:00:00 2001 From: Christian Goll Date: Thu, 20 Jul 2023 12:17:46 +0200 Subject: [PATCH] copy shim/grub on default profile container change Signed-off-by: Christian Goll --- internal/app/wwctl/container/exec/main.go | 11 ++++++++ internal/pkg/api/container/container.go | 4 +++ internal/pkg/api/profile/profile.go | 17 +++++++++++- internal/pkg/container/grub.go | 33 +++++++++-------------- internal/pkg/container/shim.go | 27 ++++++++----------- internal/pkg/node/constructors.go | 1 - internal/pkg/node/datastructure.go | 1 - internal/pkg/warewulfd/copyshim.go | 31 ++++++++++++++------- 8 files changed, 76 insertions(+), 49 deletions(-) diff --git a/internal/app/wwctl/container/exec/main.go b/internal/app/wwctl/container/exec/main.go index bc622de2..f5ecd31c 100644 --- a/internal/app/wwctl/container/exec/main.go +++ b/internal/app/wwctl/container/exec/main.go @@ -12,7 +12,9 @@ import ( "time" "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/warewulfd" "github.com/hpcng/warewulf/internal/pkg/wwlog" "github.com/spf13/cobra" ) @@ -133,6 +135,15 @@ func CobraRunE(cmd *cobra.Command, args []string) error { wwlog.Error("Could not build container %s: %s", containerName, err) os.Exit(1) } + nodeDB, err := node.New() + if err != nil { + wwlog.Warn("couldn't open node database, so can't update shim/grub if this container is used in default profile: %s", err) + } else { + profileMap, _ := nodeDB.MapAllProfiles() + if _, ok := profileMap["default"]; ok && profileMap["default"].ContainerName.Get() == containerName { + return warewulfd.CopyShimGrub() + } + } return nil } diff --git a/internal/pkg/api/container/container.go b/internal/pkg/api/container/container.go index 1942aed8..54497288 100644 --- a/internal/pkg/api/container/container.go +++ b/internal/pkg/api/container/container.go @@ -271,6 +271,10 @@ func ContainerImport(cip *wwapiv1.ContainerImportParameter) (containerName strin err = errors.Wrap(err, "failed to update profile") return } + err = warewulfd.CopyShimGrub() + if err != nil { + wwlog.Warn("couldn't copy shim/grub of default container: %s", err) + } } } // TODO: We need this in a function with a flock around it. diff --git a/internal/pkg/api/profile/profile.go b/internal/pkg/api/profile/profile.go index e6ca6c68..731d546c 100644 --- a/internal/pkg/api/profile/profile.go +++ b/internal/pkg/api/profile/profile.go @@ -8,6 +8,7 @@ import ( "github.com/hpcng/warewulf/internal/pkg/api/routes/wwapiv1" "github.com/hpcng/warewulf/internal/pkg/node" "github.com/hpcng/warewulf/internal/pkg/util" + "github.com/hpcng/warewulf/internal/pkg/warewulfd" "github.com/hpcng/warewulf/internal/pkg/wwlog" "github.com/pkg/errors" "gopkg.in/yaml.v2" @@ -24,7 +25,21 @@ func ProfileSet(set *wwapiv1.ProfileSetParameter) (err error) { if err != nil { return errors.Wrap(err, "Could not open database") } - return apinode.DbSave(&nodeDB) + + var pConf node.NodeConf + err = yaml.Unmarshal([]byte(set.NodeConfYaml), &pConf) + if err != nil { + wwlog.Error(fmt.Sprintf("%v", err.Error())) + return + } + dbError := apinode.DbSave(&nodeDB) + if util.InSlice(set.ProfileNames, "default") { + err = warewulfd.CopyShimGrub() + if err != nil { + wwlog.Warn("shim/grub couldn't be copied: %s", err) + } + } + return dbError } // ProfileSetParameterCheck does error checking on ProfileSetParameter. diff --git a/internal/pkg/container/grub.go b/internal/pkg/container/grub.go index b1f81b84..9b6d97b4 100644 --- a/internal/pkg/container/grub.go +++ b/internal/pkg/container/grub.go @@ -1,9 +1,9 @@ package container import ( + "os" "path" "path/filepath" - "sort" "github.com/hpcng/warewulf/internal/pkg/wwlog" ) @@ -12,17 +12,19 @@ func grubDirs() []string { return []string{ `/usr/share/grub2/x86_64-efi`, `/usr/share/efi/x86_64/`, + `/boot/efi/EFI/*/`, } } func grubNames() []string { return []string{ `grub-tpm.efi`, `grub.efi`, + `grubx64.efi`, } } /* -Tries to find a grub.efi in the used container +find a grub.efi in the used container */ func GrubFind(container string) string { wwlog.Debug("Finding grub") @@ -32,26 +34,15 @@ func GrubFind(container string) string { } for _, grubdir := range grubDirs() { wwlog.Debug("Checking grub directory: %s", grubdir) - for _, shimname := range shimNames() { - wwlog.Debug("Checking for shim name: %s", shimname) - grubPaths, err := filepath.Glob(path.Join(container_path, grubdir, shimname)) - if err != nil { - return "" - } - if len(grubPaths) == 0 { - continue - } - sort.Slice(grubPaths, func(i, j int) bool { - return grubPaths[i] > grubPaths[j] - }) - for _, grubPath := range grubPaths { - wwlog.Debug("Checking for grub path: %s", grubPath) - // Only succeeds if shimPath exists and, if a + for _, grubname := range grubNames() { + wwlog.Debug("Checking for grub name: %s", grubname) + grubPaths, _ := filepath.Glob(path.Join(container_path, grubdir, grubname)) + for _, grubpath := range grubPaths { + wwlog.Debug("Checking for grub path: %s", grubpath) + // Only succeeds if grubpath exists and, if a // symlink, links to a path that also exists - grubPath, err = filepath.EvalSymlinks(grubPath) - if err == nil { - wwlog.Debug("found grub: %s", grubPath) - return grubPath + if _, err := os.Stat(grubpath); err == nil { + return grubpath } } } diff --git a/internal/pkg/container/shim.go b/internal/pkg/container/shim.go index 575d04fd..aa704751 100644 --- a/internal/pkg/container/shim.go +++ b/internal/pkg/container/shim.go @@ -1,9 +1,9 @@ package container import ( + "os" "path" "path/filepath" - "sort" "github.com/hpcng/warewulf/internal/pkg/wwlog" ) @@ -11,16 +11,22 @@ import ( func shimDirs() []string { return []string{ `/usr/share/efi/x86_64/`, - `/usr/lib64/`, - ``} + `/usr/lib64/efi`, + `/boot/efi/EFI/*/`, + } } func shimNames() []string { return []string{ `shim.efi`, `shim-sles.efi`, + `shimx64.efi`, + `shim-susesigned.efi`, } } +/* +find the path of the shim binary +*/ func ShimFind(container string) string { wwlog.Debug("Finding shim") container_path := RootFsDir(container) @@ -31,23 +37,12 @@ func ShimFind(container string) string { wwlog.Debug("Checking shim directory: %s", shimdir) for _, shimname := range shimNames() { wwlog.Debug("Checking for shim name: %s", shimname) - shimPaths, err := filepath.Glob(path.Join(container_path, shimdir, shimname)) - if err != nil { - return "" - } - if len(shimPaths) == 0 { - continue - } - sort.Slice(shimPaths, func(i, j int) bool { - return shimPaths[i] > shimPaths[j] - }) + shimPaths, _ := filepath.Glob(path.Join(container_path, shimdir, shimname)) for _, shimPath := range shimPaths { wwlog.Debug("Checking for shim path: %s", shimPath) // Only succeeds if shimPath exists and, if a // symlink, links to a path that also exists - shimPath, err = filepath.EvalSymlinks(shimPath) - if err == nil { - wwlog.Debug("found shim: %s", shimPath) + if _, err := os.Stat(shimPath); err == nil { return shimPath } } diff --git a/internal/pkg/node/constructors.go b/internal/pkg/node/constructors.go index eb0baf53..857f93cf 100644 --- a/internal/pkg/node/constructors.go +++ b/internal/pkg/node/constructors.go @@ -31,7 +31,6 @@ defaultnode: init: /sbin/init root: initramfs ipxe template: default - grub template: grub.cfg.ww boot method: ipxe profiles: - default diff --git a/internal/pkg/node/datastructure.go b/internal/pkg/node/datastructure.go index aa49ce64..0965570b 100644 --- a/internal/pkg/node/datastructure.go +++ b/internal/pkg/node/datastructure.go @@ -20,7 +20,6 @@ type NodeConf struct { ClusterName string `yaml:"cluster name,omitempty" lopt:"cluster" sopt:"c" comment:"Set cluster group"` ContainerName string `yaml:"container name,omitempty" lopt:"container" sopt:"C" comment:"Set container name"` Ipxe string `yaml:"ipxe template,omitempty" lopt:"ipxe" comment:"Set the iPXE template name"` - Grub string `yaml:"grub template,omitempty" lopt:"grub" comment:"Set the grub template name"` // Deprecated start // Kernel settings here are deprecated and here for backward compatibility KernelVersion string `yaml:"kernel version,omitempty"` diff --git a/internal/pkg/warewulfd/copyshim.go b/internal/pkg/warewulfd/copyshim.go index 7660fd02..ac021e13 100644 --- a/internal/pkg/warewulfd/copyshim.go +++ b/internal/pkg/warewulfd/copyshim.go @@ -2,9 +2,11 @@ package warewulfd import ( "fmt" + "os" "path" warewulfconf "github.com/hpcng/warewulf/internal/pkg/config" + "github.com/hpcng/warewulf/internal/pkg/wwlog" "github.com/hpcng/warewulf/internal/pkg/container" "github.com/hpcng/warewulf/internal/pkg/node" @@ -17,6 +19,7 @@ to the tftp directory */ func CopyShimGrub() (err error) { + wwlog.Debug("copy shim and grub binaries") nodeDB, err := node.New() if err != nil { return err @@ -29,24 +32,34 @@ func CopyShimGrub() (err error) { if err != nil { return err } - if _, ok := profiles["default"]; ok { + if _, ok := profiles["default"]; !ok { return fmt.Errorf("default profile doesn't exist") } - if profiles["default"].BootMethod.Get() == "ipxe" { + // *Entry.Get doesn't work the same as it works for nodes! + if profiles["default"].BootMethod.Get() == "ipxe" || profiles["default"].BootMethod.Get() == "" { + wwlog.Verbose("default profile uses ipxe boot") return } - shimPath := container.ShimFind("default") + shimPath := container.ShimFind(profiles["default"].ContainerName.Get()) if shimPath == "" { - return fmt.Errorf("no shim found in the default profile") + return fmt.Errorf("no shim found in the container: %s", profiles["default"].ContainerName.Get()) } - err = util.CopyFile(shimPath, path.Join(conf.TFTP.TftpRoot, "shim.efi")) + err = util.CopyFile(shimPath, path.Join(conf.Paths.Tftpdir, "warewulf", "shim.efi")) if err != nil { return err } - grubPath := container.GrubFind("default") - if shimPath == "" { - return fmt.Errorf("no grub found in the default profile") + _ = os.Chmod(path.Join(conf.Paths.Tftpdir, "warewulf", "shim.efi"), 0o755) + grubPath := container.GrubFind(profiles["default"].ContainerName.Get()) + if grubPath == "" { + return fmt.Errorf("no grub found in the container: %s", profiles["default"].ContainerName.Get()) } - err = util.CopyFile(grubPath, path.Join(conf.TFTP.TftpRoot, "grub.efi")) + err = util.CopyFile(grubPath, path.Join(conf.Paths.Tftpdir, "warewulf", "grub.efi")) + if err != nil { + return err + } + _ = os.Chmod(path.Join(conf.Paths.Tftpdir, "warewulf", "grub.efi"), 0o755) + err = util.CopyFile(grubPath, path.Join(conf.Paths.Tftpdir, "warewulf", "grubx64.efi")) + _ = os.Chmod(path.Join(conf.Paths.Tftpdir, "warewulf", "grubx64.efi"), 0o755) + return }