diff --git a/CHANGELOG.md b/CHANGELOG.md index 837a7d11..57e3f48d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -68,6 +68,13 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). the node continues to boot and `wwclient` retries the download at runtime. - `hosts` overlay added to the default system overlay list - Distinguish between OS images and overlay images in documentation +- Updated iPXE, GRUB, and dracut boot scripts to use dedicated server routes + (`/kernel/`, `/image/`, `/system/`, `/runtime/`, `/initramfs/`) instead of + `/provision/{hwaddr}?stage=X` +- Updated `wwclient` to use the `/runtime/` route for runtime overlay downloads +- New `wwinit.server` kernel parameter for dracut/wwinit boot; `wwinit.uri` + remains supported for backward compatibility +- Updated troubleshooting documentation examples to reflect the new URL scheme - Updated `MAINTAINING.md` to document golang version policy - Clarified functionality of syncuser commands and overlay in documentation - Audit and correct documentation, cobra help text, and log messages for accuracy diff --git a/dracut/modules.d/90wwinit/load-wwinit.sh b/dracut/modules.d/90wwinit/load-wwinit.sh index d89867d2..6f851186 100644 --- a/dracut/modules.d/90wwinit/load-wwinit.sh +++ b/dracut/modules.d/90wwinit/load-wwinit.sh @@ -2,9 +2,29 @@ [ -z "${wwinit_root_device}" ] && return 0 +# Resolve the server base URL and hardware address from kernel parameters. +# Supports two formats: +# New: wwinit.server=http://host:port (uses wwid kernel param for hwaddr) +# Legacy: wwinit.uri=http://host:port/provision/hwaddr (extracts hwaddr from path) +# wwinit.server takes precedence over wwinit.uri when both are present. +resolve_base() { + local val="${wwinit_server:-${wwinit_uri}}" + if echo "${val}" | grep -q '/provision/'; then + # Legacy: http://host:port/provision/hwaddr + ww_base="${val%%/provision/*}" + ww_hwaddr="${val##*/provision/}" + else + # New: http://host:port + ww_base="${val}" + ww_hwaddr="$(getarg wwid)" + fi +} + +resolve_base + get_stage() { stage="${1}" - uri="${2:-${wwinit_uri}}" + base="${2:-${ww_base}}" cacert="${3}" info "warewulf: loading stage: ${stage}" # Load runtime overlay from a static privledged port. @@ -17,12 +37,17 @@ get_stage() { if [ -n "${cacert}" ]; then cacert_opt="--cacert ${cacert}" fi + local hwaddr="${ww_hwaddr}" + case "${stage}" in + image) uri="${base}/image/${hwaddr}" ;; + system) uri="${base}/system/${hwaddr}" ;; + runtime) uri="${base}/runtime/${hwaddr}" ;; + esac ( curl --location --silent --get ${localport} ${cacert_opt} \ --retry 60 --retry-connrefused --retry-delay 1 \ --data-urlencode "assetkey=${wwinit_assetkey}" \ --data-urlencode "uuid=${wwinit_uuid}" \ - --data-urlencode "stage=${stage}" \ --data-urlencode "compress=gz" \ "${uri}" \ | gzip -d \ @@ -58,11 +83,10 @@ done . /tmp/wwinit/warewulf/config cert_file="/tmp/wwinit/warewulf/tls/warewulf.crt" if [ "${WWTLS}" = "true" ] && [ -f "$cert_file" ]; then - # TLS enabled: build HTTPS URI using wwid from kernel cmdline + # TLS enabled: build HTTPS base URL using server address from kernel cmdline # (mirrors wwclient URL construction in internal/app/wwclient/root.go) - wwid=$(getarg wwid) - runtime_uri="https://${WWIPADDR}:${WWTLSPORT}/provision/${wwid}" - get_stage "runtime" "${runtime_uri}" "${cert_file}" || warn "warewulf: unable to load runtime overlay over HTTPS (ignored)" + tls_base="https://${WWIPADDR}:${WWTLSPORT}" + get_stage "runtime" "${tls_base}" "${cert_file}" || warn "warewulf: unable to load runtime overlay over HTTPS (ignored)" else # No TLS: fetch runtime over HTTP get_stage "runtime" || warn "warewulf: unable to load runtime overlay (ignored)" diff --git a/dracut/modules.d/90wwinit/parse-wwinit.sh b/dracut/modules.d/90wwinit/parse-wwinit.sh index 255508a4..d9be2f99 100644 --- a/dracut/modules.d/90wwinit/parse-wwinit.sh +++ b/dracut/modules.d/90wwinit/parse-wwinit.sh @@ -7,12 +7,13 @@ case "${root}" in wwinit|wwinit:*) info "warewulf: root=${root}" + export wwinit_server="$(getarg wwinit.server)" export wwinit_uri="$(getarg wwinit.uri)" - if [ -n "${wwinit_uri}" ]; then - info "warewulf: Found root=${root} and wwinit.uri=${wwinit_uri}. Will boot from Warewulf." + if [ -n "${wwinit_server}" ] || [ -n "${wwinit_uri}" ]; then + info "warewulf: Found root=${root} and wwinit.server=${wwinit_server} wwinit.uri=${wwinit_uri}. Will boot from Warewulf." rootok=1 else - die "warewulf: Found root=${root} but no wwinit.uri. Cannot boot from Warewulf." + die "warewulf: Found root=${root} but neither wwinit.server nor wwinit.uri. Cannot boot from Warewulf." fi export wwinit_uuid=$(dmidecode -s system-uuid) diff --git a/etc/grub/grub.cfg.ww b/etc/grub/grub.cfg.ww index 43eccaec..b41fab18 100644 --- a/etc/grub/grub.cfg.ww +++ b/etc/grub/grub.cfg.ww @@ -29,8 +29,9 @@ reboot echo "Reading asset key..." smbios --type 3 --get-string 8 --set assetkey -uri="(http,{{.Authority}})/provision/${net_default_mac}?assetkey=${assetkey}" -kernel="${uri}&stage=kernel" +base="(http,{{.Authority}})" +params="assetkey=${assetkey}" +kernel="${base}/kernel/${net_default_mac}?${params}" set default={{ or .Tags.GrubMenuEntry "single-stage" }} set timeout=2 @@ -64,10 +65,10 @@ menuentry "Single-stage boot" --id single-stage { fi echo "Downloading images..." - image="${uri}&stage=image&compress=gz" - system="${uri}&stage=system&compress=gz" + image="${base}/image/${net_default_mac}?${params}&compress=gz" + system="${base}/system/${net_default_mac}?${params}&compress=gz" {{- if not (eq .TLS true) }} - runtime="${uri}&stage=runtime&compress=gz" + runtime="${base}/runtime/${net_default_mac}?${params}&compress=gz" {{- end }} initrd $image $system $runtime if [ $? != 0 ] @@ -113,10 +114,10 @@ menuentry "Single-stage boot (no compression)" --id single-stage-nocompress { fi echo "Downloading images..." - image="${uri}&stage=image" - system="${uri}&stage=system" + image="${base}/image/${net_default_mac}?${params}" + system="${base}/system/${net_default_mac}?${params}" {{- if not (eq .TLS true) }} - runtime="${uri}&stage=runtime" + runtime="${base}/runtime/${net_default_mac}?${params}" {{- end }} initrd $image $system $runtime if [ $? != 0 ] @@ -149,11 +150,12 @@ menuentry "Two stage boot with dracut" --id dracut { {{- end }} echo "* KernelArgs: {{.KernelArgs}}" - initramfs="${uri}&stage=initramfs" + initramfs="${base}/initramfs/${net_default_mac}?${params}" wwinit_uri="http://{{.Ipaddr}}:{{.Port}}/provision/${net_default_mac}" + wwinit_server="http://{{.Ipaddr}}:{{.Port}}" 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:{{default "tmpfs" .Root}} wwinit.uri=${wwinit_uri} init=/warewulf/run-init" + wwinit_args="root=wwinit:{{default "tmpfs" .Root}} wwinit.server=${wwinit_server} wwinit.uri=${wwinit_uri} init=/warewulf/run-init" echo echo "Downloading kernel image..." diff --git a/etc/ipxe/default.ipxe b/etc/ipxe/default.ipxe index 8339b913..afcdafa7 100644 --- a/etc/ipxe/default.ipxe +++ b/etc/ipxe/default.ipxe @@ -15,11 +15,12 @@ sleep 30 reboot {{- end }} -set baseuri http://{{.Authority}}/provision/{{.Hwaddr}} -set uri ${baseuri}?assetkey=${asset}&uuid=${uuid} +set base http://{{.Authority}} +set hwaddr {{.Hwaddr}} +set params assetkey=${asset}&uuid=${uuid} echo Downloading kernel image... -kernel --name kernel ${uri}&stage=kernel || goto reboot +kernel --name kernel ${base}/kernel/${hwaddr}?${params} || goto reboot {{- if .Tags.IPXEMenuEntry }} set method {{ .Tags.IPXEMenuEntry }} @@ -43,12 +44,12 @@ goto metadata :imgextract_continue echo echo Downloading compressed image with imgextract... -imgextract --name image ${uri}&stage=image&compress=gz || goto error_use_initrd +imgextract --name image ${base}/image/${hwaddr}?${params}&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 +imgextract --name system ${base}/system/${hwaddr}?${params}&compress=gz || goto error_reboot {{- if not (eq .TLS true) }} 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) +imgextract --name runtime ${base}/runtime/${hwaddr}?${params}&compress=gz && set runtime_initrd initrd=runtime || echo Unable to download runtime overlay. (ignored) {{- end }} goto boot_single_stage @@ -62,12 +63,12 @@ goto metadata :initrd_continue echo echo Downloading compressed image with initrd... -initrd --name image ${uri}&stage=image&compress=gz || goto error_reboot +initrd --name image ${base}/image/${hwaddr}?${params}&compress=gz || goto error_reboot echo Downloading compressed system overlay with initrd... -initrd --name system ${uri}&stage=system&compress=gz || goto error_reboot +initrd --name system ${base}/system/${hwaddr}?${params}&compress=gz || goto error_reboot {{- if not (eq .TLS true) }} 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) +initrd --name runtime ${base}/runtime/${hwaddr}?${params}&compress=gz && set runtime_initrd initrd=runtime || echo Unable to download runtime overlay. (ignored) {{- end }} goto boot_single_stage @@ -77,12 +78,12 @@ goto metadata :initrd_nocompress_continue echo echo Downloading uncompressed image with initrd... -initrd --name image ${uri}&stage=image || goto error_reboot +initrd --name image ${base}/image/${hwaddr}?${params} || goto error_reboot echo Downloading uncompressed system overlay with initrd... -initrd --name system ${uri}&stage=system || goto error_reboot +initrd --name system ${base}/system/${hwaddr}?${params} || goto error_reboot {{- if not (eq .TLS true) }} 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) +initrd --name runtime ${base}/runtime/${hwaddr}?${params} && set runtime_initrd initrd=runtime || echo Unable to download runtime overlay. (ignored) {{- end }} goto boot_single_stage @@ -92,9 +93,9 @@ goto metadata :dracut_continue echo echo Downloading dracut initramfs... -initrd --name initramfs ${uri}&stage=initramfs || goto error_reboot +initrd --name initramfs ${base}/initramfs/${hwaddr}?${params} || 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:{{default "tmpfs" .Root}} wwinit.uri=${baseuri} init=/warewulf/run-init +set dracut_wwinit root=wwinit:{{default "tmpfs" .Root}} wwinit.server=${base} wwinit.uri=${base}/provision/${hwaddr} init=/warewulf/run-init goto boot_two_stage_dracut :boot_single_stage diff --git a/internal/app/wwclient/root.go b/internal/app/wwclient/root.go index 498fcb85..3c60fa53 100644 --- a/internal/app/wwclient/root.go +++ b/internal/app/wwclient/root.go @@ -316,12 +316,11 @@ func updateSystem(target string, ipaddr string, port int, wwid string, tag strin values := &url.Values{} values.Set("assetkey", tag) values.Set("uuid", localUUID.String()) - values.Set("stage", "runtime") values.Set("compress", "gz") getURL := &url.URL{ Scheme: scheme, Host: fmt.Sprintf("%s:%d", ipaddr, port), - Path: fmt.Sprintf("provision/%s", wwid), + Path: fmt.Sprintf("runtime/%s", wwid), RawQuery: values.Encode(), } wwlog.Debug("making request: %s", getURL) diff --git a/overlays/host/rootfs/grub.cfg.ww b/overlays/host/rootfs/grub.cfg.ww index 76f9ad35..aadfbfb9 100644 --- a/overlays/host/rootfs/grub.cfg.ww +++ b/overlays/host/rootfs/grub.cfg.ww @@ -10,11 +10,11 @@ smbios --type 3 --get-string 8 --set assetkey set timeout=2 # Must chainload in order to get kernel args for specific node menuentry "Load specific configfile" { - conf="(http,{{.Ipaddr}}:{{.Warewulf.Port}})/efiboot/grub.cfg?assetkey=${assetkey}" + conf="(http,{{.Ipaddr}}:{{.Warewulf.Port}})/grub/${net_default_mac}?assetkey=${assetkey}" configfile $conf } menuentry "Chainload shim from image" { - shim="(http,{{.Ipaddr}}:{{.Warewulf.Port}})/efiboot/shim.efi?assetkey=${assetkey}" + shim="(http,{{.Ipaddr}}:{{.Warewulf.Port}})/efiboot/shim.efi?wwid=${net_default_mac}&assetkey=${assetkey}" chainloader ${shim} } menuentry "UEFI Firmware Settings" --id "uefi-firmware" { diff --git a/userdocs/troubleshooting/troubleshooting.rst b/userdocs/troubleshooting/troubleshooting.rst index acfcdcc5..4293d04c 100644 --- a/userdocs/troubleshooting/troubleshooting.rst +++ b/userdocs/troubleshooting/troubleshooting.rst @@ -52,16 +52,17 @@ cluster node's MAC address in place of 00:00:00:00:00:00.) .. code-block:: - set uri http://10.0.0.1:9873/provision/00:00:00:00:00:00 - kernel --name kernel ${uri}?stage=kernel - imgextract --name image ${uri}?stage=image&compress=gz - imgextract --name system ${uri}?stage=system&compress=gz - imgextract --name runtime ${uri}?stage=runtime&compress=gz + set base http://10.0.0.1:9873 + set hwaddr 00:00:00:00:00:00 + kernel --name kernel ${base}/kernel/${hwaddr} + imgextract --name image ${base}/image/${hwaddr}?compress=gz + imgextract --name system ${base}/system/${hwaddr}?compress=gz + imgextract --name runtime ${base}/runtime/${hwaddr}?compress=gz boot kernel initrd=image initrd=system initrd=runtime -- The ``uri`` variable points to ``warewulfd`` for future reference. This - includes the cluster node's MAC address so that Warewulf knows what image and - overlays to provide. +- The ``base`` variable points to ``warewulfd`` for future reference. The MAC + address is appended to each resource path so that Warewulf knows what image + and overlays to provide. - The ``kernel`` command fetches a kernel for later booting. @@ -110,12 +111,12 @@ the port number if you have changed it from the default of 9873.) .. code-block:: - uri="(http,10.0.0.1:9873)/provision/${net_default_mac}" - linux "${uri}?stage=kernel" wwid=${net_default_mac} - initrd "${uri}?stage=image&compress=gz" "${uri}?stage=system&compress=gz" "${uri}?stage=runtime&compress=gz" + base="(http,10.0.0.1:9873)" + linux "${base}/kernel/${net_default_mac}" wwid=${net_default_mac} + initrd "${base}/image/${net_default_mac}?compress=gz" "${base}/system/${net_default_mac}?compress=gz" "${base}/runtime/${net_default_mac}?compress=gz" boot -- The ``uri`` variable points to ``warewulfd`` for future reference. +- The ``base`` variable points to ``warewulfd`` for future reference. ``${net_default_mac}`` provides Warewulf with the MAC address of the booting node, so that Warewulf knows what image and overlays to provide it. @@ -143,7 +144,7 @@ enabled. To do so, substitute the ``linux`` command above. .. code-block:: - linux "${uri}?stage=kernel" wwid=${net_default_mac} debug rdinit=/bin/sh + linux "${base}/kernel/${net_default_mac}" wwid=${net_default_mac} debug rdinit=/bin/sh .. note::