2
0
mirror of https://github.com/xcat2/xcat-core.git synced 2026-10-22 07:38:08 +00:00
Files
xcat-core/xCAT-genesis-base/builddeb-genesis-base
T
Daniel Hilst c87fec574b Merge master into fix/remove-xcat-genesis-builder
Master merged #7835, which changed the Genesis base files under
xCAT-genesis-builder/, the directory this branch removes. The merge
keeps master's content at this branch's paths:

- GenesisBuildRoot.pm, genesis_payload_verification.t and
  genesis_ubuntu_build_root.t take master's newer versions, pointed at
  xCAT-genesis-base/.
- verify-genesis-payload and GenesisPayload.pm are identical on both
  sides; the copies at the old path are dropped.
- buildrpms.pl keeps stage_genesis_base_sources(), which already stages
  what master added inline.
- builddebs.pl and the new genesis_deb_per_codename.t now use
  xCAT-genesis-base/.

Signed-off-by: Daniel Hilst <392820+dhilst@users.noreply.github.com>
2026-09-24 22:16:30 -03:00

260 lines
9.4 KiB
Bash
Executable File

#!/bin/bash
# Build the xcat-genesis-base .deb for ONE Ubuntu codename.
#
# dracut copies the kernel, the kernel modules and every command out of the root it runs
# in, so this must run inside a root of the target codename. builddebs.pl --genesis starts
# it in that codename's <codename>-<arch>-sbuild chroot, one build per codename.
# --expect-codename is what stops a run on the build host: a single build there gives every
# Ubuntu release the build host's kernel.
#
# Parallel to xCAT-genesis-base.spec, which does the same for EL.
set -euo pipefail
DIR=$(readlink -f "$(dirname "$0")")
OS_RELEASE=${OS_RELEASE:-/etc/os-release}
expect_codename=""
outdir=""
while [ $# -gt 0 ]; do
case "$1" in
--expect-codename) expect_codename=${2:-}; shift 2 ;;
--expect-codename=*) expect_codename=${1#*=}; shift ;;
--outdir) outdir=${2:-}; shift 2 ;;
--outdir=*) outdir=${1#*=}; shift ;;
-h|--help)
echo "usage: builddeb-genesis-base [--expect-codename <codename>] [--outdir <dir>]"
exit 0 ;;
*) echo "ERROR: unknown argument: $1" >&2; exit 2 ;;
esac
done
BUILDARCH=$(dpkg --print-architecture)
case "$BUILDARCH" in
amd64) TARCH=x86_64 ;;
ppc64el) TARCH=ppc64 ;;
*) echo "ERROR: unsupported architecture: $BUILDARCH" >&2; exit 1 ;;
esac
# The Genesis debs carry the architecture in the package name, so the packages an upgrade has
# to displace carry it too. 2.19 renames the ppc64 debs to ppc64el; dpkg keeps the old package,
# and its copy of the same files, unless the new one replaces it by name.
rewrite_control() {
local control=$1 arch=$2 superseded
case "$arch" in
ppc64el) superseded="xcat-genesis-ppc64, xcat-genesis-base-ppc64" ;;
*) superseded="xcat-genesis-$arch" ;;
esac
sed -i -e "s/xcat-genesis-base-amd64/xcat-genesis-base-$arch/g" \
-e "s/xcat-genesis-scripts-amd64/xcat-genesis-scripts-$arch/g" \
-e "s/xcat-genesis-amd64/$superseded/g" "$control"
}
VERSION=$(cat "$DIR/../Version" 2>/dev/null || echo "2.18.0")
RELEASE=$(cat "$DIR/../Release" 2>/dev/null || echo "snap$(date +%Y%m%d%H%M)")
CODENAME=$(. "$OS_RELEASE" && echo "${VERSION_CODENAME:-}")
if [ -z "$CODENAME" ]; then
echo "ERROR: $OS_RELEASE names no VERSION_CODENAME" >&2
exit 1
fi
# The image is only valid for the release whose kernel it carries. Refuse to build a
# codename's image anywhere but in that codename's root.
if [ -n "$expect_codename" ] && [ "$expect_codename" != "$CODENAME" ]; then
echo "ERROR: this root is $CODENAME, not $expect_codename." >&2
echo " The image would carry the $CODENAME kernel and boot under $expect_codename." >&2
exit 1
fi
echo "Building xcat-genesis-base for $BUILDARCH ($TARCH) on Ubuntu $CODENAME"
export DEBIAN_FRONTEND=noninteractive
echo "Installing build dependencies..."
apt-get update -qq
# XCAT::GenesisBuildRoot holds the package list, so the unit tests can call it.
REQUIRED_PACKAGES=$(perl -I"$DIR/lib" -MXCAT::GenesisBuildRoot=required_packages \
-e 'print "$_\n" for required_packages(@ARGV)' "$BUILDARCH" "$CODENAME")
apt-get install -y --no-install-recommends $REQUIRED_PACKAGES
# dpkg-architecture comes from dpkg-dev, which the line above installs.
TRIPLET=$(dpkg-architecture -qDEB_HOST_MULTIARCH)
# ncurses-base put its terminfo entries under /lib/terminfo before 24.04, and both dracut's own
# terminfo module and the 97xcat module ask for /usr/share/terminfo. On jammy the build stopped
# on /usr/share/terminfo/l/linux. Give this build root the path they ask for; the chroot is
# thrown away when the build ends.
if [ -d /lib/terminfo ]; then
mkdir -p /usr/share/terminfo
cp -an /lib/terminfo/. /usr/share/terminfo/ 2>/dev/null || true
fi
# Set up dracut module
if [ -d /usr/lib/dracut/modules.d ]; then
DRACUT_PARENT=/usr/lib/dracut/modules.d
elif [ -d /usr/share/dracut/modules.d ]; then
DRACUT_PARENT=/usr/share/dracut/modules.d
else
echo "ERROR: cannot find dracut modules directory" >&2
exit 1
fi
DRACUTMODDIR=$DRACUT_PARENT/97xcat
GENESIS_TMPDIR=$(mktemp -d /tmp/xcat-genesis-deb.XXXXXX)
GENESIS_ROOT=$GENESIS_TMPDIR/opt/xcat/share/xcat/netboot/genesis/$TARCH
GENESIS_FS=$GENESIS_ROOT/fs
DRACUT_IMAGE=$GENESIS_TMPDIR/genesis.rfs
cleanup() {
rm -rf "$GENESIS_TMPDIR" "$DRACUTMODDIR"
}
trap cleanup EXIT
rm -rf "$DRACUTMODDIR"
mkdir -p "$DRACUTMODDIR"
cp -a "$DIR/dracut_105/ubuntu/." "$DRACUTMODDIR/"
chmod 0755 "$DRACUTMODDIR/module-setup.sh" "$DRACUTMODDIR/xcatroot" "$DRACUTMODDIR/dhclient-script"
if [ "$BUILDARCH" != "amd64" ]; then
sed -i '/efibootmgr dmidecode/d' "$DRACUTMODDIR/module-setup.sh"
fi
# linux-image-generic pulls exactly one kernel into this root, and this root belongs to
# $CODENAME, so this is the target release's kernel.
KERNELVERSION=$(ls -1 /lib/modules | sort -V | tail -n 1)
if [ -z "$KERNELVERSION" ]; then
echo "ERROR: no kernel modules found in /lib/modules" >&2
exit 1
fi
echo "Using kernel $KERNELVERSION"
mkdir -p "$GENESIS_FS/etc/ssh"
mkdir -p /run/rpcbind
echo "Running dracut..."
dracut --compress gzip -m "xcat base" --no-early-microcode -N -f "$DRACUT_IMAGE" "$KERNELVERSION"
echo "Extracting initramfs..."
(cd "$GENESIS_FS" && zcat "$DRACUT_IMAGE" | cpio -dumi)
for script in \
"$GENESIS_FS/sbin/dhclient-script" \
"$GENESIS_FS/usr/sbin/dhclient-script" \
"$GENESIS_FS/sbin/xcatroot"
do
[ -f "$script" ] && chmod 0755 "$script"
done
for perl_dir in \
/usr/share/perl5 \
"/usr/lib/$TRIPLET/perl5" \
/usr/local/share/perl5 \
"/usr/local/lib/$TRIPLET/perl5"
do
if [ -d "$perl_dir" ]; then
echo "Adding perl library $perl_dir"
mkdir -p "$GENESIS_FS$perl_dir"
cp -a "$perl_dir/." "$GENESIS_FS$perl_dir/"
fi
done
mkdir -p "$GENESIS_FS/lib/udev/rules.d"
if [ -e /usr/lib/udev/rules.d/80-net-name-slot.rules ]; then
cp /usr/lib/udev/rules.d/80-net-name-slot.rules "$GENESIS_FS/lib/udev/rules.d/"
elif [ -e /lib/udev/rules.d/80-net-name-slot.rules ]; then
cp /lib/udev/rules.d/80-net-name-slot.rules "$GENESIS_FS/lib/udev/rules.d/"
elif [ -e "$DIR/80-net-name-slot.rules" ]; then
cp "$DIR/80-net-name-slot.rules" "$GENESIS_FS/lib/udev/rules.d/"
fi
KERNEL_IMAGE=/boot/vmlinuz-$KERNELVERSION
if [ ! -e "$KERNEL_IMAGE" ]; then
for candidate in \
"/boot/vmlinux-$KERNELVERSION" \
"/usr/lib/modules/$KERNELVERSION/vmlinuz" \
"/lib/modules/$KERNELVERSION/vmlinuz"
do
if [ -e "$candidate" ]; then
KERNEL_IMAGE="$candidate"
break
fi
done
fi
if [ ! -e "$KERNEL_IMAGE" ]; then
echo "ERROR: cannot find the image of kernel $KERNELVERSION" >&2
exit 1
fi
echo "Adding kernel $KERNEL_IMAGE"
cp "$KERNEL_IMAGE" "$GENESIS_ROOT/kernel"
# dracut_install reports a missing command and returns, so a hole reaches the .deb with
# nothing in the log but one line. Read the commands back from the module and check them
# against the payload, the way xCAT-genesis-base.spec does for EL.
bash "$DIR/verify-genesis-payload" --commands-from "$DRACUTMODDIR/module-setup.sh" "$GENESIS_FS" \
usr/sbin/dhclient bin/sh sbin/xcatroot sbin/dhclient-script etc/rsyslog.conf
# What the verifier cannot know: that this image belongs to this chroot's kernel. An image
# built against another root's /lib/modules boots and then finds no driver for its NIC.
if [ ! -d "$GENESIS_FS/lib/modules/$KERNELVERSION" ]; then
echo "ERROR: the image carries no /lib/modules/$KERNELVERSION" >&2
ls -1 "$GENESIS_FS/lib/modules" 2>/dev/null >&2 || true
exit 1
fi
if [ -z "$(find "$GENESIS_FS/lib/modules/$KERNELVERSION" -name '*.ko*' -print -quit)" ]; then
echo "ERROR: /lib/modules/$KERNELVERSION in the image holds no kernel module" >&2
exit 1
fi
for stray in "$GENESIS_FS"/lib/modules/*; do
[ -d "$stray" ] || continue
if [ "$(basename "$stray")" != "$KERNELVERSION" ]; then
echo "ERROR: the image carries $(basename "$stray"), not the $KERNELVERSION of this root" >&2
exit 1
fi
done
# The 97xcat hooks are what makes the image xCAT's. dracut drops a module whose check()
# fails without a word, and the image then boots to a plain dracut shell.
if [ -z "$(find "$GENESIS_FS" -path '*/hooks/cmdline/*xcat-cmdline.sh' -print -quit)" ]; then
echo "ERROR: the image carries no 97xcat cmdline hook" >&2
exit 1
fi
find "$GENESIS_TMPDIR" -type c -delete
# Stage for dpkg-buildpackage
rm -rf "$DIR/opt"
cp -a "$GENESIS_TMPDIR/opt" "$DIR/"
# Adjust control file for target arch
rewrite_control "$DIR/debian/control" "$BUILDARCH"
# debian/dirs names the image directory, which is the rpm architecture.
echo "/opt/xcat/share/xcat/netboot/genesis/$TARCH/" > "$DIR/debian/dirs"
# dch reads debian/control from the current directory, not from the file it writes.
cd "$DIR"
PKG_VERSION="${VERSION}-${RELEASE}~${CODENAME}"
rm -f "$DIR/debian/changelog"
dch --create --package "xcat-genesis-base-$BUILDARCH" \
--newversion "$PKG_VERSION" --distribution "$CODENAME" \
--controlmaint -c "$DIR/debian/changelog" \
"Native Ubuntu build on $CODENAME $BUILDARCH"
echo "Building .deb package..."
dpkg-buildpackage -rfakeroot -uc -us -b
if [ -n "$outdir" ]; then
mkdir -p "$outdir"
mv "$DIR/../"xcat-genesis-base-*_*.deb "$outdir/"
echo "Build complete. .deb files in $outdir:"
ls -la "$outdir"
else
echo "Build complete. .deb files:"
ls -la "$DIR/../"xcat-genesis-base*.deb 2>/dev/null || echo "Check parent directory for .deb files"
fi