diff --git a/internal/app/wwctl/kernel/imprt/main.go b/internal/app/wwctl/kernel/imprt/main.go index 47a2e636..4a586366 100644 --- a/internal/app/wwctl/kernel/imprt/main.go +++ b/internal/app/wwctl/kernel/imprt/main.go @@ -49,12 +49,12 @@ func CobraRunE(cmd *cobra.Command, args []string) error { } else if OptDetect && (OptContainer != "") { kernelName = OptContainer } - output, err := kernel.Build(kernelVersion, kernelName, OptRoot) + err = kernel.Build(kernelVersion, kernelName, OptRoot) if err != nil { wwlog.Error("Failed building kernel: %s", err) os.Exit(1) } else { - fmt.Printf("%s: %s\n", kernelName, output) + fmt.Printf("%s: %s\n", kernelName, "Finished kernel build") } if SetDefault { diff --git a/internal/pkg/kernel/kernel.go b/internal/pkg/kernel/kernel.go index 47395d5c..2145bc9e 100644 --- a/internal/pkg/kernel/kernel.go +++ b/internal/pkg/kernel/kernel.go @@ -111,9 +111,13 @@ func ListKernels() ([]string, error) { return ret, nil } -func Build(kernelVersion, kernelName, root string) (string, error) { - kernelDriversRelative := path.Join("/lib/modules/", kernelVersion) - kernelDrivers := path.Join(root, kernelDriversRelative) +/* +Triggers the kernel extraction and build of the modules for the given +kernel version. A name for this kernel and were to find has also to be +supplied +*/ +func Build(kernelVersion, kernelName, root string) error { + kernelDrivers := path.Join(root, "/lib/modules/", kernelVersion) kernelDestination := KernelImage(kernelName) driversDestination := KmodsImage(kernelName) versionDestination := KernelVersionFile(kernelName) @@ -122,17 +126,17 @@ func Build(kernelVersion, kernelName, root string) (string, error) { // 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") + 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") + 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) + return fmt.Errorf("failed to create version dest: %s", err) } for _, searchPath := range kernelSearchPaths { @@ -146,20 +150,20 @@ func Build(kernelVersion, kernelName, root string) (string, error) { if kernelSource == "" { wwlog.Error("Could not locate kernel image") - return "", errors.New("could not locate kernel image") + return errors.New("could not locate kernel image") } else { wwlog.Info("Found kernel at: %s", kernelSource) } if !util.IsDir(kernelDrivers) { - return "", errors.New("Could not locate kernel drivers") + return errors.New("Could not locate kernel drivers") } wwlog.Verbose("Setting up Kernel") if _, err := os.Stat(kernelSource); err == nil { kernel, err := os.Open(kernelSource) if err != nil { - return "", errors.Wrap(err, "could not open kernel") + return errors.Wrap(err, "could not open kernel") } defer kernel.Close() @@ -169,20 +173,20 @@ func Build(kernelVersion, kernelName, root string) (string, error) { writer, err := os.Create(kernelDestination) if err != nil { - return "", errors.Wrap(err, "could not decompress kernel") + 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") + 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") + return errors.Wrap(err, "could not copy kernel") } } @@ -197,7 +201,7 @@ func Build(kernelVersion, kernelName, root string) (string, error) { root, driversDestination, []string{ - "." + kernelDriversRelative, + "." + kernelDrivers, "./lib/firmware"}, []string{}, // ignore cross-device files @@ -207,25 +211,25 @@ func Build(kernelVersion, kernelName, root string) (string, error) { "-L") if err != nil { - return "", err + return err } } wwlog.Verbose("Creating version file") file, err := os.Create(versionDestination) if err != nil { - return "", errors.Wrap(err, "Failed to create version file") + 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") + 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 errors.Wrap(err, "Could not sync kernel version") } - return "Done", nil + return nil } func DeleteKernel(name string) error { diff --git a/internal/pkg/kernel/kernel_test.go b/internal/pkg/kernel/kernel_test.go new file mode 100644 index 00000000..e5b12128 --- /dev/null +++ b/internal/pkg/kernel/kernel_test.go @@ -0,0 +1,66 @@ +package kernel + +import ( + "os" + "path" + "testing" + + warewulfconf "github.com/hpcng/warewulf/internal/pkg/config" + "github.com/hpcng/warewulf/internal/pkg/util" + "github.com/hpcng/warewulf/internal/pkg/wwlog" + "github.com/stretchr/testify/assert" +) + +var kernelBuildTests = []struct { + kernelVersion string + kernelName string + kernelFileName string + succeed bool +}{ + {"4.3.2.1", "kernel1", "vmlinuz-1.2.3.4.gz", false}, + {"1.2.3.4", "kernel1", "vmlinuz-1.2.3.4.gz", true}, +} + +func Test_BuildKernel(t *testing.T) { + wwlog.SetLogLevel(wwlog.DEBUG) + srvDir, err := os.MkdirTemp(os.TempDir(), "ww-test-srv-*") + assert.NoError(t, err) + defer os.RemoveAll(srvDir) + conf := warewulfconf.Get() + conf.Paths.WWProvisiondir = srvDir + kernelDir, err := os.MkdirTemp(os.TempDir(), "ww-test-kernelImage-*") + assert.NoError(t, err) + defer os.RemoveAll(kernelDir) + { + err = os.MkdirAll(path.Join(kernelDir, "boot"), 0755) + assert.NoError(t, err) + for _, tt := range kernelBuildTests { + _, err = os.Create(path.Join(kernelDir, "boot", tt.kernelFileName)) + assert.NoError(t, err) + err = os.MkdirAll(path.Join(kernelDir, "lib/modules", tt.kernelVersion), 0755) + assert.NoError(t, err) + _, err = os.Create(path.Join(kernelDir, "lib/modules", tt.kernelVersion, "test-module")) + assert.NoError(t, err) + err = os.MkdirAll(path.Join(kernelDir, "lib/firmware"), 0755) + assert.NoError(t, err) + _, err = os.Create(path.Join(kernelDir, "lib/firmware/test-firmware")) + assert.NoError(t, err) + } + } + for _, tt := range kernelBuildTests { + t.Run(tt.kernelName, func(t *testing.T) { + err = Build(tt.kernelVersion, tt.kernelName, kernelDir) + if tt.succeed { + assert.NoError(t, err) + assert.FileExists(t, path.Join(srvDir, "kernel", tt.kernelName, "vmlinuz")) + assert.FileExists(t, path.Join(srvDir, "kernel", tt.kernelName, "kmods.img.gz")) + assert.FileExists(t, path.Join(srvDir, "kernel", tt.kernelName, "kmods.img")) + files, err := util.CpioFiles(path.Join(srvDir, "kernel", tt.kernelName, "kmods.img")) + assert.NoError(t, err) + assert.Equal(t, files, []string{"lib/firmware/test-firmware", "lib/modules/1.2.3.4/test-module"}) + } else { + assert.Error(t, err) + } + }) + } +} diff --git a/internal/pkg/overlay/overlay_test.go b/internal/pkg/overlay/overlay_test.go index 11e76295..194ea49e 100644 --- a/internal/pkg/overlay/overlay_test.go +++ b/internal/pkg/overlay/overlay_test.go @@ -1,15 +1,17 @@ package overlay import ( - warewulfconf "github.com/hpcng/warewulf/internal/pkg/config" - "github.com/hpcng/warewulf/internal/pkg/node" - "github.com/sassoftware/go-rpmutils/cpio" - "github.com/stretchr/testify/assert" "io" "os" "path" "sort" "testing" + + warewulfconf "github.com/hpcng/warewulf/internal/pkg/config" + "github.com/hpcng/warewulf/internal/pkg/node" + "github.com/stretchr/testify/assert" + + "github.com/hpcng/warewulf/internal/pkg/util" ) var buildOverlayTests = []struct { @@ -161,9 +163,9 @@ func Test_BuildOverlay(t *testing.T) { if tt.image != "" { image := path.Join(provisionDir, "overlays", tt.image) assert.FileExists(t, image) - sort.Strings(tt.contents) - files := cpioFiles(t, image) + files, err := util.CpioFiles(image) + assert.NoError(t, err) sort.Strings(files) assert.Equal(t, tt.contents, files) } else { @@ -401,20 +403,3 @@ func dirIsEmpty(t *testing.T, name string) bool { t.Log(dirnames) return false } - -func cpioFiles(t *testing.T, name string) (files []string) { - f, openErr := os.Open(name) - if openErr != nil { - return - } - defer f.Close() - - reader := cpio.NewReader(f) - for { - header, err := reader.Next() - if err != nil { - return - } - files = append(files, header.Filename()) - } -} diff --git a/internal/pkg/util/cpio.go b/internal/pkg/util/cpio.go new file mode 100644 index 00000000..f8709c3d --- /dev/null +++ b/internal/pkg/util/cpio.go @@ -0,0 +1,31 @@ +package util + +import ( + "io" + "os" + + "github.com/sassoftware/go-rpmutils/cpio" +) + +/* +Opens cpio archive and returns the file list +*/ +func CpioFiles(name string) (files []string, err error) { + f, err := os.Open(name) + if err != nil { + return files, err + } + defer f.Close() + + reader := cpio.NewReader(f) + for { + header, err := reader.Next() + if err == io.EOF { + return files, nil + } + if err != nil { + return files, err + } + files = append(files, header.Filename()) + } +} diff --git a/internal/pkg/util/util.go b/internal/pkg/util/util.go index 2381e77b..a213e384 100644 --- a/internal/pkg/util/util.go +++ b/internal/pkg/util/util.go @@ -421,7 +421,7 @@ func SliceAddUniqueElement(array []string, add string) []string { } /* -Appends a string slice to another slice. Guarantess that the elements are uniq. +Appends a string slice to another slice. Guarantees that the elements are uniq. */ func SliceAppendUniq(array []string, add []string) []string { ret := array