2
0
mirror of https://github.com/xcat2/xcat-core.git synced 2026-09-25 09:14:05 +00:00

fix(xcat-core): the Genesis build root is missing nine commands the image needs

The first native build stopped on the payload lint. The Ubuntu dracut module
installs ping, nc, nslookup, sfdisk, mkfs.btrfs, usb.ids, poweroff, reboot and
shutdown unconditionally, and no package in the build root supplies any of them.
dracut reported each one with a FAILED: line and exited 0, which is how the image
that shipped without dhclient was packaged. Add iputils-ping, netcat-openbsd,
fdisk, btrfs-progs, hwdata and systemd-sysv.

Two names change between releases. util-linux-extra appeared in 23.04, so the
jammy build stopped with "E: Unable to locate package util-linux-extra" where
hwclock is still in util-linux; bind9-dnsutils replaced dnsutils in 22.04.
add_first_available installs the first name apt knows and stops the build when a
release carries none of them.

dch reads debian/control from the working directory, not from the file it writes,
so the build directory has to be the working directory before it runs.

Signed-off-by: Daniel Hilst <392820+dhilst@users.noreply.github.com>
This commit is contained in:
Daniel Hilst
2026-09-12 08:56:11 -03:00
parent b5bd2e4657
commit 4bbed9e184
2 changed files with 42 additions and 13 deletions
+23 -2
View File
@@ -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
+19 -11
View File
@@ -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;
}