Support dracut booting with GRUB

Signed-off-by: Jonathon Anderson <janderson@ciq.com>
This commit is contained in:
Jonathon Anderson
2024-06-06 03:08:43 -04:00
parent 9500487ad3
commit 05b951d78d
4 changed files with 70 additions and 6 deletions

View File

@@ -41,7 +41,9 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
- Add `stage=initramfs` to warewulfd provision to serve initramfs from container image. #1115
- Add `warewulf-dracut` package to support building Warewulf-compatible initramfs images with dracut. #1115
- Add iPXE template `dracut.ipxe` to boot a dracut initramfs. #1115
- Add `.NetDevs` variable to iPXE templates, similar to overlay templates. #1115
- Add dracut menuentry to `grub.cfg.ww` to boot a dracut initramfs. #1115
- Add `.NetDevs` variable to iPXE and GRUB templates, similar to overlay templates. #1115
- Add `.Tags` variable to iPXE and GRUB templates, similar to overlay templates. #1115
### Changed

View File

@@ -6,13 +6,16 @@ echo "Warewulf Controller: {{.Ipaddr}}"
echo
sleep 1
smbios --type1 --get-string 8 --set assetkey
uri="(http,{{.Ipaddr}}:{{.Port}})/provision/${net_default_mac}?assetkey=${assetkey}"
kernel="${uri}&stage=kernel"
container="${uri}&stage=container&compress=gz"
system="${uri}&stage=system&compress=gz"
runtime="${uri}&stage=runtime&compress=gz"
set default=ww4
set default={{ or .Tags.GrubMenuEntry "ww4" }}
set timeout=5
menuentry "Network boot node: {{.Id}}" --id ww4 {
{{if .KernelOverride }}
echo "Kernel: {{.KernelOverride}}"
@@ -34,17 +37,54 @@ menuentry "Network boot node: {{.Id}}" --id ww4 {
reboot
fi
}
menuentry "Network boot node with dracut: {{.Id}}" --id dracut {
initramfs="${uri}&stage=initramfs"
uri="http://{{.Ipaddr}}:{{.Port}}/provision/${net_default_mac}?assetkey=${assetkey}"
container="${uri}&stage=container&compress=gz"
system="${uri}&stage=system&compress=gz"
runtime="${uri}&stage=runtime&compress=gz"
{{if .KernelOverride }}
echo "Kernel: {{.KernelOverride}}"
{{else}}
echo "Kernel: {{.ContainerName}} (container default)"
{{end}}
echo "KernelArgs: {{.KernelArgs}}"
net_args="rd.neednet=1 {{range $devname, $netdev := .NetDevs}}{{if and $netdev.Hwaddr $netdev.Device}} ifname={{$netdev.Device}}:{{$netdev.Hwaddr}} {{end}}{{end}}"
wwinit_args="root=wwinit wwinit.container=${container} wwinit.system=${system} wwinit.runtime=${runtime} init=/init"
linux $kernel wwid=${net_default_mac} {{.KernelArgs}} $net_args $wwinit_args
if [ x$? = x0 ] ; then
echo "Loading Container: {{.ContainerName}}"
initrd $initramfs
boot
else
echo "MESSAGE: This node seems to be unconfigured. Please have your system administrator add a"
echo " configuration for this node with HW address: ${net_default_mac}"
echo ""
echo "Rebooting in 1 minute..."
sleep 60
reboot
fi
}
menuentry "Chainload specific configfile" {
conf="(http,{{.Ipaddr}}:{{.Port}})/efiboot/grub.cfg"
configfile $conf
}
menuentry "UEFI Firmware Settings" --id "uefi-firmware" {
fwsetup
}
menuentry "System restart" {
echo "System rebooting..."
reboot
}
menuentry "System shutdown" {
echo "System shutting down..."
halt

View File

@@ -34,6 +34,7 @@ type templateVars struct {
Port string
KernelArgs string
KernelOverride string
Tags map[string]string
NetDevs map[string]*node.NetDevs
}
@@ -108,7 +109,8 @@ func ProvisionSend(w http.ResponseWriter, req *http.Request) {
ContainerName: node.ContainerName.Get(),
KernelArgs: node.Kernel.Args.Get(),
KernelOverride: node.Kernel.Override.Get(),
NetDevs: tstruct.NetDevs}
NetDevs: tstruct.NetDevs,
Tags: tstruct.Tags}
} else if rinfo.stage == "kernel" {
if node.Kernel.Override.Defined() {
stage_file = kernel.KernelImage(node.Kernel.Override.Get())
@@ -180,6 +182,7 @@ func ProvisionSend(w http.ResponseWriter, req *http.Request) {
}
case "grub.cfg":
stage_file = path.Join(conf.Paths.Sysconfdir, "warewulf/grub/grub.cfg.ww")
tstruct := overlay.InitStruct(&node)
tmpl_data = templateVars{
Id: node.Id.Get(),
Cluster: node.ClusterName.Get(),
@@ -190,7 +193,9 @@ func ProvisionSend(w http.ResponseWriter, req *http.Request) {
Hwaddr: rinfo.hwaddr,
ContainerName: node.ContainerName.Get(),
KernelArgs: node.Kernel.Args.Get(),
KernelOverride: node.Kernel.Override.Get()}
KernelOverride: node.Kernel.Override.Get(),
NetDevs: tstruct.NetDevs,
Tags: tstruct.Tags}
if stage_file == "" {
wwlog.ErrorExc(fmt.Errorf("could't find grub.cfg template"), containerName)
w.WriteHeader(http.StatusNotFound)

View File

@@ -74,10 +74,27 @@ booting the node image directly.
The iPXE template may be set at the node or profile level.
Alternatively, to direct GRUB to fetch the node's initramfs image and boot with
dracut semantics, set a ``GrubMenuEntry`` tag for the node.
.. note::
Warewulf configures GRUB with a template located at
``/etc/warewulf/grub/grub.cfg.ww``. Inspect the template to learn more about
the dracut booting process.
.. code-block:: shell
wwctl node set wwnode1 --tagadd GrubMenuEntry=dracut
.. note::
The ``GrubMenuEntry`` variable may be set at the node or profile level.
During boot, ``warewulfd`` will detect and dynamically serve an
initramfs from a node's container image in much the same way that it
can serve a kernel from a container image. This image is loaded by
iPXE, and iPXE directs dracut to fetch the node's container image
iPXE (or GRUB) which directs dracut to fetch the node's container image
during boot.
The wwinit module provisions to tmpfs. By default, tmpfs is permitted
@@ -88,7 +105,7 @@ more details.)
.. warning::
Kernel overrides are not currently supported during dracut initramfs boot.
Kernel overrides are not currently fully supported during dracut initramfs boot.
Booting with GRUB
=================