mirror of
https://github.com/xcat2/xcat-core.git
synced 2026-09-21 16:39:30 +00:00
fix(xcat-core): the el10 Genesis image carries no openssl, so getcert never returns
A compute node that boots the legacy Genesis image built on el10 stops after
"Getting initial certificate --> <mn>:3001". /etc/xcat is empty, getdestiny never runs and
the node reports no destiny, so xcatd leaves nodelist.status at powering-on. On the node,
openssl reports "command not found" and the getcert process stays alive.
xCAT-genesis-base.spec never build-requires openssl. el8 and el9 hold /usr/bin/openssl in
the build root as a dependency of another package, and el10 does not, so dracut_install in
dracut_105/el/module-setup.sh installed nothing and reported nothing. getcert line 8 waits
for openssl with no bound, which turns the missing command into a wait instead of an error.
The spec now build-requires openssl on every release. verify-genesis-payload reads the
command names back from the dracut module with --commands-from and requires each one in the
payload, so the next name the build root does not supply fails the build. getcert reports a
missing openssl and stops, and bounds the wait for /etc/xcat/certkey.pem at 600 seconds,
which is far longer than the background 4096 bit key needs.
The spec read %{_target_cpu} after BuildArch: noarch, where rpm has already set it to
noarch, so the dmidecode and efibootmgr build-requires never applied and a sed deleted their
dracut_install line on every architecture. Every shipped image lacks both. The spec now
reads %{tarch}, and the dracut module installs whichever of the two the build root carries,
because ppc64le packages neither.
xCAT-test/unit/genesis_getcert_missing_openssl.t, genesis_payload_verification.t and
genesis_base_spec_buildrequires.t fail on the test commit before this one.
Signed-off-by: Daniel Hilst <392820+dhilst@users.noreply.github.com>
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -1,16 +1,35 @@
|
||||
#!/bin/bash
|
||||
#
|
||||
# verify-genesis-payload <payload-root> [required-path ...]
|
||||
# verify-genesis-payload [--commands-from <module-setup.sh>] <payload-root> [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 <payload-root>. 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 <payload-root>. --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:-<empty>}" >&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"
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 "<xcatrequest>
|
||||
|
||||
Reference in New Issue
Block a user