diff --git a/builddebs.pl b/builddebs.pl index 7f9ce1062..eb6576b80 100755 --- a/builddebs.pl +++ b/builddebs.pl @@ -293,6 +293,11 @@ sub collect_debs { # (--sbuild). They hand out disposable overlay sessions, so what the build # installs is discarded and the next codename starts from the pristine base. +# Where the build runs inside the chroot. A directory of its own at the chroot root, because +# every other candidate is shared: /build and /opt/xcat-ci-shared are bind mounts the sbuild +# chroots give to every session. +my $GENESIS_STAGE = '/xcat-genesis-build'; + sub host_deb_arch { my $arch = `dpkg --print-architecture 2>/dev/null` // ''; chomp $arch; @@ -350,24 +355,28 @@ sub build_one_genesis_deb { # The builder needs its own directory, and Version and Release beside it. Copy them # in rather than bind-mount the checkout: the build rewrites debian/control and # debian/changelog, and it must not rewrite them in the tree the pipeline builds from. - sh_or_die("mkdir -p " . sh_quote("$root/build/xCAT-genesis-builder"), + # + # NOT under /build: the sbuild chroots bind-mount /var/lib/sbuild/build there, so every + # session of every chroot shares one directory. Two builds running at once overwrite each + # other's copy of the builder, and the output of an earlier run is still in it. A + # directory of its own at the chroot root lives in the session overlay and goes with it. + my $stage = "$root$GENESIS_STAGE"; + sh_or_die("rm -rf " . sh_quote($stage) . " && mkdir -p " + . sh_quote("$stage/xCAT-genesis-builder"), "FATAL: cannot make the build directory in session:$id\n"); sh_or_die("cp -a " . sh_quote("$ROOT/xCAT-genesis-builder") . "/. " - . sh_quote("$root/build/xCAT-genesis-builder") . "/", + . sh_quote("$stage/xCAT-genesis-builder") . "/", "FATAL: cannot copy xCAT-genesis-builder into session:$id\n"); - for my $f (qw(Version Release)) { - next unless -f "$ROOT/$f"; - copy("$ROOT/$f", "$root/build/$f") - or die "FATAL: cannot copy $f into session:$id: $!\n"; - } - write_text("$root/build/Release", "$RELEASE\n"); + copy("$ROOT/Version", "$stage/Version") + or die "FATAL: cannot copy Version into session:$id: $!\n"; + write_text("$stage/Release", "$RELEASE\n"); # --expect-codename is the guard that keeps the image and the root together: the # builder stops when the root it woke up in is not the release it was asked for. my $cmd = join ' ', 'schroot', '--run-session', '-c', sh_quote("session:$id"), '-u', 'root', '-d', '/', - '--', '/bin/bash', '/build/xCAT-genesis-builder/builddeb-genesis-base', - '--expect-codename', sh_quote($codename), '--outdir', '/build/out'; + '--', '/bin/bash', "$GENESIS_STAGE/xCAT-genesis-builder/builddeb-genesis-base", + '--expect-codename', sh_quote($codename), '--outdir', "$GENESIS_STAGE/out"; my $rc = sh("$cmd > " . sh_quote($logfile) . " 2>&1"); # The log is read whether or not the command failed: a build that exits 0 with @@ -379,7 +388,7 @@ sub build_one_genesis_deb { } die $problems if $problems; - my @debs = glob("$root/build/out/*.deb"); + my @debs = glob("$root$GENESIS_STAGE/out/*.deb"); die "FATAL: the Genesis build for $codename produced no .deb; log: $logfile\n" unless @debs; for my $deb (@debs) { diff --git a/docs/source/developers/guides/code/builds.rst b/docs/source/developers/guides/code/builds.rst index 1146e4225..b1c8fe9d5 100644 --- a/docs/source/developers/guides/code/builds.rst +++ b/docs/source/developers/guides/code/builds.rst @@ -65,6 +65,20 @@ ppc64el, and every release the repository serves declares the architecture; ``xCAT-genesis-scripts`` keeps the two architectures it has control files for, because riscv64 Genesis ships as an OpenEmbedded package instead. +The Genesis image is the exception, and it is off unless it is asked for:: + + ./builddebs.pl --genesis-only --genesis-dist jammy --genesis-dist noble + +``dracut`` copies the kernel, the kernel modules and every command out of the root +it runs in, so the image belongs to the release that built it. ``--genesis`` builds +one image per ``--genesis-dist`` codename inside that codename's +``--sbuild`` schroot -- the chroots xcat-dep's ``sbuild-all.pl`` +creates on the Ubuntu build host -- for the architecture of the build host. It +refuses to run in a root of another release, it fails the build on an error in the +log even when the exit status is 0, and it checks the extracted payload against the +commands the dracut module installs. ``--genesis-only`` builds the images and +nothing else, which is what xcat-dep consumes with ``--genesis-deb``. + Helpers shared by both builders live in ``build-utils/lib/XCAT/BuildUtils.pm``. ``buildcore.sh`` builds the architecture specific packages (``xCAT``, ``xCATsn``, diff --git a/xCAT-genesis-builder/builddeb-genesis-base b/xCAT-genesis-builder/builddeb-genesis-base index 6396754cc..64dab3b3a 100755 --- a/xCAT-genesis-builder/builddeb-genesis-base +++ b/xCAT-genesis-builder/builddeb-genesis-base @@ -105,14 +105,35 @@ add_first_available() { echo "ERROR: $CODENAME carries none of these packages: $*" >&2 exit 1 } +# A package that exists only on some releases. 26.04 moved the backward-compatibility zone +# names (Chile/Continental and the rest of the list the dracut module installs) out of tzdata +# into tzdata-legacy. +add_if_available() { + local p + for p in "$@"; do + apt-cache show "$p" >/dev/null 2>&1 && REQUIRED_PACKAGES="$REQUIRED_PACKAGES $p" + done + return 0 +} + add_first_available bind9-dnsutils dnsutils add_first_available util-linux-extra util-linux +add_if_available tzdata-legacy 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