diff --git a/xCAT-genesis-builder/dracut_105/el/module-setup.sh b/xCAT-genesis-builder/dracut_105/el/module-setup.sh index 32f0aadda..95d52c395 100755 --- a/xCAT-genesis-builder/dracut_105/el/module-setup.sh +++ b/xCAT-genesis-builder/dracut_105/el/module-setup.sh @@ -87,7 +87,11 @@ install() { dracut_install /sbin/rsyslogd /etc/protocols umount /bin/rpm /usr/lib/rpm/rpmrc #dracut_install chmod /sbin/route /sbin/ifconfig /usr/bin/whoami /usr/bin/head /usr/bin/tail basename /etc/redhat-release ping tr lsusb /usr/share/hwdata/usb.ids #ibm fw wrapper requirements dracut_install chmod ip /usr/bin/whoami /usr/bin/head /usr/bin/tail basename /etc/redhat-release ping tr lsusb /usr/share/hwdata/usb.ids #ibm fw wrapper requirements - dracut_install efibootmgr dmidecode #uxspi prereqs, but will use dmidecode to improve decision on loading ipmi_si + # uxspi prereqs. dmidecode also improves the decision on loading ipmi_si. Neither is + # packaged for ppc64le, so install whichever the build root carries. + for _fw_tool in efibootmgr dmidecode; do + command -v "$_fw_tool" >/dev/null 2>&1 && dracut_install "$_fw_tool" + done dracut_install lldptool dracut_install /usr/share/zoneinfo/posix/Zulu dracut_install /usr/share/zoneinfo/posix/GMT-0 diff --git a/xCAT-genesis-builder/verify-genesis-payload b/xCAT-genesis-builder/verify-genesis-payload index 7addc544f..11fdc4a33 100755 --- a/xCAT-genesis-builder/verify-genesis-payload +++ b/xCAT-genesis-builder/verify-genesis-payload @@ -1,16 +1,35 @@ #!/bin/bash # -# verify-genesis-payload [required-path ...] +# verify-genesis-payload [--commands-from ] [required-path ...] # # dracut_install() reports a missing binary and returns, so the module install function keeps -# going and the image ships without it. Three such holes reached a release: no dhclient, no -# sshd-session and no UTF-8 locale. Check the extracted payload before it becomes an rpm. +# going and the image ships without it. Four such holes reached a release: no dhclient, no +# openssl, no sshd-session and no UTF-8 locale. Check the extracted payload before it becomes +# an rpm. # -# Paths are relative to . The caller adds what only it knows (dhclient is not -# packaged on every release); the rules below come from the payload itself. +# Paths are relative to . --commands-from reads back the command names the +# dracut module installs. The caller adds what only it knows (the DHCP client is not the same +# package on every release); the rules below come from the payload itself. set -u +commands_from="" +while [ $# -gt 0 ]; do + case "$1" in + --commands-from) + commands_from=${2:-} + shift 2 || true + ;; + --commands-from=*) + commands_from=${1#*=} + shift + ;; + *) + break + ;; + esac +done + payload=${1:-} if [ -z "$payload" ] || [ ! -d "$payload" ]; then echo "verify-genesis-payload: not a payload directory: ${payload:-}" >&2 @@ -36,6 +55,34 @@ for path in "$@"; do require "$path" "required by the build" done +# The dracut module names every command Genesis runs. A name that the build root does not +# supply installs nothing and says nothing, so read the names back and check each one. +# Names under a condition are release-dependent, so only the top level of install() counts. +if [ -n "$commands_from" ]; then + if [ ! -r "$commands_from" ]; then + echo "verify-genesis-payload: cannot read $commands_from" >&2 + exit 2 + fi + commands=$(awk ' + /^install\(\)/ { in_install = 1; next } + in_install && /^}/ { in_install = 0 } + in_install && /^ dracut_install / { + sub(/#.*/, "") + sub(/^ dracut_install /, "") + print + }' "$commands_from" | tr ' \t' '\n\n' | grep -v '^$' | grep -v '^[/-]' | sort -u) + if [ -z "$commands" ]; then + echo "verify-genesis-payload: no command name read from $commands_from" >&2 + exit 2 + fi + for command in $commands; do + have "bin/$command" || have "sbin/$command" \ + || have "usr/bin/$command" || have "usr/sbin/$command" \ + || missing="$missing + $command (installed by $commands_from)" + done +fi + require usr/sbin/sshd "Genesis is reached over ssh" require usr/bin/mktemp "getdestiny makes its request file with it" diff --git a/xCAT-genesis-builder/xCAT-genesis-base.spec b/xCAT-genesis-builder/xCAT-genesis-base.spec index cd3e737bb..7fa11dcce 100644 --- a/xCAT-genesis-builder/xCAT-genesis-base.spec +++ b/xCAT-genesis-builder/xCAT-genesis-base.spec @@ -46,7 +46,7 @@ BuildRequires: chrony BuildRequires: cpio BuildRequires: e2fsprogs BuildRequires: hostname -%if "%{_target_cpu}" == "x86_64" +%if "%{tarch}" == "x86_64" BuildRequires: dmidecode BuildRequires: efibootmgr %endif @@ -79,6 +79,9 @@ BuildRequires: nfs-utils BuildRequires: nmap-ncat BuildRequires: openssh-clients BuildRequires: openssh-server +# getcert, getdestiny, getipmi and getadapter run the openssl command. el8 and el9 hold it in +# the build root as a dependency of another package; el10 does not. +BuildRequires: openssl BuildRequires: parted BuildRequires: pciutils BuildRequires: perl @@ -134,9 +137,6 @@ rm -rf "$DRACUTMODDIR" mkdir -p "$DRACUTMODDIR" cp -a "%{_builddir}/xCAT-genesis-base-build-support/dracut_105/el/." "$DRACUTMODDIR/" chmod 0755 "$DRACUTMODDIR/module-setup.sh" "$DRACUTMODDIR/xcatroot" "$DRACUTMODDIR/dhclient-script" -if [ "%{_target_cpu}" != "x86_64" ]; then - sed -i '/efibootmgr dmidecode/d' "$DRACUTMODDIR/module-setup.sh" -fi KERNELVERSION=$(ls -1 /lib/modules | sort -V | tail -n 1) test -n "$KERNELVERSION" @@ -243,6 +243,7 @@ GENESIS_REQUIRED="usr/sbin/dhclient" GENESIS_REQUIRED="usr/sbin/dhcpcd" %endif bash "%{_builddir}/xCAT-genesis-base-build-support/verify-genesis-payload" \ + --commands-from "$DRACUTMODDIR/module-setup.sh" \ "$GENESIS_FS" $GENESIS_REQUIRED find "$GENESIS_TMPDIR" -type c -delete diff --git a/xCAT-genesis-scripts/usr/bin/getcert b/xCAT-genesis-scripts/usr/bin/getcert index cf4cf1b07..7bad27285 100755 --- a/xCAT-genesis-scripts/usr/bin/getcert +++ b/xCAT-genesis-scripts/usr/bin/getcert @@ -4,8 +4,27 @@ CREDPID=$! if [ -z "$XCATDEST" ]; then XCATDEST=$1 fi +# doxcat runs getcert in the foreground and ignores its status, so a wait with no bound stops +# the boot and prints nothing. +give_up() { + logger -s -t xcat -p local4.err "getcert: $1" + kill $CREDPID + exit 1 +} + +if ! command -v openssl > /dev/null 2>&1; then + give_up "this Genesis image carries no openssl, so no certificate is requested" +fi + #retry in case certkey.pem is not right, yet +# doxcat writes /etc/xcat/certkey.pem in the background with a 4096 bit key, so the first +# requests fail. An emulated node needs minutes for that key. +CSR_TIMEOUT=${GETCERT_CSR_TIMEOUT:-600} +CSR_DEADLINE=$((SECONDS + CSR_TIMEOUT)) while ! openssl req -new -key /etc/xcat/certkey.pem -out /tmp/tls.csr -subj "/CN=$(hostname)" >& /dev/null; do + if [ "$SECONDS" -ge "$CSR_DEADLINE" ]; then + give_up "no certificate request after ${CSR_TIMEOUT}s; /etc/xcat/certkey.pem is not usable" + fi sleep 1 done echo "