diff --git a/dracut/modules.d/90wwinit/load-wwinit.sh b/dracut/modules.d/90wwinit/load-wwinit.sh old mode 100755 new mode 100644 index aec55be9..6190f608 --- a/dracut/modules.d/90wwinit/load-wwinit.sh +++ b/dracut/modules.d/90wwinit/load-wwinit.sh @@ -1,19 +1,52 @@ #!/bin/bash -info "Mounting tmpfs at $NEWROOT" -mount -t tmpfs -o mpol=interleave ${wwinit_tmpfs_size_option} tmpfs "$NEWROOT" +function setup_disks() { + # format and prepare the disk(s) + /usr/bin/ignition --root=/sysroot --platform=metal --stage=disks || die "warewulf: failed to partition/format disk" + # mount /dev/disk/by-partlabel/root "$NEWROOT" || die "warewulf: failed to mount new root" + /usr/bin/ignition --root=/sysroot --platform=metal --stage=mount || die "warewulf: failed to mount disk" -for stage in "image" "system" "runtime" -do - info "Loading stage: ${stage}" - # Load runtime overlay from a static privledged port. - # Others use default settings. - localport="" - if [[ "${stage}" == "runtime" ]] - then +} + + +info "warewulf: Running warewulf v4 dracut init ${wwinit_persistent}" +archives="image system runtime" +if [ ${wwinit_persistent} -ne 1 ] ; then + info "warewulf: Mounting tmpfs at $NEWROOT" + mount -t tmpfs -o mpol=interleave ${wwinit_tmpfs_size_option} tmpfs "$NEWROOT" +else + info "warewulf: Using persistent setup ${wwinit_ignition}/ignition.json.ww?render=${wwinit_id}" + # get the igintion config and store in /run/igintion.ign, don't use igntion as so we can + # construct the download link + curl --location --silent --get ${localport} \ + --retry 60 --retry-delay 1 \ + "${wwinit_ignition}/ignition.json.ww?render=${wwinit_id}" -o /run/ignition-rootfs.json || die "warewulf: failed to fetch ignition configuration from ${wwinit_ignition}/ignition.json.ww?render=${wwinit_id}" + jq '.storage.filesystems |= map(select(.device=="/dev/disk/by-partlabel/rootfs").path="/")' /run/ignition-rootfs.json > /run/ignition.json || die "warewulf: failed to rewrite ignition configuration" + setup_disks +# if [ -e ${NEWROOT}/warewulf/ww_${wwinit_imagename} ] ; then +# info "warewulf: found ${NEWROOT}/warewulf/ww_${wwinit_imagename} running rsync for update" +# # we need only the overlays as we update the root +# # with rsync when the same image is used +# archives="system runtime" +# rsync -aux --delete --exclude=/proc/ --exclude=/sys/ --exclude=/dev rsync://${wwinit_ip}/${wwinit_imagename} $NEWROOT || die "warewulf: failed to run rsync" +# elif [ -e ${NEWROOT}/warewulf/ww_* ] ; then +# info "warewulf: found $(ls ${NEWROOT}/warewulf/ww_*) but image is ${wwinit_imagename}, wiping $NEWROOT" +# # we didn't have the wanted image but provisioned with warewulf, wipe the rootfs +# /usr/bin/ignition --root=/sysroot --platform=metal --stage=umount || die "warewulf: failed to mount disk" +# jq '.storage.filesystems |= map(select(.device=="/dev/disk/by-partlabel/rootfs").wipeFilesystem=true)' /run/ignition.json > /run/ignition.json.mod || die "couldn't reformation ignition configuration" +# mv /run/ignition.json.mod /run/ignition.json || die "warewulf: couldn't mv ignition configuration back" +# setup_disks +# fi +fi +for stage in $archives ; do + info "warewulf: Loading ${stage}" + # Load runtime overlay from a static privledged port. + # Others use default settings. + localport="" + if [[ "${stage}" == "runtime" ]] ; then localport="--local-port 1-1023" - fi - ( + fi + ( curl --location --silent --get ${localport} \ --retry 60 --retry-connrefused --retry-delay 1 \ --data-urlencode "assetkey=${wwinit_assetkey}" \ @@ -25,3 +58,16 @@ do | cpio -im --directory="${NEWROOT}" ) || die "Unable to load stage: ${stage}" done + +if [ ${wwinit_persistent} -eq 1 ] ; then + # this avoids that ignition runs a second time + info "warewulf: removing ignition config from wwinit image" + rm -rf ${NEWROOT}/warewulf/ignition.json + echo "Container name of persistent install: ${wwinit_imagename}" > ${NEWROOT}/warewulf/ww_${wwinit_imagename} + echo "# created from ${wwinit_ignition_uri}/fstab.ww?render=${winit_id}" > ${NEWROOT}/etc/fstab + curl --location --silent --get ${localport} \ + --retry 60 --retry-delay 1 \ + "${wwinit_ignition}/fstab.ww?render=${wwinit_id}" >> ${NEWROOT}/etc/fstab || die "warewulf: failed to write correct fstab" +fi +info "warewulf: Finished warewulf v4 dracut" + diff --git a/dracut/modules.d/90wwinit/module-setup.sh b/dracut/modules.d/90wwinit/module-setup.sh old mode 100755 new mode 100644 index aeec152c..9aa5dc65 --- a/dracut/modules.d/90wwinit/module-setup.sh +++ b/dracut/modules.d/90wwinit/module-setup.sh @@ -9,12 +9,12 @@ check() { } depends() { - echo network + echo network ignition return 0 } install() { - inst_multiple cpio curl dmidecode + inst_multiple cpio curl dmidecode rsync jq inst_hook cmdline 30 "$moddir/parse-wwinit.sh" inst_hook pre-mount 30 "$moddir/load-wwinit.sh" if dracut_module_included "network-manager" && dracut_module_included "systemd" diff --git a/dracut/modules.d/90wwinit/parse-wwinit.sh b/dracut/modules.d/90wwinit/parse-wwinit.sh old mode 100755 new mode 100644 index 65bc6349..d46dbd64 --- a/dracut/modules.d/90wwinit/parse-wwinit.sh +++ b/dracut/modules.d/90wwinit/parse-wwinit.sh @@ -3,25 +3,27 @@ [ -z "$root" ] && root=$(getarg root=) -if [ "${root}" = "wwinit" ] -then - info "root=${root}" +if [ "${root}" = "wwinit" ] || [ "${root}" = "persistent" ] ; then + info "warewulf: root=${root}" export wwinit_uuid=$(dmidecode -s system-uuid) export wwinit_assetkey=$(dmidecode -s chassis-asset-tag) export wwinit_uri="$(getarg wwinit.uri)" - + export wwinit_ignition="$(getarg wwinit.ignition)" + export wwinit_ip="$(getarg wwinit.ip)" + export wwinit_imagename="$(getarg wwinit.imagename)" + export wwinit_id=$(getarg wwinit.id) wwinit_tmpfs_size=$(getarg wwinit.tmpfs.size=) - if [ -n "$wwinit_tmpfs_size" ] - then - info "wwinit.tmpfs.size=${wwinit_tmpfs_size}" + if [ -n "$wwinit_tmpfs_size" ] ; then + info "warewulf: wwinit.tmpfs.size=${wwinit_tmpfs_size}" export wwinit_tmpfs_size_option="-o size=${wwinit_tmpfs_size}" fi - - if [ -n "${wwinit_uri}" ] - then - info "Found root=${root} and a Warewulf server uri. Will boot from Warewulf." + if [ "${root}" = "persistent" ] ; then + export wwinit_persistent="1"; info "warewulf: wwinit_persistent=$wwinit_persistent" + fi + if [ -n "${wwinit_uri}" ] ; then + info "warewulf: Found root=${root} and a Warewulf server uri. Will boot from Warewulf." rootok=1 else - die "Found root=${root} but no Warewulf server uri. Cannot boot from Warewulf." + die "warewulf: Found root=${root} but no Warewulf server uri. Cannot boot from Warewulf." fi fi diff --git a/etc/grub/grub.cfg.ww b/etc/grub/grub.cfg.ww index 9c3413a1..6ee3ce3e 100644 --- a/etc/grub/grub.cfg.ww +++ b/etc/grub/grub.cfg.ww @@ -31,7 +31,10 @@ smbios --type 3 --get-string 8 --set assetkey uri="(http,{{.Ipaddr}}:{{.Port}})/provision/${net_default_mac}?assetkey=${assetkey}" kernel="${uri}&stage=kernel" -set default={{ or .Tags.GrubMenuEntry "single-stage" }} +{{- $defentry := "singlestage" }} +{{- if eq .Root "persistent"}}{{ $defentry = "dracut" }}{{ end }} +{{- if .Tags.GrubMenuEntry }}{{ $defentry = .Tags.GrubMenuEntry }}{{ end }} +set default={{ $defentry}} set timeout=2 menuentry "Single-stage boot" --id single-stage { @@ -58,8 +61,6 @@ menuentry "Single-stage boot" --id single-stage { echo "!! Unable to load kernel." echo "!! Rebooting in 15s..." echo "!!" - sleep 15 - reboot fi echo "Downloading images..." @@ -73,8 +74,6 @@ menuentry "Single-stage boot" --id single-stage { echo "!! Unable to load images." echo "!! Rebooting in 15s..." echo "!!" - sleep 15 - reboot fi echo "Booting..." @@ -105,8 +104,6 @@ menuentry "Single-stage boot (no compression)" --id single-stage-nocompress { echo "!! Unable to load kernel." echo "!! Rebooting in 15s..." echo "!!" - sleep 15 - reboot fi echo "Downloading images..." @@ -120,15 +117,13 @@ menuentry "Single-stage boot (no compression)" --id single-stage-nocompress { echo "!! Unable to load images." echo "!! Rebooting in 15s..." echo "!!" - sleep 15 - reboot fi echo "Booting..." boot } -menuentry "Two stage boot with dracut" --id dracut { +menuentry "Two stage boot with dracut {{ if eq .Root "persistent"}}(persistent){{ end }}" --id dracut { echo "Warewulf Server:" echo "* Ipaddr: {{.Ipaddr}}" echo "* Port: {{.Port}}" @@ -148,19 +143,24 @@ menuentry "Two stage boot with dracut" --id dracut { wwinit_uri="http://{{.Ipaddr}}:{{.Port}}/provision/${net_default_mac}" 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" + {{- if eq .Root "persistent"}} + ignition_args="wwinit.ignition=http://{{.Ipaddr}}:{{.Port}}/overlay-file/persistent wwinit.imagename={{ .ImageName }} wwinit.id={{ .Id }} wwinit.ip={{ .Ipaddr }}" + root="persistent" + echo "* Persistent install" + {{- else }} + root="wwinit" + {{- end }} + wwinit_args="root=$root wwinit.uri=${wwinit_uri} init=/init" echo echo "Downloading kernel image..." - linux $kernel wwid=${net_default_mac} {{.KernelArgs}} $net_args $wwinit_args + linux $kernel wwid=${net_default_mac} {{.KernelArgs}} $net_args $wwinit_args $ignition_args if [ $? != 0 ] then echo "!!" echo "!! Unable to load kernel." echo "!! Rebooting in 15s..." echo "!!" - sleep 15 - reboot fi echo "Downloading initramfs..." @@ -171,8 +171,6 @@ menuentry "Two stage boot with dracut" --id dracut { echo "!! Unable to load initramfs." echo "!! Rebooting in 15s..." echo "!!" - sleep 15 - reboot fi echo "Booting..." diff --git a/overlays/persistent/ignition.json.ww b/overlays/persistent/ignition.json.ww new file mode 100644 index 00000000..de2ece76 --- /dev/null +++ b/overlays/persistent/ignition.json.ww @@ -0,0 +1 @@ +{{ IgnitionJson }} \ No newline at end of file diff --git a/overlays/wwinit/rootfs/init b/overlays/wwinit/rootfs/init index f1cdaa58..13b15196 100755 --- a/overlays/wwinit/rootfs/init +++ b/overlays/wwinit/rootfs/init @@ -28,6 +28,9 @@ WWROOT="${WWROOT:-initramfs}" if [ "${WWROOT}" = "initramfs" ]; then echo "WWROOT=${WWROOT}: using initial rootfs and invoking ${WWPRESCRIPTS}..." exec "${WWPRESCRIPTS}" +elif [ "${WWROOT}" = "persistent" ] ; then + echo "WWROOT=${WWROOT}: booting from DISK" + exec "${WWPRESCRIPTS}" elif [ "${WWROOT}" = "ramfs" -o "${WWROOT}" = "tmpfs" ]; then echo "WWROOT=${WWROOT}: setting up new ${WWROOT} rootfs (/newroot)..." mkdir /newroot