Merge pull request #1742 from anderbubble/wwinit-logging

Improved logging during iPXE, GRUB, and wwinit
This commit is contained in:
Christian Goll
2025-02-20 10:32:11 +01:00
committed by GitHub
18 changed files with 525 additions and 309 deletions

View File

@@ -17,6 +17,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
- Added `WW_HISTFILE` to control shell history location during `wwctl image shell`. #1732
- Added target help in Makefile. #1740
- Added fstab mounts for `/home` and `/opt` to initial default profile. #1744
- Add support for an `IPXEMenuEntry` tag to select the boot method during iPXE.
### Changed
@@ -30,6 +31,13 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
- Update syncuser documentation. #1736
- Update PS1 during `wwctl image shell` to include working directory by default,
and to include `PS1` from the environment if present. #1245
- DHCP template generates as much of the subnet and range definition as possible. #1469
- Updated overlay flags to `wwctl <node|profile> <add|set> [--runtime-overlays|--system-overlays]`. #1495
- Added logging and updated output during iPXE and GRUB. #1156
- Defined a menu for iPXE. #1156
- Added logging to wwinit scripts. #1156
- Renamed /warewulf/wwinit to /warewulf/prescripts. #1156
- Display auto-detected kernel version during iPXE and GRUB. #1742
### Fixed
@@ -49,6 +57,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
- Remove syncuser warning messages in `wwctl` that assume its use. #1321
- Remove syncuser from the list of default runtime overlays. #1322
- Removed check for "discoverable" profiles during `wwctl upgrade nodes`.
- Removed `dracut.ipxe` template. (Use `default.ipxe` and set tag `IPXEMenuEntry=dracut`.)
## v4.6.0rc2, 2025-02-07

View File

@@ -216,7 +216,7 @@ install: build docs ## Install Warewulf from source
(cd overlays && find * -path '*/internal' -prune -o -type d -exec mkdir -pv $(DESTDIR)$(DATADIR)/warewulf/overlays/{} \;)
(cd overlays && find * -path '*/internal' -prune -o -type l -exec cp -av {} $(DESTDIR)$(DATADIR)/warewulf/overlays/{} \;)
chmod 0755 $(DESTDIR)$(DATADIR)/warewulf/overlays/wwinit/rootfs/init
chmod 0755 $(DESTDIR)$(DATADIR)/warewulf/overlays/wwinit/rootfs/$(WWCLIENTDIR)/wwinit
chmod 0755 $(DESTDIR)$(DATADIR)/warewulf/overlays/wwinit/rootfs/$(WWCLIENTDIR)/wwprescripts
chmod 0600 $(DESTDIR)$(DATADIR)/warewulf/overlays/wwinit/rootfs/$(WWCLIENTDIR)/config.ww
chmod 0600 $(DESTDIR)$(DATADIR)/warewulf/overlays/ssh.host_keys/rootfs/etc/ssh/ssh*
chmod 0644 $(DESTDIR)$(DATADIR)/warewulf/overlays/ssh.host_keys/rootfs/etc/ssh/ssh*.pub.ww

View File

@@ -1,77 +1,170 @@
{{ if .ImageName }}
echo "================================================================================"
echo "Warewulf v4 now http booting grub: {{.Fqdn}} ({{.Hwaddr}})"
echo "================================================================================"
echo
echo "Warewulf Controller: {{.Ipaddr}}"
echo "Warewulf v4 (GRUB)"
echo
sleep 1
echo "Warewulf Server:"
echo "* Ipaddr: {{.Ipaddr}}"
echo "* Port: {{.Port}}"
echo
echo "This node:"
echo "* Fqdn: {{.Fqdn}}"
echo "* Hwaddr: {{.Hwaddr}}"
echo "* ImageName: {{.ImageName}}"
{{- if .KernelVersion }}
echo "* KernelVersion: {{.KernelVersion}}"
{{- else }}
echo "* KernelVersion: (image default)"
{{- end }}
echo "* KernelArgs: {{.KernelArgs}}"
{{- if not .ImageName }}
echo "!!"
echo "!! No image defined for {{.Fqdn}}."
echo "!! Rebooting in 30s...
echo "!!"
sleep 30
reboot
{{- end }}
echo "Reading asset key..."
smbios --type 3 --get-string 8 --set assetkey
uri="(http,{{.Ipaddr}}:{{.Port}})/provision/${net_default_mac}?assetkey=${assetkey}"
kernel="${uri}&stage=kernel"
image="${uri}&stage=image&compress=gz"
system="${uri}&stage=system&compress=gz"
runtime="${uri}&stage=runtime&compress=gz"
set default={{ or .Tags.GrubMenuEntry "ww4" }}
set timeout=5
set default={{ or .Tags.GrubMenuEntry "single-stage" }}
set timeout=2
menuentry "Network boot node: {{.Id}}" --id ww4 {
{{if .KernelVersion }}
echo "Kernel: {{.KernelVersion}}"
{{else}}
echo "Kernel: {{.ImageName}} (image default)"
{{end}}
echo "KernelArgs: {{.KernelArgs}}"
menuentry "Single-stage boot" --id single-stage {
echo "Warewulf Server:"
echo "* Ipaddr: {{.Ipaddr}}"
echo "* Port: {{.Port}}"
echo
echo "This node:"
echo "* Fqdn: {{.Fqdn}}"
echo "* Hwaddr: {{.Hwaddr}}"
echo "* ImageName: {{.ImageName}}"
{{- if .KernelVersion }}
echo "* KernelVersion: {{.KernelVersion}}"
{{- else }}
echo "* KernelVersion: (image default)"
{{- end }}
echo "* KernelArgs: {{.KernelArgs}}"
echo
echo "Downloading kernel image..."
linux $kernel wwid=${net_default_mac} {{.KernelArgs}}
if [ x$? = x0 ] ; then
echo "Loading Image: {{.ImageName}}"
initrd $image $system $runtime
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
if [ $? != 0 ]
then
echo "!!"
echo "!! Unable to load kernel."
echo "!! Rebooting in 15s..."
echo "!!"
fi
echo "Downloading images..."
image="${uri}&stage=image&compress=gz"
system="${uri}&stage=system&compress=gz"
runtime="${uri}&stage=runtime&compress=gz"
initrd $image $system $runtime
if [ $? != 0 ]
then
echo "!!"
echo "!! Unable to load images."
echo "!! Rebooting in 15s..."
echo "!!"
fi
echo "Booting..."
boot
}
menuentry "Network boot node with dracut: {{.Id}}" --id dracut {
menuentry "Single-stage boot (no compression)" --id single-stage-nocompress {
echo "Warewulf Server:"
echo "* Ipaddr: {{.Ipaddr}}"
echo "* Port: {{.Port}}"
echo
echo "This node:"
echo "* Fqdn: {{.Fqdn}}"
echo "* Hwaddr: {{.Hwaddr}}"
echo "* ImageName: {{.ImageName}}"
{{- if .KernelVersion }}
echo "* KernelVersion: {{.KernelVersion}}"
{{- else }}
echo "* KernelVersion: (image default)"
{{- end }}
echo "* KernelArgs: {{.KernelArgs}}"
echo
echo "Downloading kernel image..."
linux $kernel wwid=${net_default_mac} {{.KernelArgs}}
if [ $? != 0 ]
then
echo "!!"
echo "!! Unable to load kernel."
echo "!! Rebooting in 15s..."
echo "!!"
fi
echo "Downloading images..."
image="${uri}&stage=image"
system="${uri}&stage=system"
runtime="${uri}&stage=runtime"
initrd $image $system $runtime
if [ $? != 0 ]
then
echo "!!"
echo "!! Unable to load images."
echo "!! Rebooting in 15s..."
echo "!!"
fi
echo "Booting..."
boot
}
menuentry "Two stage boot with dracut" --id dracut {
echo "Warewulf Server:"
echo "* Ipaddr: {{.Ipaddr}}"
echo "* Port: {{.Port}}"
echo
echo "This node:"
echo "* Fqdn: {{.Fqdn}}"
echo "* Hwaddr: {{.Hwaddr}}"
echo "* ImageName: {{.ImageName}}"
{{- if .KernelVersion }}
echo "* KernelVersion: {{.KernelVersion}}"
{{- else }}
echo "* KernelVersion: (image default)"
{{- end }}
echo "* KernelArgs: {{.KernelArgs}}"
initramfs="${uri}&stage=initramfs"
wwinit_uri="http://{{.Ipaddr}}:{{.Port}}/provision/${net_default_mac}"
{{if .KernelVersion }}
echo "Kernel: {{.KernelVersion}}"
{{else}}
echo "Kernel: {{.ImageName}} (image 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.uri=${wwinit_uri} init=/init"
echo
echo "Downloading kernel image..."
linux $kernel wwid=${net_default_mac} {{.KernelArgs}} $net_args $wwinit_args
if [ x$? = x0 ] ; then
echo "Loading Image: {{.ImageName}}"
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
if [ $? != 0 ]
then
echo "!!"
echo "!! Unable to load kernel."
echo "!! Rebooting in 15s..."
echo "!!"
fi
}
menuentry "Chainload specific configfile" {
conf="(http,{{.Ipaddr}}:{{.Port}})/efiboot/grub.cfg?assetkey=${assetkey}"
configfile $conf
echo "Downloading initramfs..."
initrd $initramfs
if [ $? != 0 ]
then
echo "!!"
echo "!! Unable to load initramfs."
echo "!! Rebooting in 15s..."
echo "!!"
fi
echo "Booting..."
boot
}
menuentry "UEFI Firmware Settings" --id "uefi-firmware" {
@@ -87,12 +180,3 @@ menuentry "System shutdown" {
echo "System shutting down..."
halt
}
{{ else }}
echo "================================================================================"
echo " Warewulf v4:"
echo " No node image defined for this node ({{.Fqdn}})."
echo " Rebooting in 30s."
echo "================================================================================"
sleep 30
reboot
{{ end }}

View File

@@ -1,94 +1,129 @@
#!ipxe
{{ if .ImageName }}
echo
echo ================================================================================
echo Warewulf v4 now booting: {{.Fqdn}} ({{.Hwaddr}})
echo
echo Image: {{.ImageName}}
{{if .KernelVersion }}
echo Kernel: {{.KernelVersion}}
{{else}}
echo Kernel: {{.ImageName}} (image default)
{{end}}
echo KernelArgs: {{.KernelArgs}}
echo
echo Warewulf v4 (iPXE)
echo
set next start
goto metadata
set uri_base http://{{.Ipaddr}}:{{.Port}}/provision/{{.Hwaddr}}?assetkey=${asset}&uuid=${uuid}
echo Warewulf Controller: {{.Ipaddr}}
echo Downloading Kernel Image:
kernel --name kernel ${uri_base}&stage=kernel || goto reboot
# imgextract causes RAM space problems on non-EFI systems (because of the 3GB barrier
# in 32-Bit mode).
# -> Use the old initrd method with a compressed image to save as much RAM as possible
# in this early boot stage.
# See <https://github.com/warewulf/warewulf/issues/222> for more details.
iseq ${platform} efi && goto efi || goto noefi
:efi
# try extracting compressed images first
# NOTE: system overlay tends to be the smallest, so failure here is the cheapest
echo Downloading Image:
imgextract --name image ${uri_base}&stage=image&compress=gz || goto nocompress
echo Downloading System Overlay:
imgextract --name system ${uri_base}&stage=system&compress=gz || goto reboot
echo Downloading Runtime Overlay:
imgextract --name runtime ${uri_base}&stage=runtime&compress=gz && set runtime_initrd initrd=runtime || echo Failed downloading runtime overlay.
goto imoktogo
:nocompress
echo
echo Image extract not supported in this iPXE, using standard initrd mode
echo Downloading Image:
initrd --name image ${uri_base}&stage=image || goto reboot
echo Downloading System Overlay:
initrd --name system ${uri_base}&stage=system || goto reboot
echo Downloading Runtime Overlay:
initrd --name runtime ${uri_base}&stage=runtime && set runtime_initrd initrd=runtime || echo Failed downloading runtime overlay.
goto imoktogo
:noefi
echo
echo Use legacy initrd mode with compressed images
echo Downloading Image:
initrd --name image ${uri_base}&stage=image&compress=gz || goto reboot
echo Downloading System Overlay:
initrd --name system ${uri_base}&stage=system&compress=gz || goto reboot
echo Downloading Runtime Overlay:
initrd --name runtime ${uri_base}&stage=runtime&compress=gz && set runtime_initrd initrd=runtime || echo Failed downloading runtime overlay.
:imoktogo
echo boot kernel initrd=image initrd=system ${runtime_initrd} wwid={{.Hwaddr}} {{.KernelArgs}}
boot kernel initrd=image initrd=system ${runtime_initrd} wwid={{.Hwaddr}} {{.KernelArgs}} || goto reboot
:reboot
echo
echo There was an error, rebooting in 15s...
echo
sleep 15
reboot
{{ else }}
echo ================================================================================
echo Warewulf v4:
echo No image defined for this node ({{.Fqdn}}).
echo Rebooting in 30s.
echo ================================================================================
:start
{{- if not .ImageName }}
echo !!
echo !! No image defined for {{.Fqdn}}.
echo !! Rebooting in 30s...
echo !!
sleep 30
reboot
{{ end }}
{{- end }}
set baseuri http://{{.Ipaddr}}:{{.Port}}/provision/{{.Hwaddr}}
set uri ${baseuri}?assetkey=${asset}&uuid=${uuid}
echo Downloading kernel image...
kernel --name kernel ${uri}&stage=kernel || goto reboot
{{- if .Tags.IPXEMenuEntry }}
set method {{ .Tags.IPXEMenuEntry }}
{{- else }}
# https://github.com/warewulf/warewulf/issues/222
iseq ${platform} efi && set method imgextract || set method initrd
{{- end }}
:menu
menu Warewulf v4 image provisioning method
item imgextract Single-stage with imgextract
item initrd Single-stage with initrd
item initrd_nocompress Single stage with initrd (no compression)
item dracut Two stage with dracut
item shell iPXE shell
choose --default ${method} --timeout 2000 method && goto ${method} || goto menu
:imgextract
set next imgextract_continue
goto metadata
:imgextract_continue
echo
echo Downloading compressed image with imgextract...
imgextract --name image ${uri}&stage=image&compress=gz || goto error_use_initrd
echo Downloading compressed system overlay image with imgextract...
imgextract --name system ${uri}&stage=system&compress=gz || goto error_reboot
echo Downloading compressed runtime overlay image with imgextract...
imgextract --name runtime ${uri}&stage=runtime&compress=gz && set runtime_initrd initrd=runtime || echo Unable to download runtime overlay. (ignored)
goto boot_single_stage
:error_use_initrd
echo Encountered an error. Now using initrd.
goto initrd_continue
:initrd
set next initrd_continue
goto metadata
:initrd_continue
echo
echo Downloading compressed image with initrd...
initrd --name image ${uri}&stage=image&compress=gz || goto error_reboot
echo Downloading compressed system overlay with initrd...
initrd --name system ${uri}&stage=system&compress=gz || goto error_reboot
echo Downloading compressed runtime overlay with initrd...
initrd --name runtime ${uri}&stage=runtime&compress=gz && set runtime_initrd initrd=runtime || echo Unable to download runtime overlay. (ignored)
goto boot_single_stage
:initrd_nocompress
set next initrd_nocompress_continue
goto metadata
:initrd_nocompress_continue
echo
echo Downloading uncompressed image with initrd...
initrd --name image ${uri}&stage=image || goto error_reboot
echo Downloading uncompressed system overlay with initrd...
initrd --name system ${uri}&stage=system || goto error_reboot
echo Downloading uncompressed runtime overlay with initrd...
initrd --name runtime ${uri}&stage=runtime && set runtime_initrd initrd=runtime || echo Unable to download runtime overlay. (ignored)
goto boot_single_stage
:dracut
set next dracut_continue
goto metadata
:dracut_continue
echo
echo Downloading dracut initramfs...
initrd --name initramfs ${uri}&stage=initramfs || goto error_reboot
set dracut_net rd.neednet=1 {{range $devname, $netdev := .NetDevs}}{{if and $netdev.Hwaddr $netdev.Device}} ifname={{$netdev.Device}}:{{$netdev.Hwaddr}} ip={{$netdev.Device}}:dhcp {{end}}{{end}}
set dracut_wwinit root=wwinit wwinit.uri=${baseuri} init=/init
goto boot_two_stage_dracut
:boot_single_stage
echo Booting (single stage)...
boot kernel initrd=image initrd=system ${runtime_initrd} wwid={{.Hwaddr}} {{.KernelArgs}} || goto error_reboot
:boot_two_stage_dracut
echo Booting dracut (first stage)...
boot kernel initrd=initramfs ${dracut_net} ${dracut_wwinit} wwid={{.Hwaddr}} {{.KernelArgs}} || error_reboot
:error_reboot
echo !!
echo !! Encountered an error.
echo !! rebooting in 15s...
echo !!
sleep 15
reboot
:shell
shell
goto menu
:metadata
echo Warewulf Server:
echo * Ipaddr: {{.Ipaddr}}
echo * Port: {{.Port}}
echo
echo This node:
echo * Fqdn: {{.Fqdn}}
echo * Hwaddr: {{.Hwaddr}}
echo * ImageName: {{.ImageName}}
{{- if .KernelVersion }}
echo * KernelVersion: {{.KernelVersion}}
{{- else }}
echo * KernelVersion: (image default)
{{- end }}
echo * KernelArgs: {{.KernelArgs}}
goto ${next}

View File

@@ -1,47 +0,0 @@
#!ipxe
{{ if .ImageName }}
echo
echo ================================================================================
echo Warewulf v4 now booting via dracut: {{.Fqdn}} ({{.Hwaddr}})
echo
echo Image: {{.ImageName}}
{{if .KernelVersion }}
echo Kernel: {{.KernelVersion}}
{{else}}
echo Kernel: {{.ImageName}} (image default)
{{end}}
echo KernelArgs: {{.KernelArgs}}
echo
set baseuri http://{{.Ipaddr}}:{{.Port}}/provision/{{.Hwaddr}}
set uri ${baseuri}?assetkey=${asset}&uuid=${uuid}
echo Warewulf Controller: {{.Ipaddr}}
echo Downloading Kernel Image:
kernel --name kernel ${uri}&stage=kernel || goto reboot
echo Downloading initramfs
initrd --name initramfs ${uri}&stage=initramfs || goto reboot
set dracut_net rd.neednet=1 {{range $devname, $netdev := .NetDevs}}{{if and $netdev.Hwaddr $netdev.Device}} ifname={{$netdev.Device}}:{{$netdev.Hwaddr}} ip={{$netdev.Device}}:dhcp {{end}}{{end}}
set dracut_wwinit root=wwinit wwinit.uri=${baseuri} init=/init
echo Booting initramfs
boot kernel initrd=initramfs ${dracut_net} ${dracut_wwinit} wwid={{.Hwaddr}} {{.KernelArgs}}
:reboot
echo
echo There was an error, rebooting in 15s...
echo
sleep 15
reboot
{{ else }}
echo ================================================================================
echo Warewulf v4:
echo No image defined for this node ({{.Fqdn}}).
echo Rebooting in 30s.
echo ================================================================================
sleep 30
reboot
{{ end }}

48
init.bak Executable file
View File

@@ -0,0 +1,48 @@
#!/bin/sh
echo "Warewulf pre-init (/init)"
echo
echo "Mounting kernel file systems..."
mountpoint -q /proc || (mkdir -p /proc && mount -t proc proc /proc && echo "Mounted /proc")
mountpoint -q /dev || (mkdir -p /dev && mount -t devtmpfs devtmpfs /dev && echo "Mounted /dev")
mountpoint -q /sys || (mkdir -p /sys && mount -t sysfs sysfs /sys && echo "Mounted /sys")
echo
echo "Loading /warewulf/config..."
if [ -f "/warewulf/config" ]; then
. /warewulf/config
else
echo "ERROR: Warewulf configuration file not found."
echo "Rebooting in 1 minute..."
sleep 60
echo b > /proc/sysrq-trigger || /sbin/reboot -f
fi
echo
echo "Configuring root file system..."
WWPRESCRIPTS=/warewulf/wwprescripts
chmod +rx "${WWPRESCRIPTS}"
WWROOT="${WWROOT:-initramfs}"
if [ "${WWROOT}" = "initramfs" ]; then
echo "WWROOT=${WWROOT}: using initial rootfs and invoking ${WWPRESCRIPTS}..."
exec "${WWPRESCRIPTS}"
elif [ "${WWROOT}" = "ramfs" -o "${WWROOT}" = "tmpfs" ]; then
echo "WWROOT=${WWROOT}: setting up new ${WWROOT} rootfs (/newroot)..."
mkdir /newroot
mount wwroot /newroot -t ${WWROOT} -o mpol=interleave # mpol ignored for ramfs
tar -cf - --exclude ./proc --exclude ./sys --exclude ./dev --exclude --exclude ./newroot . | tar -xf - -C /newroot
mkdir /newroot/proc /newroot/dev /newroot/sys 2>/dev/null
echo "Switching to new rootfs (/newroot) and invoking ${WWPRESCRIPTS}..."
exec /sbin/switch_root /newroot "${WWPRESCRIPTS}"
else
echo "ERROR: Unrecognized rootfs type requested: ${WWROOT}"
echo "Rebooting in 1 minute..."
sleep 60
echo b > /proc/sysrq-trigger || /sbin/reboot -f
fi
echo
echo "ERROR: wwinit encountered a problem."
echo "Rebooting in 1 minute..."
sleep 60
echo b > /proc/sysrq-trigger || /sbin/reboot -f

View File

@@ -165,6 +165,7 @@ type Node struct {
func (legacy *Node) Upgrade(addDefaults bool, replaceOverlays bool) (upgraded *node.Node) {
upgraded = new(node.Node)
upgraded.Tags = make(map[string]string)
upgraded.Resources = make(map[string]node.Resource)
upgraded.Disks = make(map[string]*node.Disk)
upgraded.FileSystems = make(map[string]*node.FileSystem)
upgraded.Ipmi = new(node.IpmiConf)
@@ -226,7 +227,31 @@ func (legacy *Node) Upgrade(addDefaults bool, replaceOverlays bool) (upgraded *n
if upgraded.Ipmi.Write == "" && legacy.IpmiWrite != "" {
warnError(upgraded.Ipmi.Write.Set(legacy.IpmiWrite))
}
upgraded.Ipxe = legacy.Ipxe
if legacy.Keys != nil {
for key, value := range legacy.Keys {
upgraded.Tags[key] = value
}
}
if legacy.Tags != nil {
for key, value := range legacy.Tags {
upgraded.Tags[key] = value
}
}
for _, tag := range legacy.TagsDel {
delete(upgraded.Tags, tag)
}
if legacy.Ipxe == "dracut" {
if _, ok := upgraded.Tags["IPXEMenuEntry"]; !ok {
wwlog.Info("Replacing ipxe template 'dracut' with 'default' and setting tag 'IPXEMenuEntry=dracut'")
upgraded.Ipxe = "default"
upgraded.Tags["IPXEMenuEntry"] = "dracut"
} else {
wwlog.Warn("Found ipxe template 'dracut' but tag 'IPXEMenuEntry' is already set; ignoring")
upgraded.Ipxe = legacy.Ipxe
}
} else {
upgraded.Ipxe = legacy.Ipxe
}
if legacy.Kernel != nil {
upgraded.Kernel = legacy.Kernel.Upgrade(upgraded.ImageName)
} else {
@@ -237,11 +262,6 @@ func (legacy *Node) Upgrade(addDefaults bool, replaceOverlays bool) (upgraded *n
}
upgraded.Kernel = inlineKernel.Upgrade(upgraded.ImageName)
}
if legacy.Keys != nil {
for key, value := range legacy.Keys {
upgraded.Tags[key] = value
}
}
if legacy.NetDevs != nil {
for name, netDev := range legacy.NetDevs {
upgraded.NetDevs[name] = netDev.Upgrade(false)
@@ -313,14 +333,11 @@ func (legacy *Node) Upgrade(addDefaults bool, replaceOverlays bool) (upgraded *n
genericSplitOverlays)
}
}
if legacy.Tags != nil {
for key, value := range legacy.Tags {
upgraded.Tags[key] = value
if legacy.Resources != nil {
for key, value := range legacy.Resources {
upgraded.Resources[key] = value
}
}
for _, tag := range legacy.TagsDel {
delete(upgraded.Tags, tag)
}
return
}
@@ -427,7 +444,31 @@ func (legacy *Profile) Upgrade(addDefaults bool, replaceOverlays bool) (upgraded
if upgraded.Ipmi.Write == "" && legacy.IpmiWrite != "" {
warnError(upgraded.Ipmi.Write.Set(legacy.IpmiWrite))
}
upgraded.Ipxe = legacy.Ipxe
if legacy.Keys != nil {
for key, value := range legacy.Keys {
upgraded.Tags[key] = value
}
}
if legacy.Tags != nil {
for key, value := range legacy.Tags {
upgraded.Tags[key] = value
}
}
for _, tag := range legacy.TagsDel {
delete(upgraded.Tags, tag)
}
if legacy.Ipxe == "dracut" {
if _, ok := upgraded.Tags["IPXEMenuEntry"]; !ok {
wwlog.Info("Replacing ipxe template 'dracut' with 'default' and setting tag 'IPXEMenuEntry=dracut'")
upgraded.Ipxe = "default"
upgraded.Tags["IPXEMenuEntry"] = "dracut"
} else {
wwlog.Warn("Found ipxe template 'dracut' but tag 'IPXEMenuEntry' is already set; ignoring")
upgraded.Ipxe = legacy.Ipxe
}
} else {
upgraded.Ipxe = legacy.Ipxe
}
if legacy.Kernel != nil {
upgraded.Kernel = legacy.Kernel.Upgrade(upgraded.ImageName)
} else {
@@ -438,11 +479,6 @@ func (legacy *Profile) Upgrade(addDefaults bool, replaceOverlays bool) (upgraded
}
upgraded.Kernel = inlineKernel.Upgrade(upgraded.ImageName)
}
if legacy.Keys != nil {
for key, value := range legacy.Keys {
upgraded.Tags[key] = value
}
}
if legacy.NetDevs != nil {
for name, netDev := range legacy.NetDevs {
upgraded.NetDevs[name] = netDev.Upgrade(addDefaults)
@@ -503,14 +539,6 @@ func (legacy *Profile) Upgrade(addDefaults bool, replaceOverlays bool) (upgraded
genericSplitOverlays)
}
}
if legacy.Tags != nil {
for key, value := range legacy.Tags {
upgraded.Tags[key] = value
}
}
for _, tag := range legacy.TagsDel {
delete(upgraded.Tags, tag)
}
if legacy.Resources != nil {
for key, value := range legacy.Resources {
upgraded.Resources[key] = value

View File

@@ -254,7 +254,7 @@ nodes:
`,
},
{
name: "keys and tags",
name: "keys, tags, and resources",
addDefaults: false,
replaceOverlays: false,
legacyYaml: `
@@ -269,6 +269,13 @@ nodeprofiles:
key4: valD
tagsdel:
- key4
resources:
res1:
- val1a
- val1b
res2:
- val2a
- val2b
network devices:
default:
tags:
@@ -295,6 +302,13 @@ nodes:
key4: valD
tagsdel:
- key4
resources:
resn1:
- valn1a
- valn1b
resn2:
- valn2a
- valn2b
network devices:
default:
tags:
@@ -327,6 +341,13 @@ nodeprofiles:
key1: val1
key2: valB
key3: valC
resources:
res1:
- val1a
- val1b
res2:
- val2a
- val2b
nodes:
n1:
ipmi:
@@ -342,6 +363,13 @@ nodes:
key1: val1
key2: valB
key3: valC
resources:
resn1:
- valn1a
- valn1b
resn2:
- valn2a
- valn2b
`,
},
{
@@ -852,6 +880,29 @@ nfs:
mount: true
- path: /var
mount: false
`,
},
{
name: "Replace dracut template with IPXEMenuEntry",
legacyYaml: `
nodeprofiles:
default:
ipxe template: dracut
nodes:
n1:
ipxe template: dracut
`,
upgradedYaml: `
nodeprofiles:
default:
ipxe template: default
tags:
IPXEMenuEntry: dracut
nodes:
n1:
ipxe template: default
tags:
IPXEMenuEntry: dracut
`,
},
}

View File

@@ -104,6 +104,11 @@ func ProvisionSend(w http.ResponseWriter, req *http.Request) {
kernelArgs = strings.Join(remoteNode.Kernel.Args, " ")
kernelVersion = remoteNode.Kernel.Version
}
if kernelVersion == "" {
if kernel_ := kernel.FromNode(&remoteNode); kernel_ != nil {
kernelVersion = kernel_.Version()
}
}
tmpl_data = &templateVars{
Id: remoteNode.Id(),
Cluster: remoteNode.ClusterName,
@@ -186,6 +191,11 @@ func ProvisionSend(w http.ResponseWriter, req *http.Request) {
kernelArgs = strings.Join(remoteNode.Kernel.Args, " ")
kernelVersion = remoteNode.Kernel.Version
}
if kernelVersion == "" {
if kernel_ := kernel.FromNode(&remoteNode); kernel_ != nil {
kernelVersion = kernel_.Version()
}
}
tmpl_data = &templateVars{
Id: remoteNode.Id(),
Cluster: remoteNode.ClusterName,

View File

@@ -1,14 +1,13 @@
#!/bin/sh
#
# This is one of those types of files that you shouldn't edit unless you really
# know what you are doing and even then you should make a backup.
#
# Edit at your own risk! DANGER DANGER.
echo "Warewulf pre-init (/init)"
echo
echo "Mounting kernel file systems..."
mountpoint -q /proc || (mkdir -p /proc && mount -t proc proc /proc && echo "Mounted /proc")
mountpoint -q /dev || (mkdir -p /dev && mount -t devtmpfs devtmpfs /dev && echo "Mounted /dev")
mountpoint -q /sys || (mkdir -p /sys && mount -t sysfs sysfs /sys && echo "Mounted /sys")
echo
echo "Loading /warewulf/config..."
if [ -f "/warewulf/config" ]; then
. /warewulf/config
else
@@ -17,24 +16,24 @@ else
sleep 60
echo b > /proc/sysrq-trigger || /sbin/reboot -f
fi
echo
echo "Warewulf v4 is now booting: ${WWHOSTNAME}"
echo
echo "Configuring root file system..."
chmod 755 /warewulf/wwinit
WWPRESCRIPTS=/warewulf/wwprescripts
chmod +rx "${WWPRESCRIPTS}"
if [ -z "${WWROOT}" -o "${WWROOT}" = "initramfs" ]; then
echo "Retaining initramfs and invoking /warewulf/wwinit..."
exec /warewulf/wwinit
WWROOT="${WWROOT:-initramfs}"
if [ "${WWROOT}" = "initramfs" ]; then
echo "WWROOT=${WWROOT}: using initial rootfs and invoking ${WWPRESCRIPTS}..."
exec "${WWPRESCRIPTS}"
elif [ "${WWROOT}" = "ramfs" -o "${WWROOT}" = "tmpfs" ]; then
echo "Setting up new ${WWROOT} rootfs..."
echo "WWROOT=${WWROOT}: setting up new ${WWROOT} rootfs (/newroot)..."
mkdir /newroot
mount wwroot /newroot -t ${WWROOT} -o mpol=interleave # mpol ignored for ramfs
tar -cf - --exclude ./proc --exclude ./sys --exclude ./dev --exclude --exclude ./newroot . | tar -xf - -C /newroot
mkdir /newroot/proc /newroot/dev /newroot/sys 2>/dev/null
echo "Switching to new rootfs and invoking /warewulf/wwinit..."
exec /sbin/switch_root /newroot /warewulf/wwinit
echo "Switching to new rootfs (/newroot) and invoking ${WWPRESCRIPTS}..."
exec /sbin/switch_root /newroot "${WWPRESCRIPTS}"
else
echo "ERROR: Unrecognized rootfs type requested: ${WWROOT}"
echo "Rebooting in 1 minute..."
@@ -43,7 +42,7 @@ else
fi
echo
echo "ERROR: There was a problem with the initial provisioning process."
echo "ERROR: wwinit encountered a problem."
echo "Rebooting in 1 minute..."
sleep 60
echo b > /proc/sysrq-trigger || /sbin/reboot -f

View File

@@ -1,6 +1,6 @@
#!/bin/sh
. /warewulf/config
echo "Bringing up lo:127.0.0.1"
echo "Warewulf prescript: localhost"
echo
echo "Bringing up lo..."
/sbin/ip link set dev lo up

View File

@@ -4,17 +4,22 @@
export PATH=/usr/bin:/bin:/usr/sbin:/sbin
echo "Warewulf prescript: IPMI"
echo
if [ "$WWIPMI_WRITE" != "true" ]; then
echo "IPMI write not configured: skipping"
exit
fi
echo "Loading IPMI kernel modules..."
modprobe ipmi_si ipmi_ssif ipmi_devintf ipmi_msghandler || (
echo "unable to load IPMI kernel modules: skipping IPMI configuration"
echo "Unable to load IPMI kernel modules: skipping IPMI configuration"
exit
)
if [ ! -e /dev/ipmi0 ]; then
echo "/dev/ipmi0 does not exist; creating..."
sleep 1
ipmi_dev=$(grep ipmidev /proc/devices | awk '{ print $1 }')
mknod -m 0666 /dev/ipmi0 c "$ipmi_dev" 0
@@ -83,7 +88,7 @@ if [ -n "$WWIPMI_PASSWORD" ]; then
fi
fi
# Serial Over LAN
echo "Configuring Serial over LAN..."
ipmitool channel setaccess 1 2 link=on ipmi=on callin=on privilege=4
ipmitool sol set force-encryption true 1
ipmitool sol set force-authentication true 1

View File

@@ -2,23 +2,19 @@
. /warewulf/config
# This will eventually be optional
if true; then
if [ -f "/etc/pam.d/system-auth" ]; then
echo "FIXING: system-auth"
sed -i -e '/^account.*pam_unix\.so\s*$/s/\s*$/\ broken_shadow/' /etc/pam.d/system-auth
echo "Warewulf prescript: VNFS fixes"
echo
add_broken_shadow() {
if [ -f "${1}" ]; then
echo "Adding broken_shadow to ${1}..."
sed -i -e '/^account.*pam_unix\.so\s*$/s/\s*$/\ broken_shadow/' "${1}"
fi
}
if [ -f "/etc/pam.d/password-auth" ]; then
echo "FIXING: password-auth"
sed -i -e '/^account.*pam_unix\.so\s*$/s/\s*$/\ broken_shadow/' /etc/pam.d/password-auth
fi
if [ -f "/etc/pam.d/common-account" ]; then
echo "FIXING: common-account"
sed -i -e '/^account.*pam_unix\.so\s*$/s/\s*$/\ broken_shadow/' /etc/pam.d/common-account
fi
fi
add_broken_shadow /etc/pam.d/system-auth
add_broken_shadow /etc/pam.d/password-auth
add_broken_shadow /etc/pam.d/common-account
echo "Adjusting root directory permissions..."
chmod 755 /

View File

@@ -2,32 +2,42 @@
. /warewulf/config
echo "Warewulf prescript: SELinux"
if test -f "/etc/sysconfig/selinux"; then
. /etc/sysconfig/selinux
else
echo "Skipping SELinux configuration: Host config not found: /etc/sysconfig/selinux"
echo "File not found: /etc/sysconfig/selinux"
echo "Skipping SELinux configuration."
exit
fi
if test "$SELINUX" == "disabled"; then
echo "Skipping SELinux setup per /etc/sysconfig/selinux"
if [ "$SELINUX" = "disabled" ]; then
echo "/etc/sysconfig/selinux:SELINUX=${SELINUX}: skipping SELinux configuration."
exit
fi
if grep -q "selinux=0" /proc/cmdline; then
echo "Skipping SELinux setup per kernel command line"
echo "/proc/cmdline:selinux=0: skipping SELinux configuration."
exit
fi
if [ $(findmnt / --noheadings --output SOURCE) == 'rootfs' ]; then
echo "Skipping SELinux configuration: rootfs does not support SELinux contexts"
if [ $(findmnt / --noheadings --output SOURCE) = 'rootfs' ]; then
echo "/ is a 'rootfs' file system, which does not support SELinux contexts."
echo "Skipping SELinux configuration."
echo
echo "WARNING: SELinux prep is being skipped, but SELinux is enabled on host! This may"
echo "WARNING: cause the system to not work properly. Try setting 'Root=tmpfs'"
sleep 5
echo "WARNING: SELinux configuration is being skipped, but SELinux is"
echo "WARNING: enabled in the image! The node will probably not boot"
echo "WARNING: properly."
echo "WARNING:"
echo "WARNING: Try setting 'Root=tmpfs'"
echo
echo "Continuing in 60s..."
sleep 60
exit
fi
echo "Setting up SELinux"
echo "Loading SELinux policy..."
/sbin/load_policy -i
echo "Restoring filesystem labels..."
/sbin/restorecon -e /sys -r /

View File

@@ -1,17 +0,0 @@
#!/bin/sh
echo "Hello from WWINIT"
. /warewulf/config
myPATH=/warewulf/init.d
ls -1 $myPATH/ | while read -r NAME; do
echo "Launching: $NAME"
sh "$myPATH/$NAME"
done
echo "Calling $WWINIT..."
echo
sleep 2
exec $WWINIT

View File

@@ -0,0 +1,14 @@
#!/usr/bin/sh
. /warewulf/config
echo "Warewulf prescript runner (/warewulf/wwprescripts)"
scriptdir=/warewulf/init.d
echo "Looking for prescripts in /warewulf/init.d/..."
ls -1 "${scriptdir}/" | while read -r name; do
echo "Running prescript: ${name}..."
sh "${scriptdir}/${name}"
done
echo
echo "Running ${WWINIT}..."
exec $WWINIT

View File

@@ -332,24 +332,22 @@ initramfs inside the image.
necessary to remove ``/etc/machine-id`` for dracut to properly generate
the initramfs in the location that Warewulf is expecting.
Set the node's iPXE template to ``dracut`` to direct iPXE to fetch the
node's initramfs image and boot with dracut semantics, rather than
booting the node image directly.
To direct iPXE to fetch the node's initramfs image and boot with dracut
semantics, set an ``IPXEMenuEntry`` tag for the node.
.. note::
Warewulf iPXE templates are located at ``/etc/warewulf/ipxe/`` when
Warewulf is installed via official packages. You can learn more
about how dracut booting works by inspecting its iPXE template at
``/etc/warewulf/ipxe/dracut.ipxe``.
Warewulf configures iPXE with a template located at
``/etc/warewulf/ipxe/default.ipxe``. Inspect the template to learn more about
the dracut booting process.
.. code-block:: shell
wwctl node set wwnode1 --ipxe dracut
wwctl node set wwnode1 --tagadd IPXEMenuEntry=dracut
.. note::
The iPXE template may be set at the node or profile level.
The IPXEMenuEntry variable 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.
@@ -379,8 +377,3 @@ to use up to 50% of physical memory. This size limit may be adjustd
using the kernel argument `wwinit.tmpfs.size`. (This parameter is
passed to the `size` option during tmpfs mount. See ``tmpfs(5)`` for
more details.)
.. warning::
Kernel overrides are not currently fully supported during dracut initramfs boot.

View File

@@ -23,12 +23,10 @@ iPXE
If you're using iPXE to boot (the default), you can get a command prompt by pressing with C-b during boot.
From the iPXE command prompt, you can run the same commands from `default.ipxe`_ (or `dracut.ipxe`_) to troubleshoot potential boot problems.
From the iPXE command prompt, you can run the same commands from `default.ipxe`_ to troubleshoot potential boot problems.
.. _default.ipxe: https://github.com/warewulf/warewulf/blob/main/etc/ipxe/default.ipxe
.. _dracut.ipxe: https://github.com/warewulf/warewulf/blob/main/etc/ipxe/dracut.ipxe
For example, the following commands perform a (relatively) normal Warewulf boot.
(Substitute your Warewulf server's IP address in place of 10.0.0.1,
update the port number if you have changed it from the default of 9873,