From 2f572b49a654422652c94d9a219de761389769ee Mon Sep 17 00:00:00 2001 From: Daniel Hilst <392820+dhilst@users.noreply.github.com> Date: Thu, 25 Jun 2026 15:42:52 -0300 Subject: [PATCH] fix(xCAT-genesis-base): make 2.14.5 -> 2.18 upgrade clean on EL8/EL9 A 2.17 -> 2.18 management-node upgrade installs xCAT-genesis-base 2.18 over the 2.14.5 payload that 2.17 shipped, and aborted in three ways that only surface on the upgrade path (a fresh EL10 install never hit them): 1. usr/lib/dracut/hooks changed type: 2.14.5 shipped it as a real directory, modern dracut (EL8+) makes it a symlink to ../../../var/lib/dracut/hooks. RPM refuses to replace a directory with a symlink across an upgrade ("file ... conflicts"). The %pretrans removal does not help because rpm computes the conflict from package metadata, not the live filesystem. Materialize the symlink back into a real directory (with the hook contents) in %install so the payload type matches the installed 2.14.5 layout. 2. The %pretrans Lua used table.getn()/unpack(), removed in Lua 5.2+, so on EL8/EL9 (and any upgrade where the dirs exist) the scriptlet died with "attempt to call a nil value (field getn)". Use #t / table.unpack. 3. The %post ran "mknb" unconditionally; during a full "dnf update xCAT" xcatd is stopped, so mknb cannot connect and exited non-zero, failing the whole transaction. Tolerate the failure and leave the genesis-base-updated marker so the image is rebuilt once xcatd is back. (cherry picked from commit f421c2b30c1572c5aa37d8da043e3c87267b275a) --- xCAT-genesis-builder/xCAT-genesis-base.spec | 31 +++++++++++++++------ 1 file changed, 23 insertions(+), 8 deletions(-) diff --git a/xCAT-genesis-builder/xCAT-genesis-base.spec b/xCAT-genesis-builder/xCAT-genesis-base.spec index aea7027f9..768c368a8 100644 --- a/xCAT-genesis-builder/xCAT-genesis-base.spec +++ b/xCAT-genesis-builder/xCAT-genesis-base.spec @@ -131,13 +131,25 @@ dracut --compress gzip -m "xcat base" --no-early-microcode -N -f "$DRACUT_IMAGE" zcat "$DRACUT_IMAGE" | cpio -dumi ) -%if 0%{?rhel} > 0 && 0%{?rhel} <= 9 -# EL9 upgrade safety depends on this remaining a real directory. +# xCAT 2.14.5 genesis payloads shipped usr/lib/dracut/hooks as a real directory. +# Newer dracut (EL8+) makes it a symlink to ../../../var/lib/dracut/hooks. RPM +# cannot replace a directory with a symlink across an upgrade, so a 2.17 -> 2.18 +# upgrade aborts with a file conflict on this path. Materialize the symlink back +# into a real directory (with the hook contents) so the payload type matches the +# installed 2.14.5 layout and the upgrade is conflict-free on EL8/EL9/EL10. +if [ -L "$GENESIS_FS/usr/lib/dracut/hooks" ]; then + hooks_target="$GENESIS_FS/var/lib/dracut/hooks" + rm -f "$GENESIS_FS/usr/lib/dracut/hooks" + if [ -d "$hooks_target" ]; then + cp -a "$hooks_target" "$GENESIS_FS/usr/lib/dracut/hooks" + else + mkdir -p "$GENESIS_FS/usr/lib/dracut/hooks" + fi +fi if [ ! -d "$GENESIS_FS/usr/lib/dracut/hooks" ] || [ -L "$GENESIS_FS/usr/lib/dracut/hooks" ]; then - echo "EL%{?rhel} genesis payload has invalid usr/lib/dracut/hooks layout" >&2 + echo "genesis payload has invalid usr/lib/dracut/hooks layout" >&2 exit 1 fi -%endif for script in \ "$GENESIS_FS/sbin/dhclient-script" \ @@ -207,7 +219,7 @@ local tail_leaf_prefix = '`-- ' local link_prefix = ' -> ' local function printf(...) - io.write(string.format(unpack(arg))) + io.write(string.format(table.unpack({...}))) end local function remove_directory(directory, level, prefix) @@ -215,7 +227,7 @@ local function remove_directory(directory, level, prefix) local num_files = 0 if posix.access(directory, "rw") then local files = posix.dir(directory) - local last_file_index = table.getn(files) + local last_file_index = #files table.sort(files) for i, name in ipairs(files) do if name ~= '.' and name ~= '..' then @@ -277,8 +289,11 @@ remove_directory_deep("/opt/xcat/share/xcat/netboot/genesis/%{tarch}/fs/var/run" if [ "$1" == "2" ]; then #only on upgrade, as on install it's probably not going to work... if [ -f "/proc/cmdline" ]; then # prevent running it during install into chroot image . /etc/profile.d/xcat.sh - mknb %{tarch} - echo "If you are installing/updating xCAT-genesis-base separately, not as part of installing/updating all of xCAT, run 'mknb ' manually" + # During a full 'dnf update xCAT', xcatd is stopped while xCAT is being + # upgraded, so mknb cannot reach it and exits non-zero. That must not fail + # the rpm transaction: drop the genesis-base-updated marker so the netboot + # image is regenerated later (xcatd post-start / manual 'mknb '). + mknb %{tarch} || echo "mknb %{tarch} deferred (xcatd not reachable during upgrade); run 'mknb %{tarch}' after xcatd is up" mkdir -p /etc/xcat touch /etc/xcat/genesis-base-updated fi