From 16eea29daf0c315579c0d8d8f99db44aa7d7265f 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, 20 Aug 2026 16:42:19 -0300 Subject: [PATCH] test(xCAT-test): cover EL riscv64 install media and diskless defaults Pin the riscv64 installer kernel lookup in anaconda.pm and geninitrd.pm, and evaluate the rh/genimage default driver and resolver library blocks for riscv64 and the existing architectures. Add an autotest nodeset case with bogus riscv64 grub2 nodes and a rhels10.99 riscv64 osimage, checking the per-node grub2 files, the grub2.riscv64 loader link and the hex-ip/mac links. --- xCAT-test/autotest/testcase/nodeset/cases1 | 7 ++ .../autotest/testcase/nodeset/functions.sh | 28 +++++- .../nodeset/nodeset_osimage_grub2_riscv64 | 73 +++++++++++++++ xCAT-test/unit/el_riscv64_install_paths.t | 88 +++++++++++++++++++ 4 files changed, 195 insertions(+), 1 deletion(-) create mode 100755 xCAT-test/autotest/testcase/nodeset/nodeset_osimage_grub2_riscv64 create mode 100644 xCAT-test/unit/el_riscv64_install_paths.t diff --git a/xCAT-test/autotest/testcase/nodeset/cases1 b/xCAT-test/autotest/testcase/nodeset/cases1 index 8667e37ae..b3196702d 100644 --- a/xCAT-test/autotest/testcase/nodeset/cases1 +++ b/xCAT-test/autotest/testcase/nodeset/cases1 @@ -26,6 +26,13 @@ cmd:/opt/xcat/share/xcat/tools/autotest/testcase/nodeset/nodeset_osimage_grub2 check:rc==0 end +start:nodeset_osimage_grub2_riscv64 +label:others +description: Verify if `nodeset osimage` perform well for riscv64 nodes booted by grub2 over UEFI when part of nodes in a node range have problem +cmd:/opt/xcat/share/xcat/tools/autotest/testcase/nodeset/nodeset_osimage_grub2_riscv64 +check:rc==0 +end + start:nodeset_osimage_petitboot label:others description: Verify if `nodeset osimage` perform well when part of nodes in a node range have problem. Use petitboot OS loader diff --git a/xCAT-test/autotest/testcase/nodeset/functions.sh b/xCAT-test/autotest/testcase/nodeset/functions.sh index 5476a9411..fbd73fef0 100644 --- a/xCAT-test/autotest/testcase/nodeset/functions.sh +++ b/xCAT-test/autotest/testcase/nodeset/functions.sh @@ -118,6 +118,21 @@ function make_bogus_petitboot_nodes() done } +function make_bogus_riscv64_grub2_nodes() +{ + local i + # riscv64 boots through UEFI and grub2 + for i in {001..005} + do + mkdef -t node -o tz${i} \ + arch=riscv64 cons=ipmi groups=riscv64 mgt=ipmi \ + netboot=grub2 \ + ip=10.99.1.$((10#${i})) \ + mac=e6:d4:d2:3a:ad:0$((10#${i})) \ + profile=compute os=rhels10.99 + done +} + function make_bogus_xnba_nodes() { local i @@ -181,6 +196,16 @@ function make_bogus_x64_osimage() echo blah >/install/rhels6.99/x86_64/images/pxeboot/initrd.img } +function make_bogus_riscv64_osimage() +{ + mkdef "rhels10.99-riscv64-install-compute" \ + -u profile=compute provmethod=install \ + osvers=rhels10.99 osarch=riscv64 + mkdir -p /install/rhels10.99/riscv64/images/pxeboot + echo blah >/install/rhels10.99/riscv64/images/pxeboot/vmlinuz + echo blah >/install/rhels10.99/riscv64/images/pxeboot/initrd.img +} + function destory_bogus_osimages() { local o @@ -188,7 +213,8 @@ function destory_bogus_osimages() rhels7.99-ppc64le-install-compute \ rhels7.99-ppc64-install-compute \ rhels6.99-ppc64-install-compute \ - rhels6.99-x86_64-install-compute + rhels6.99-x86_64-install-compute \ + rhels10.99-riscv64-install-compute do rmdef -t osimage ${o} done diff --git a/xCAT-test/autotest/testcase/nodeset/nodeset_osimage_grub2_riscv64 b/xCAT-test/autotest/testcase/nodeset/nodeset_osimage_grub2_riscv64 new file mode 100755 index 000000000..2dc293615 --- /dev/null +++ b/xCAT-test/autotest/testcase/nodeset/nodeset_osimage_grub2_riscv64 @@ -0,0 +1,73 @@ +#!/bin/bash + +BASE_DIR="${0%/*}" + +! source "${BASE_DIR}/functions.sh" >/dev/null 2>&1 && + echo "File \"${BASE_DIR}/functions.sh\" not found" >&2 && exit 1 + +make_bogus_riscv64_osimage +make_bogus_riscv64_grub2_nodes + +# riscv64 nodes are booted by the grub2.riscv64 UEFI image; provide a bogus +# one when the management node does not ship it so nodeset can link to it +GRUB2_RISCV64="/tftpboot/boot/grub2/grub2.riscv64" +BOGUS_GRUB2_RISCV64="" +if [ ! -e "${GRUB2_RISCV64}" ] +then + mkdir -p "${GRUB2_RISCV64%/*}" + echo blah >"${GRUB2_RISCV64}" + BOGUS_GRUB2_RISCV64="${GRUB2_RISCV64}" +fi + +function custom_cleanup() +{ + destory_bogus_nodes + destory_bogus_osimages + [ -n "${BOGUS_GRUB2_RISCV64}" ] && rm -f "${BOGUS_GRUB2_RISCV64}" +} + +chdef tz002 mac= +chdef tz003 arch= + +NODESET_STDOUT="${TMP_DIR}/nodeset.out" +NODESET_STDERR="${TMP_DIR}/nodeset.err" + +nodeset tz001+4 osimage=rhels10.99-riscv64-install-compute \ + > >(tee "${NODESET_STDOUT}") 2> >(tee "${NODESET_STDERR}") +# Check $? != 0 +[ "$?" -ne "0" ] +exit_if_bad "$?" "nodeset command should exit with non-zero" + +grep 'tz002: .*o MAC address' "${NODESET_STDERR}" +exit_if_bad "$?" "nodeset command error message checking failed" + +# Make sure all other nodes are good +for node in tz001 tz004 tz005 +do + [ -f "/tftpboot/boot/grub2/${node}" ] + exit_if_bad "$?" "file not found /tftpboot/boot/grub2/${node}" + + # the per-node loader link points at the riscv64 grub2 image + [ "$(readlink "/tftpboot/boot/grub2/grub2-${node}")" = "grub2.riscv64" ] + exit_if_bad "$?" "grub2-${node} does not link to grub2.riscv64" + + # the installer kernel and initrd come from images/pxeboot + grep 'vmlinuz' "/tftpboot/boot/grub2/${node}" + exit_if_bad "$?" "installer kernel not found in /tftpboot/boot/grub2/${node}" + grep 'initrd.img' "/tftpboot/boot/grub2/${node}" + exit_if_bad "$?" "installer initrd not found in /tftpboot/boot/grub2/${node}" + + # the riscv64 grub2 image has no linuxefi command + ! grep 'linuxefi' "/tftpboot/boot/grub2/${node}" + exit_if_bad "$?" "linuxefi must not be used for riscv64 in /tftpboot/boot/grub2/${node}" +done + +# the hex ip and mac links nodeset writes shadow the discovery network files +[ -f "/tftpboot/boot/grub2/grub.cfg-0A630101" ] +exit_if_bad "$?" "file not found /tftpboot/boot/grub2/grub.cfg-0A630101" +[ -f "/tftpboot/boot/grub2/grub.cfg-01-e6-d4-d2-3a-ad-01" ] +exit_if_bad "$?" "file not found /tftpboot/boot/grub2/grub.cfg-01-e6-d4-d2-3a-ad-01" + +nodeset tz001+4 offline + +exit 0 diff --git a/xCAT-test/unit/el_riscv64_install_paths.t b/xCAT-test/unit/el_riscv64_install_paths.t new file mode 100644 index 000000000..c204ac238 --- /dev/null +++ b/xCAT-test/unit/el_riscv64_install_paths.t @@ -0,0 +1,88 @@ +#!/usr/bin/env perl +use strict; +use warnings; + +use FindBin; +use File::Spec; +use Test::More; +use lib "$FindBin::Bin/../../perl-xCAT"; +use lib "$FindBin::Bin/../../xCAT-server/lib/perl"; +use lib "$FindBin::Bin/../../xCAT-server/share/xcat/netboot/imgutils"; +use imgutils; + +# EL riscv64 media and diskless images: the installer kernel/initrd live under +# images/pxeboot like x86 and aarch64 media, and riscv64 diskless images need +# their own default network drivers and lib64 resolver libraries. The +# behavior is pinned without running the database-backed plugins: the arch +# conditions are asserted in the shipped source and the resolver block is +# extracted and evaluated directly. + +my $repo_root = File::Spec->catdir( $FindBin::Bin, '..', '..' ); + +sub slurp { + my ($relative) = @_; + my $path = File::Spec->catfile( $repo_root, split( m{/}, $relative ) ); + plan skip_all => "$path not found" unless -r $path; + open( my $fh, '<', $path ) or die "Unable to read $path: $!"; + my $content = do { local $/; <$fh> }; + close($fh); + return $content; +} + +my $anaconda = slurp('xCAT-server/lib/xcat/plugins/anaconda.pm'); +my $geninitrd = slurp('xCAT-server/lib/xcat/plugins/geninitrd.pm'); +my $genimage = slurp('xCAT-server/share/xcat/netboot/rh/genimage'); + +# anaconda.pm: stateful install kernel/initrd discovery +like( + $anaconda, + qr/\( \$arch =~ \/x86\/ or \$arch =~ \/aarch64\/ or \$arch =~ \/riscv64\/ \) and\n\s*\(\n\s*-r "\$pkgdir\/images\/pxeboot\/vmlinuz"/, + 'anaconda looks for riscv64 installer kernels under images/pxeboot like x86 and aarch64', +); +like( + $anaconda, + qr/\/\\\/vmlinuz-\(\.\*\(x86_64\|ppc64\|el\\d\+\|ppc64le\|aarch64\|riscv64\)\)\$\//, + 'driver-disk kernel updates recognise riscv64 kernels', +); + +# geninitrd.pm: diskless installer initrd source +like( + $geninitrd, + qr/if \(\$arch =~ \/x86\/ or \(\$arch =~ \/riscv64\/ and \$osvers !~ \/sles\|suse\/\)\) \{\n\s*if \(\$osvers =~ \/\(\^ol\[0-9\]\.\*\)\|\(centos\.\*\)\|\(alma\.\*\)\|\(rocky\.\*\)\|\(rh\.\*\)\|\(fedora\.\*\)\|\(SL\.\*\)\/\) \{\n\s*\$kernelpath = "\$tftppath\/vmlinuz";\n\s*copy\("\$pkgdir\/images\/pxeboot\/vmlinuz", \$kernelpath\);/, + 'geninitrd copies riscv64 EL kernels from images/pxeboot', +); +like( + $geninitrd, + qr/\$arch =~ \/riscv64\/ and \$osvers !~ \/sles\|suse\//, + 'a SUSE osimage on riscv64 keeps the unsupported-architecture error instead of reading SUSE installer media paths', +); +unlike( + $geninitrd, + qr/\} elsif \(\$arch =~ \/riscv64\/\)/, + 'geninitrd does not need a separate riscv64 branch', +); + +is_deeply( + [ imgutils::default_net_drivers( 'rh', 'riscv64' ) ], + [qw/e1000 e1000e igb ixgbe r8169 tg3 bnx2x mlx5_core virtio_net/], + 'riscv64 diskless images default to virtio, Intel, Realtek, Broadcom and Mellanox drivers', +); + +# rh/genimage: resolver libraries for the boot image +my ($lib_block) = $genimage =~ m{^(\s*if \(\$arch =~ /x86_64/ or \$arch =~ /aarch64/ or \$arch =~ /riscv64/\) \{\n\s*push \@filestoadd, "lib64/libnss_dns\.so\.2";\n.*?^\s*\}\n)}ms; +ok( $lib_block, 'the resolver library block was located in rh/genimage' ) + or BAIL_OUT('rh/genimage no longer matches the expected resolver library block'); + +sub resolver_libs { + my ($arch) = @_; + my $code = "sub { my \$arch = shift; my \@filestoadd;\n$lib_block\n return \@filestoadd; }"; + my $sub = eval $code; ## no critic (BuiltinFunctions::ProhibitStringyEval) + die "Unable to evaluate the resolver library block: $@" if $@; + return [ $sub->($arch) ]; +} + +is_deeply( resolver_libs('riscv64'), [ 'lib64/libnss_dns.so.2', 'lib64/libresolv.so.2' ], 'riscv64 images take the resolver libraries from lib64' ); +is_deeply( resolver_libs('x86_64'), [ 'lib64/libnss_dns.so.2', 'lib64/libresolv.so.2' ], 'x86_64 images still use lib64' ); +is_deeply( resolver_libs('ppc64'), [ 'lib/libnss_dns.so.2', 'lib/libresolv.so.2' ], 'ppc64 images still use lib' ); + +done_testing();