From bf561167325361a4496258d56827096f389c66d2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vin=C3=ADcius=20Ferr=C3=A3o?= <2031761+viniciusferrao@users.noreply.github.com> Date: Thu, 3 Sep 2026 19:07:52 -0300 Subject: [PATCH 1/4] refactor(debian): map media architectures through a shared table copycd translated the architecture the Ubuntu media reports with its own if/elsif chain, and genimage translates the same names back for debootstrap with another one. Neither can be reused, so a new architecture has to be added to both. Put both directions in xCAT::Utils and have copycd read from there. The names and the fallback do not change: media that xCAT has no name for still leave the architecture as the media reported it. --- perl-xCAT/xCAT/Utils.pm | 49 ++++++++++++++++++++++++++ xCAT-server/lib/xcat/plugins/debian.pm | 18 ++-------- 2 files changed, 51 insertions(+), 16 deletions(-) diff --git a/perl-xCAT/xCAT/Utils.pm b/perl-xCAT/xCAT/Utils.pm index 142164f08..838e40bbb 100644 --- a/perl-xCAT/xCAT/Utils.pm +++ b/perl-xCAT/xCAT/Utils.pm @@ -4862,6 +4862,55 @@ sub splitkcmdline { } +################################################################################### +#subroutine debian_arch +#Usage: give the Debian architecture name for an xCAT architecture. The media, the +# package lists and debootstrap all use the Debian name. +#Input Params: +# $arch: the xCAT architecture, for example x86_64 or ppc64le +#Return value: +# the Debian architecture name, or the input when Debian names it the same +################################################################################### +# ppc64le is deliberately absent: the Ubuntu driver table, the NSS libraries and the +# image paths all key on ppc64el, so translating it here alone would build an image +# without network drivers instead of stopping at debootstrap. +my %DEBIAN_ARCH = ( + 'x86_64' => 'amd64', +); + +sub debian_arch { + my $arch = shift; + $arch = shift if ($arch =~ /xCAT::Utils/); + return unless defined $arch; + return $DEBIAN_ARCH{ lc $arch } // $arch; +} + +################################################################################### +#subroutine xcat_arch_from_debian +#Usage: give the xCAT architecture for the architecture the Ubuntu media reports. +#Input Params: +# $darch: the architecture from the media, for example amd64 or ppc64el +#Return value: +# the xCAT architecture, or undef when the media names one xCAT does not know +################################################################################### +my @XCAT_ARCH_FROM_DEBIAN = ( + [ qr/^i.86$/ => 'x86' ], + [ qr/^ppc64el$/ => 'ppc64el' ], + [ qr/ppc|powerpc/ => 'ppc64' ], + [ qr/^amd64$/ => 'x86_64' ], +); + +sub xcat_arch_from_debian { + my $darch = shift; + $darch = shift if ($darch =~ /xCAT::Utils/); + return unless defined $darch and $darch ne ''; + foreach my $rule (@XCAT_ARCH_FROM_DEBIAN) { + my ($pattern, $arch) = @{$rule}; + return $arch if $darch =~ $pattern; + } + return; +} + ################################################################################### #subroutine lookupNetboot #Usage: determine the possible noderes.netboot values of the osimage diff --git a/xCAT-server/lib/xcat/plugins/debian.pm b/xCAT-server/lib/xcat/plugins/debian.pm index fbae0f344..7f98fdf7e 100644 --- a/xCAT-server/lib/xcat/plugins/debian.pm +++ b/xCAT-server/lib/xcat/plugins/debian.pm @@ -368,22 +368,8 @@ sub copycd # So that I can use amd64 below my $debarch = $darch; - if ($darch and $darch =~ /i.86/) - { - $darch = "x86"; - } - elsif ($darch and $darch =~ /ppc64el/) - { - $darch = "ppc64el"; - } - elsif ($darch and ($darch =~ /ppc/ or $darch =~ /powerpc/)) - { - $darch = "ppc64"; - } - elsif ($darch and $darch =~ /amd64/) - { - $darch = "x86_64"; - } + my $mapped = xCAT::Utils->xcat_arch_from_debian($darch); + $darch = $mapped if $mapped; if ($darch) { From e982e161810000734483dccd1c5c5dcd413e49a0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vin=C3=ADcius=20Ferr=C3=A3o?= <2031761+viniciusferrao@users.noreply.github.com> Date: Thu, 3 Sep 2026 19:10:47 -0300 Subject: [PATCH 2/4] test(xCAT-test): cover the Debian architecture mapping Pin both directions for every architecture xCAT supports on Ubuntu, the pass-through for names Debian shares, and the round trip that copycd and debootstrap depend on agreeing about. --- xCAT-test/unit/debian_arch_map.t | 52 ++++++++++++++++++++++++++++++++ 1 file changed, 52 insertions(+) create mode 100644 xCAT-test/unit/debian_arch_map.t diff --git a/xCAT-test/unit/debian_arch_map.t b/xCAT-test/unit/debian_arch_map.t new file mode 100644 index 000000000..617004a43 --- /dev/null +++ b/xCAT-test/unit/debian_arch_map.t @@ -0,0 +1,52 @@ +#!/usr/bin/env perl +use strict; +use warnings; + +use FindBin; +use Test::More; + +# Debian, xCAT and the kernel each name the same architecture differently. copycd reads the +# name from the media and genimage gives debootstrap the Debian one, so both directions have +# to agree on every architecture xCAT supports. + +use lib "$FindBin::Bin/../lib"; +use lib "$FindBin::Bin/../../perl-xCAT"; +use xCAT::Utils; + +# --- what debootstrap and the package lists are given ---------------------- +is(xCAT::Utils->debian_arch('x86_64'), 'amd64', + 'Debian calls x86_64 amd64'); +is(xCAT::Utils->debian_arch('ppc64el'), 'ppc64el', + 'the Debian name for POWER LE is unchanged'); +is(xCAT::Utils->debian_arch('ppc64le'), 'ppc64le', + 'the POWER LE alias is left alone, because only ppc64el reaches the driver table'); +is(xCAT::Utils->debian_arch('s390x'), 's390x', + 'an architecture Debian names the same is passed through'); +is(xCAT::Utils->debian_arch('ppc64'), 'ppc64', + 'POWER BE is passed through'); +is(xCAT::Utils->debian_arch(undef), undef, + 'no architecture resolves to nothing'); + +# --- what copycd reads from the media -------------------------------------- +is(xCAT::Utils->xcat_arch_from_debian('amd64'), 'x86_64', + 'amd64 media installs x86_64 nodes'); +is(xCAT::Utils->xcat_arch_from_debian('i386'), 'x86', + 'i386 media installs x86 nodes'); +is(xCAT::Utils->xcat_arch_from_debian('i686'), 'x86', + 'every 32-bit x86 spelling installs x86 nodes'); +is(xCAT::Utils->xcat_arch_from_debian('ppc64el'), 'ppc64el', + 'POWER LE media keeps the Debian name xCAT uses for Ubuntu'); +is(xCAT::Utils->xcat_arch_from_debian('powerpc'), 'ppc64', + 'POWER BE media installs ppc64 nodes'); +is(xCAT::Utils->xcat_arch_from_debian('nonesuch'), undef, + 'media xCAT has no name for resolves to nothing'); +is(xCAT::Utils->xcat_arch_from_debian(''), undef, + 'media with no architecture resolves to nothing'); + +# --- the two directions agree ---------------------------------------------- +foreach my $arch (qw(x86_64 ppc64el)) { + is(xCAT::Utils->xcat_arch_from_debian(xCAT::Utils->debian_arch($arch)), $arch, + "$arch survives a round trip through both directions"); +} + +done_testing(); From 1efeef489570b6344c50d915caa509ff784ef4fd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vin=C3=ADcius=20Ferr=C3=A3o?= <2031761+viniciusferrao@users.noreply.github.com> Date: Thu, 3 Sep 2026 19:12:02 -0300 Subject: [PATCH 3/4] refactor(genimage): take the debootstrap architecture from the shared mapping genimage translated one architecture for debootstrap, x86_64 to amd64, and compared against a bareword rather than a string, which only resolves because the script does not enable strict subs. Read the name from xCAT::Utils, which genimage already loads. Every architecture reaches debootstrap with the name it does today. --- xCAT-server/share/xcat/netboot/ubuntu/genimage | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/xCAT-server/share/xcat/netboot/ubuntu/genimage b/xCAT-server/share/xcat/netboot/ubuntu/genimage index 2f2b6995b..475d9ae00 100755 --- a/xCAT-server/share/xcat/netboot/ubuntu/genimage +++ b/xCAT-server/share/xcat/netboot/ubuntu/genimage @@ -215,8 +215,7 @@ foreach (@ndrivers, @default_ndrivers) { } } -my $uarch = $arch; -$uarch = "amd64" if ($arch eq x86_64); +my $uarch = xCAT::Utils->debian_arch($arch); unless ($onlyinitrd) { From ca2aec5397233926ebb2984c4e10391b6d976da6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vin=C3=ADcius=20Ferr=C3=A3o?= <2031761+viniciusferrao@users.noreply.github.com> Date: Thu, 3 Sep 2026 19:12:24 -0300 Subject: [PATCH 4/4] test(xCAT-test): cover the debootstrap architecture genimage passes Drive the assignment genimage makes and check the name debootstrap receives for each architecture, including the POWER LE spelling that debootstrap rejects. --- .../unit/ubuntu_genimage_debootstrap_arch.t | 44 +++++++++++++++++++ 1 file changed, 44 insertions(+) create mode 100644 xCAT-test/unit/ubuntu_genimage_debootstrap_arch.t diff --git a/xCAT-test/unit/ubuntu_genimage_debootstrap_arch.t b/xCAT-test/unit/ubuntu_genimage_debootstrap_arch.t new file mode 100644 index 000000000..f47341864 --- /dev/null +++ b/xCAT-test/unit/ubuntu_genimage_debootstrap_arch.t @@ -0,0 +1,44 @@ +#!/usr/bin/env perl +use strict; +use warnings; + +use File::Spec; +use FindBin; +use Test::More; + +# debootstrap takes the Debian architecture name, which differs from the name xCAT uses for +# the node. Drive the assignment genimage makes and check the name it computes. The +# invocation that consumes it is not exercised here. + +use lib "$FindBin::Bin/../lib"; +use lib "$FindBin::Bin/../../perl-xCAT"; +use xCAT::Utils; + +my $repo_root = File::Spec->rel2abs(File::Spec->catdir($FindBin::Bin, '..', '..')); +my $genimage = File::Spec->catfile( + $repo_root, 'xCAT-server', 'share', 'xcat', 'netboot', 'ubuntu', 'genimage'); +plan skip_all => "genimage not found at $genimage" unless -f $genimage; + +my $src = do { local $/; open my $fh, '<', $genimage or die $!; <$fh> }; +# Take every line that assigns $uarch, not just the first: the name has been built in +# more than one statement before, and half of it would look like a different value. +my ($assignment) = $src =~ /^(my \$uarch\b.*?)\n\s*\n/ms; +ok(defined $assignment, 'found the debootstrap architecture assignment in genimage') + or do { done_testing(); exit }; + +sub debootstrap_arch { + my ($arch) = @_; + my $uarch; + my $code = $assignment; + $code =~ s/^my\s+//; + no strict 'subs'; ## the script itself does not enable strict subs + eval "$code 1" or die $@; ## no critic (BuiltinFunctions::ProhibitStringyEval) + return $uarch; +} + +is(debootstrap_arch('x86_64'), 'amd64', 'x86_64 resolves to the Debian name amd64'); +is(debootstrap_arch('ppc64el'), 'ppc64el', 'the Debian spelling of POWER LE is kept'); +is(debootstrap_arch('ppc64le'), 'ppc64le', 'the POWER LE alias is passed through, as it is today'); +is(debootstrap_arch('s390x'), 's390x', 'an architecture Debian names the same is passed through'); + +done_testing();