2
0
mirror of https://github.com/xcat2/xcat-core.git synced 2026-09-09 05:00:44 +00:00
Files
xcat-core/xCAT-test/unit/debian_subiquity_boot_params.t
T
Daniel Hilst 173cbea550 test(subiquity): three values the Ubuntu install path accepts and cannot use
The Subiquity diskful path builds three values from configuration, and nothing
checks that the value it builds is one the consumer can use.

The boot flip addresses port 3002. xcatd's install monitor listens on
site.xcatiport, so a cluster that moves the port loses the flip and every node
PXE-loops. The exchange also counts any reply as an accepted request, so a
different service on that port reads as a flipped node. xcatd greets with
"ready" and answers every request with "done".

subiquity_nfsroot_server resolves the install server without a family. A
dual-stack management node answers with its IPv6 address, and nfsroot=<v6>:<path>
is unparseable, because klibc nfsmount takes everything after the first colon as
the path.

The DNS setup writes the xcatmaster name as a nameserver when getent fails,
which is the case the step exists to prevent.

ubuntu_subiquity_boot_flip.t drives the template's own late-command against a
stand-in monitor. ubuntu_resolvconf_ip.t runs the DNS step and reads the file it
writes. debian_subiquity_boot_params.t drives the helpers with a dual-stack
resolver. All three fail on this commit.

Signed-off-by: Daniel Hilst <392820+dhilst@users.noreply.github.com>
2026-09-03 14:44:17 -03:00

115 lines
5.1 KiB
Perl

#!/usr/bin/env perl
use strict;
use warnings;
use File::Spec;
use FindBin;
use Test::More;
# Regression: the helpers were covered and the call site was not.
#
# subiquity_nfsroot_server and subiquity_kcmdline each had tests, but reverting the CALL SITE in
# mkinstall -- putting `xCAT::NetworkUtils->getipaddr($instserver)` back in place of
# subiquity_nfsroot_server, i.e. the exact regression the fix removes -- left the whole unit
# suite green. A helper can be perfectly covered while nothing connects it to production.
#
# mkinstall needs a management node, so the composition it performs (resolve the install server,
# then build the command line, or explain why not) lives in subiquity_boot_params, which takes
# its inputs and returns an answer. The caller keeps report_node_error and the loop's `next`.
my $repo_root = File::Spec->rel2abs(
File::Spec->catdir( $FindBin::Bin, '..', '..' )
);
my $plugin = File::Spec->catfile(
$repo_root, 'xCAT-server', 'lib', 'xcat', 'plugins', 'debian.pm'
);
plan skip_all => "debian.pm not found" unless -f $plugin;
my $src = do { local $/; open my $fh, '<', $plugin or die $!; <$fh> };
# BAIL_OUT rather than skip, so a rename fails loudly instead of silently covering nothing.
my $body = '';
for my $name (qw(subiquity_nfsroot_server subiquity_kcmdline subiquity_boot_params)) {
my ($sub) = $src =~ /\n(sub \Q$name\E \{.*?\n\})\n/s;
BAIL_OUT("could not extract $name from debian.pm") unless defined $sub;
$body .= "$sub\n";
}
# Stand in for the module the routine falls back to when no resolver is injected. Without this
# a call site that bypassed the injected resolver would die on a missing module -- a red, but
# for the wrong reason. With it, bypassing the resolver produces the WRONG ANSWER instead of an
# exception, which is what the assertions below are meant to catch.
{
package xCAT::NetworkUtils;
sub getipaddr { return undef }
}
{
package T;
eval "$body; 1" or main::BAIL_OUT("could not eval the subiquity helpers: $@");
}
my $resolver = sub { $_[0] eq 'mn.cluster' ? '10.0.0.1' : undef };
# The regression this exists to catch: an unset noderes.xcatmaster gives '!myipfn!', and the
# boot config must still be produced with the placeholder intact, because pxe.pm and grub2.pm
# substitute it with an address when they write the config.
{
my ($kcmdline, $err) = T::subiquity_boot_params(
'nofb utf8 auto xcatd=!myipfn!', '!myipfn!',
'/install/ubuntu24.04/x86_64', '80', 'cn1', $resolver );
ok( !defined $err, 'a node with no xcatmaster still gets a boot config' )
or diag("error was: $err");
like( $kcmdline, qr/nfsroot=!myipfn!:/,
'and nfsroot keeps the placeholder for pxe.pm/grub2.pm to substitute' );
like( $kcmdline, qr/boot=casper/, 'the casper boot flag survives the composition' );
}
# A resolvable name still becomes an address, because klibc's nfsmount has no resolver.
{
my ($kcmdline, $err) = T::subiquity_boot_params(
'nofb utf8 auto xcatd=mn.cluster', 'mn.cluster',
'/install/ubuntu24.04/x86_64', '80', 'cn1', $resolver );
ok( !defined $err, 'a resolvable install server produces a boot config' );
like( $kcmdline, qr{nfsroot=10\.0\.0\.1:/install/ubuntu24\.04/x86_64},
'and nfsroot carries the address, not the name' );
like( $kcmdline, qr{ds=nocloud-net;s=http://mn\.cluster:80/},
'while the cloud-init seed URL keeps the name, where DNS works' );
}
# A dual-stack management node has both an A and an AAAA record, and getipaddr answers with
# whichever the resolver returns first. casper mounts the live filesystem with klibc's nfsmount,
# which takes an IPv4 address, and it takes everything after the first colon in nfsroot= as the
# path -- so an IPv6 address there is not a slower path, it is an unparseable one. This install
# asks for ip=dhcp, so the address must be IPv4.
{
no warnings 'redefine';
local *xCAT::NetworkUtils::getipaddr = sub {
my ($class, $host, %opt) = @_;
return $opt{OnlyV4} ? '10.0.0.1' : '2001:db8::1';
};
my ($kcmdline, $err) = T::subiquity_boot_params(
'nofb utf8 auto xcatd=mn.cluster', 'mn.cluster',
'/install/ubuntu24.04/x86_64', '80', 'cn1' );
ok( !defined $err, 'a dual-stack install server produces a boot config' )
or diag("error was: $err");
like( $kcmdline, qr{nfsroot=10\.0\.0\.1:/install/ubuntu24\.04/x86_64},
'and nfsroot carries the IPv4 address of the install server' );
unlike( $kcmdline, qr/nfsroot=[^ ]*::/,
'never the IPv6 address, which klibc nfsmount cannot use' );
}
# The guard the original commit added must survive: a name that does not resolve is an error,
# not a command line with a name in nfsroot.
{
my ($kcmdline, $err) = T::subiquity_boot_params(
'nofb utf8 auto xcatd=nosuchhost', 'nosuchhost',
'/install/ubuntu24.04/x86_64', '80', 'cn1', $resolver );
ok( !defined $kcmdline, 'an unresolvable install server yields no boot config' );
like( $err, qr/nosuchhost/, 'and the error names the server that failed' );
like( $err, qr/klibc|nfsmount|address/i, 'and says why it matters' );
}
done_testing();