From 1ddb361174b358d390a20d916e0fcb51284aa8a9 Mon Sep 17 00:00:00 2001 From: Daniel Hilst <392820+dhilst@users.noreply.github.com> Date: Mon, 24 Aug 2026 18:15:34 -0300 Subject: [PATCH] test(xcat-core): capture the two Ubuntu 26.04 provisioning blockers Two independent defects stop xCAT working on Ubuntu 26.04 (resolute). bind9 is only a Recommends on the xcat and xcatsn metapackages. xCAT manages the cluster DNS through makedns/named, so a DNS server is essential to a management or a service node -- but a Recommends is installed only while the system's APT recommendation policy asks for it, so nothing guarantees named is on the node. On an Ubuntu 26.04 management node it was not there: no /usr/sbin/named, and makedns failed with "failed to start named". The Ubuntu netboot genimage reduces an osimage's osvers to a debootstrap suite with a bare s/\.\d+$//. That also strips the minor from a two-part osvers -- an initial release with no point-release ISO -- so ubuntu26.04 becomes "26" and debootstrap dies with "E: No such script: /usr/share/debootstrap/scripts/26". It is not 26.04-specific: an initial-release 18.04/20.04/22.04 ISO hits it too. Assert bind9 is a hard Depends on both metapackages, and drive genimage's real codename derivation over a table of osvers. Both fail today. Signed-off-by: Daniel Hilst <392820+dhilst@users.noreply.github.com> --- xCAT-test/unit/ubuntu_bind9_dependency.t | 48 +++++++++++++++++ xCAT-test/unit/ubuntu_genimage_codename.t | 64 +++++++++++++++++++++++ 2 files changed, 112 insertions(+) create mode 100644 xCAT-test/unit/ubuntu_bind9_dependency.t create mode 100644 xCAT-test/unit/ubuntu_genimage_codename.t diff --git a/xCAT-test/unit/ubuntu_bind9_dependency.t b/xCAT-test/unit/ubuntu_bind9_dependency.t new file mode 100644 index 000000000..9f10a249c --- /dev/null +++ b/xCAT-test/unit/ubuntu_bind9_dependency.t @@ -0,0 +1,48 @@ +#!/usr/bin/env perl +use strict; +use warnings; + +use File::Spec; +use FindBin; +use Test::More; + +# Regression: xCAT manages the cluster DNS with `makedns`, which drives named, so a management +# node (and a service node) requires a DNS server as surely as it requires a DHCP backend. +# bind9 was only a Recommends, which is installed only while the system's APT recommendation +# policy asks for it -- nothing guarantees named is on the node. +# +# On an Ubuntu 26.04 management node it was not there: no /usr/sbin/named, `makedns` failed with +# "failed to start named", and provisioning broke before a node was ever deployed. +# +# Make bind9 a hard Depends on both metapackages so the DNS backend is guaranteed regardless of +# that policy, mirroring the existing "isc-dhcp-server | kea" Depends. + +my $repo_root = File::Spec->rel2abs( + File::Spec->catdir( $FindBin::Bin, '..', '..' ) +); + +sub read_file { + my ($filename) = @_; + open( my $fh, '<', $filename ) or die "Unable to read $filename: $!"; + my $content = do { local $/; <$fh> }; + close($fh); + return $content; +} + +foreach my $pkg ( [ 'xCAT', 'xcat' ], [ 'xCATsn', 'xcatsn' ] ) { + my ( $dir, $name ) = @$pkg; + my $control = read_file( File::Spec->catfile( $repo_root, $dir, 'debian', 'control' ) ); + + my ($depends) = $control =~ /^Depends:\s*(.*)$/m; + my ($recommends) = $control =~ /^Recommends:\s*(.*)$/m; + + ok( defined $depends, "$name debian/control has a Depends line" ); + + like( $depends, qr/(?:^|,)\s*bind9\s*(?:,|$)/, + "$name Depends on bind9 (required by makedns, so not a Recommends)" ); + + unlike( $recommends, qr/(?:^|,)\s*bind9\s*(?:,|$)/, + "$name no longer carries bind9 as a Recommends" ); +} + +done_testing(); diff --git a/xCAT-test/unit/ubuntu_genimage_codename.t b/xCAT-test/unit/ubuntu_genimage_codename.t new file mode 100644 index 000000000..f71e25732 --- /dev/null +++ b/xCAT-test/unit/ubuntu_genimage_codename.t @@ -0,0 +1,64 @@ +#!/usr/bin/env perl +use strict; +use warnings; + +use File::Spec; +use FindBin; +use Test::More; + +# Regression: the Ubuntu netboot genimage derives a debootstrap suite from the osimage's +# osvers. It reduced "ubuntu24.04.4" to "24.04" with a bare s/\.\d+$//, which ALSO strips the +# minor from a two-part osvers -- an initial release with no point-release ISO, e.g. +# "ubuntu26.04" -> "26". "26" is not in the codename map and is not a debootstrap suite, so +# the rootimg build dies with: +# +# E: No such script: /usr/share/debootstrap/scripts/26 +# +# Only a trailing THIRD component may be stripped, so 24.04.4 -> 24.04 while 26.04 (and 18.04, +# 20.04, 22.04 from an initial-release ISO) survive intact and reach the codename map. +# +# Driven by the real derivation code: the substitution and the codename map are extracted from +# genimage and evaluated here, so this test tracks the script rather than a copy of it. + +my $repo_root = File::Spec->rel2abs( + File::Spec->catdir( $FindBin::Bin, '..', '..' ) +); + +my $genimage_path = File::Spec->catfile( + $repo_root, 'xCAT-server', 'share', 'xcat', 'netboot', 'ubuntu', 'genimage' +); +plan skip_all => "genimage not found at $genimage_path" unless -f $genimage_path; + +my $src = do { local $/; open my $fh, '<', $genimage_path or die $!; <$fh> }; + +my ($strip) = $src =~ /^\s*(\$codename\s*=~\s*s\/.*?;)\s*(?:#.*)?$/m; +ok( defined $strip, 'found the codename point-release substitution in genimage' ) + or done_testing(), exit; + +my ($map) = $src =~ /^\s*(my\s+%cn\s*=\s*\(.*?\);)\s*$/ms; +ok( defined $map, 'found the codename map in genimage' ) + or done_testing(), exit; + +sub derive { + my ($osver) = @_; + my $codename = $osver; + $codename =~ s/^ubuntu//; + ## no critic + eval "$strip $map \$codename = \$cn{\$codename} if exists \$cn{\$codename}; 1" + or die "failed to evaluate genimage codename derivation: $@"; + ## use critic + return $codename; +} + +is( derive('ubuntu24.04.4'), 'noble', + 'a point release still reduces to its MAJOR.MINOR codename (24.04.4 -> noble)' ); +is( derive('ubuntu26.04'), 'resolute', + 'an initial release keeps its minor and maps to a codename (26.04 -> resolute, not "26")' ); +is( derive('ubuntu20.04'), 'focal', + 'an initial 20.04 osvers is not over-stripped to "20"' ); +is( derive('ubuntu22.04'), 'jammy', + 'an initial 22.04 osvers is not over-stripped to "22"' ); +is( derive('ubuntu18.04'), 'bionic', + 'an initial 18.04 osvers is not over-stripped to "18"' ); + +done_testing();