mirror of
https://github.com/xcat2/xcat-core.git
synced 2026-09-30 14:55:16 +00:00
b5bd2e4657
dracut copies the kernel, the kernel modules and every command out of the root it runs in. The Ubuntu Genesis deb was built once, on the build host, so every Ubuntu release got the build host's kernel. Nothing called the builder at all: the pipelines converted the EL rpm with alien instead. builddebs.pl gains --genesis, --genesis-only and --genesis-dist. The Genesis deb is now built once per codename inside that codename's <codename>-<arch>-sbuild chroot, the chroots xcat-dep's sbuild-all.pl already creates on the Ubuntu build host. builddeb-genesis-base takes --expect-codename and stops when the root it woke up in is a different release, so a build on the build host cannot produce a codename's image. builddebs.pl reads the build log through XCAT::BuildUtils::genesis_log_errors and fails the build on FAILED:, a package apt cannot find and four more lines that a zero exit status hides. The extracted payload goes through verify-genesis-payload with the command list read back from the dracut module, plus the DHCP client, the 97xcat hooks and a /lib/modules that holds this chroot's kernel and no other. The build root gains isc-dhcp-client, ifenslave and util-linux-extra, which supply dhclient, ifenslave and hwclock. genesis_deb_per_codename.t, genesis_payload_verification.t and genesis_ubuntu_build_root.t fail without this change. Signed-off-by: Daniel Hilst <392820+dhilst@users.noreply.github.com>
123 lines
4.2 KiB
Bash
Executable File
123 lines
4.2 KiB
Bash
Executable File
#!/bin/bash
|
|
#
|
|
# 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. 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 given on the command line are relative to <payload-root>. --commands-from reads back
|
|
# what the dracut module installs: a bare command name is looked for in the four binary
|
|
# directories, an absolute path under <payload-root> itself. 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
|
|
exit 2
|
|
fi
|
|
shift
|
|
|
|
missing=""
|
|
|
|
# have PATH: true when the payload carries PATH as a file, following the usr-merge symlinks
|
|
# the image ships (/sbin -> usr/sbin).
|
|
have() {
|
|
[ -e "$payload/$1" ]
|
|
}
|
|
|
|
require() {
|
|
local path=$1 why=$2
|
|
have "$path" || missing="$missing
|
|
$path ($why)"
|
|
}
|
|
|
|
for path in "$@"; do
|
|
require "$path" "required by the build"
|
|
done
|
|
|
|
# The dracut module names every command and every data file Genesis needs. A name 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 want in $commands; do
|
|
case "$want" in
|
|
# dracut_install installs an absolute path at that same path, so read it back
|
|
# under the payload root. Dropping these let an image with no /usr/bin/awk pass.
|
|
/*) have "${want#/}" || missing="$missing
|
|
$want (installed by $commands_from)"
|
|
;;
|
|
*) have "bin/$want" || have "sbin/$want" \
|
|
|| have "usr/bin/$want" || have "usr/sbin/$want" \
|
|
|| missing="$missing
|
|
$want (installed by $commands_from)"
|
|
;;
|
|
esac
|
|
done
|
|
fi
|
|
|
|
require usr/sbin/sshd "Genesis is reached over ssh"
|
|
require usr/bin/mktemp "getdestiny makes its request file with it"
|
|
|
|
# OpenSSH 9.8 split the per-connection work into sshd-session, which sshd execs by absolute
|
|
# path. EL9 carries OpenSSH 9.9, so an image with sshd alone refuses every connection.
|
|
if have usr/sbin/sshd && grep -qa 'sshd-session' "$payload/usr/sbin/sshd" 2>/dev/null; then
|
|
if ! have usr/libexec/openssh/sshd-session && ! have usr/lib/openssh/sshd-session; then
|
|
missing="$missing
|
|
usr/libexec/openssh/sshd-session (this sshd execs it for every connection)"
|
|
fi
|
|
fi
|
|
|
|
# tmux exits under the C locale. The hook falls back to running doxcat directly, so this is
|
|
# not fatal to booting, but a Genesis shell without tmux loses the console attach.
|
|
if have usr/bin/tmux && ! have usr/lib/locale/C.utf8/LC_CTYPE; then
|
|
missing="$missing
|
|
usr/lib/locale/C.utf8/LC_CTYPE (tmux refuses to start without a UTF-8 locale)"
|
|
fi
|
|
|
|
if [ -n "$missing" ]; then
|
|
echo "verify-genesis-payload: $payload is incomplete:$missing" >&2
|
|
exit 1
|
|
fi
|
|
|
|
echo "verify-genesis-payload: $payload is complete"
|
|
exit 0
|