diff --git a/xCAT-genesis-builder/builddeb-genesis-base b/xCAT-genesis-builder/builddeb-genesis-base index a6af7e9b1..e1c550ebd 100755 --- a/xCAT-genesis-builder/builddeb-genesis-base +++ b/xCAT-genesis-builder/builddeb-genesis-base @@ -80,7 +80,8 @@ REQUIRED_PACKAGES=" nfs-common rpcbind pciutils usbutils parted dosfstools e2fsprogs lvm2 mdadm net-tools bc psmisc rsync wget cpio - isc-dhcp-client ifenslave util-linux-extra + isc-dhcp-client ifenslave + systemd-sysv hwdata btrfs-progs netcat-openbsd iputils-ping fdisk dpkg-dev debhelper fakeroot devscripts vim-tiny " if [ "$BUILDARCH" = "amd64" ]; then @@ -89,6 +90,24 @@ fi echo "Installing build dependencies..." apt-get update -qq + +# Two commands the image needs changed package between releases: nslookup left dnsutils for +# bind9-dnsutils in 22.04, and hwclock left util-linux for util-linux-extra in 23.04. Ask apt +# which name this release carries rather than branch on the codename. +add_first_available() { + local p + for p in "$@"; do + if apt-cache show "$p" >/dev/null 2>&1; then + REQUIRED_PACKAGES="$REQUIRED_PACKAGES $p" + return 0 + fi + done + echo "ERROR: $CODENAME carries none of these packages: $*" >&2 + exit 1 +} +add_first_available bind9-dnsutils dnsutils +add_first_available util-linux-extra util-linux + apt-get install -y --no-install-recommends $REQUIRED_PACKAGES # dpkg-architecture comes from dpkg-dev, which the line above installs. @@ -237,6 +256,9 @@ 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" \ @@ -245,7 +267,6 @@ dch --create --package "xcat-genesis-base-$BUILDARCH" \ "Native Ubuntu build on $CODENAME $BUILDARCH" echo "Building .deb package..." -cd "$DIR" dpkg-buildpackage -rfakeroot -uc -us -b if [ -n "$outdir" ]; then diff --git a/xCAT-test/unit/genesis_ubuntu_build_root.t b/xCAT-test/unit/genesis_ubuntu_build_root.t index 1d87f7e63..4510cac3f 100755 --- a/xCAT-test/unit/genesis_ubuntu_build_root.t +++ b/xCAT-test/unit/genesis_ubuntu_build_root.t @@ -24,21 +24,25 @@ plan skip_all => 'ubuntu module-setup.sh not found' unless -f $module; plan tests => 9; # Commands the Ubuntu dracut module marks mandatory that a minimal Ubuntu server root does -# NOT already provide, and the package that supplies each one. Every entry here has to be in -# REQUIRED_PACKAGES or the image ships without the command. -my %PACKAGE_FOR = ( - dhclient => 'isc-dhcp-client', - ifenslave => 'ifenslave', - hwclock => 'util-linux-extra', +# NOT already provide, and the packages that supply each one. Every command here needs one of +# its packages in the build root or the image ships without it. hwclock has two names because +# it left util-linux for util-linux-extra in 23.04, and the build root asks apt which name the +# release it is building for carries. +my %PACKAGES_FOR = ( + dhclient => ['isc-dhcp-client'], + ifenslave => ['ifenslave'], + hwclock => [ 'util-linux-extra', 'util-linux' ], ); my %mandatory = map { $_ => 1 } mandatory_commands($module); my @packages = required_packages($builder); -for my $command (sort keys %PACKAGE_FOR) { +for my $command (sort keys %PACKAGES_FOR) { + my @provider = @{ $PACKAGES_FOR{$command} }; ok($mandatory{$command}, "the Ubuntu dracut module installs '$command' unconditionally"); - ok(scalar(grep { $_ eq $PACKAGE_FOR{$command} } @packages), - "the build root installs $PACKAGE_FOR{$command}, which provides '$command'"); + my @named = grep { my $p = $_; grep { $_ eq $p } @packages } @provider; + ok(scalar @named, + "the build root installs @{[ join ' or ', @provider ]}, which provides '$command'"); } # doxcat asks dhclient for the provisioning lease. An image without it never gets an address, @@ -85,8 +89,10 @@ BASH return @names; } -# required_packages($path): extract the REQUIRED_PACKAGES assignment from the build script and -# evaluate it, so the list comes from the value the script actually uses. +# required_packages($path): the packages the build root installs. The fixed list is the +# REQUIRED_PACKAGES assignment, evaluated so the value comes from the script itself; a command +# whose package name changed between releases is added by add_first_available, whose candidates +# count too -- the script picks whichever one apt knows. sub required_packages { my ($path) = @_; my $text = do { open my $fh, '<', $path or die "$path: $!"; local $/; <$fh> }; @@ -95,5 +101,7 @@ sub required_packages { my $out = qx{bash -c 'set -u; $block; printf "%s\\n" \$REQUIRED_PACKAGES' 2>/dev/null}; my @packages = grep { length } split /\s+/, ($out // ''); BAIL_OUT("REQUIRED_PACKAGES in $path evaluated to nothing") unless @packages; + push @packages, grep { length } split /\s+/, $1 + while $text =~ /^add_first_available\s+(.+)$/mg; return @packages; }