diff --git a/containers/Docker/centos-8 b/containers/Docker/centos-8 new file mode 100644 index 00000000..da6fc27f --- /dev/null +++ b/containers/Docker/centos-8 @@ -0,0 +1,52 @@ +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 < \"%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() diff --git a/internal/pkg/container/kernel.go b/internal/pkg/container/kernel.go new file mode 100644 index 00000000..9d74ee21 --- /dev/null +++ b/internal/pkg/container/kernel.go @@ -0,0 +1,58 @@ +package container + +import ( + "path" + "path/filepath" + "sort" + + "github.com/hpcng/warewulf/internal/pkg/util" + "github.com/hpcng/warewulf/internal/pkg/wwlog" +) + +var ( + 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 "" + } + + 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 "" + } + + 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) { + return kernelPath + } + } + } + + return "" +} + +func KernelVersion(container string) string { + wwlog.Printf(wwlog.DEBUG, "Finding kernel version inside container: %s\n", container) + kernel := KernelFind(container) + if kernel == "" { + return "" + } + + return path.Base(path.Dir(kernel)) +} diff --git a/internal/pkg/kernel/kernel.go b/internal/pkg/kernel/kernel.go index 552807cd..33237229 100644 --- a/internal/pkg/kernel/kernel.go +++ b/internal/pkg/kernel/kernel.go @@ -199,7 +199,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() diff --git a/internal/pkg/node/constructors.go b/internal/pkg/node/constructors.go index 927b479c..8b082b19 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 fb2e5e0f..b12c956a 100644 --- a/internal/pkg/overlay/overlay.go +++ b/internal/pkg/overlay/overlay.go @@ -169,7 +169,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 22958f5f..f386852d 100644 --- a/internal/pkg/warewulfd/kernel.go +++ b/internal/pkg/warewulfd/kernel.go @@ -2,8 +2,10 @@ package warewulfd import ( "net/http" + "path" "strings" + "github.com/hpcng/warewulf/internal/pkg/container" "github.com/hpcng/warewulf/internal/pkg/kernel" ) @@ -28,18 +30,25 @@ func KernelSend(w http.ResponseWriter, req *http.Request) { return } - if node.KernelVersion.Defined() { - fileName := kernel.KernelImage(node.KernelVersion.Get()) + var fileName string + if node.KernelOverride.Defined() { + fileName = kernel.KernelImage(node.KernelOverride.Get()) - updateStatus(node.Id.Get(), "KERNEL", node.KernelVersion.Get(), 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()) } }