2
0
mirror of https://github.com/xcat2/xcat-core.git synced 2026-10-22 07:38:08 +00:00

test(http): characterize port defaults at boot URL callers

This commit is contained in:
Vinícius Ferrão
2026-10-08 16:25:39 -03:00
parent 937f6895f0
commit 93b87ba063
7 changed files with 228 additions and 8 deletions
+27
View File
@@ -0,0 +1,27 @@
#!/usr/bin/env bats
setup()
{
[ "$(uname -s)" = Linux ] || skip 'DHCP rendering requires Linux namespaces'
}
@test "ISC subnet and node callers preserve their HTTP port defaults" {
[ -n "$BATS_TEST_TMPDIR" ] || return 1
for port in null '""' 0 '"0"' '"80"' '"080"' '"8080"'; do
fixture=$(mktemp -d "$BATS_TEST_TMPDIR/isc.XXXXXX")
mkdir -p "$fixture/etc/sysconfig" "$fixture/tftp" "$fixture/config"
printf 'DHCPDARGS=""\n' > "$fixture/etc/sysconfig/dhcpd"
run bwrap --die-with-parent --unshare-net --ro-bind / / --dev /dev --proc /proc \
--tmpfs /tmp --ro-bind "$BATS_TEST_DIRNAME/../.." /tmp/source \
--bind "$fixture" /tmp/fixture --bind "$fixture/etc" /etc --chdir /tmp/fixture \
perl /tmp/source/xCAT-test/bats/fixtures/dhcp-http.pl "$port"
[ "$status" -eq 0 ] || { printf '%s\n' "$output"; return 1; }
case "$port" in
'"080"') suffix=:080 ;;
'"8080"') suffix=:8080 ;;
*) suffix= ;;
esac
grep -Fq "option cumulus-provision-url \"http://192.0.2.1$suffix/install/postscripts/cumulusztp\";" "$fixture/dhcpd.conf"
grep -Fq "http://192.0.2.1$suffix/tftpboot/petitboot/cn1" "$fixture/omshell"
done
}
+78
View File
@@ -0,0 +1,78 @@
use strict;
use warnings;
## no critic (Modules::RequireFilenameMatchesPackage)
use FindBin;
use lib "$FindBin::Bin/../../../perl-xCAT";
use lib "$FindBin::Bin/../../../xCAT-server/lib/perl";
use File::Path qw(make_path);
use JSON ();
BEGIN {
*CORE::GLOBAL::readpipe = sub { return '' if $_[0] eq 'ip -6 route'; die "Unexpected command: $_[0]"; };
}
$ENV{XCATROOT} = "$FindBin::Bin/../../../xCAT-server";
$ENV{XCATCFG} = '/tmp/fixture/config';
make_path($ENV{XCATCFG}, '/tmp/xcat');
require xCAT::Utils;
require xCAT::TableUtils;
no warnings qw(redefine once);
local *xCAT::TableUtils::getTftpDir = sub { return '/tmp/fixture/tftp'; };
local *xCAT::Utils::osver = sub { return 'rhels9.4'; };
my $plugin = "$FindBin::Bin/../../../xCAT-server/lib/xcat/plugins/dhcp.pm";
require $plugin;
my $port = JSON->new->allow_nonref->decode($ARGV[0]);
my %site = (httpport => $port, domain => 'example.invalid', dhcpinterfaces => 'eth0', dnshandler => 'none');
local %::XCATSITEVALS = %site;
local $xCAT_plugin::dhcp::dhcpconffile = '/tmp/fixture/dhcpd.conf';
local *xCAT::TableUtils::get_site_attribute = sub { return $site{$_[-1]}; };
local *xCAT::DHCP::Backend::new_backend = sub { return bless {}, 'HTTPTestBackend'; };
local *xCAT::DHCP::OmapiRunner::key_algorithm_error = sub { return; };
local *xCAT::Utils::isServiceNode = sub { return 0; };
local *xCAT::Utils::isFIPS = sub { return 0; };
local *xCAT::Utils::checkservicestatus = sub { return 0; };
local *xCAT::Utils::restartservice = sub { return 0; };
local *xCAT::MsgUtils::trace = sub { return; };
local *xCAT::NetworkUtils::determinehostname = sub { return 'mn'; };
local *xCAT::NetworkUtils::my_ip_facing = sub { return (0, '192.0.2.1'); };
local *xCAT::NetworkUtils::nodeonmynet = sub { return 1; };
local *xCAT::NetworkUtils::getipaddr = sub { return '192.0.2.10'; };
local *xCAT_plugin::dhcp::getipaddr = sub { return '192.0.2.10'; };
local *xCAT_plugin::dhcp::local_ipv4_routes = sub { return ['192.0.2.0', 'eth0', '255.255.255.0', '']; };
local *xCAT::DBobjUtils::getnodetype = sub { return { cn1 => 'osi' }; };
local *xCAT::DBobjUtils::getNetwkInfo = sub { return (cn1 => {mgtifname => 'eth0'}); };
local *xCAT::Table::new = sub { return bless {name => $_[1]}, 'HTTPTestTable'; };
local *xCAT_plugin::dhcp::_open_omshell_writer = sub {
open(my $fh, '>', '/tmp/fixture/omshell') or die $!;
return $fh;
};
local *xCAT_plugin::dhcp::_close_omshell_writer = sub { close($_[0]) or die $!; };
my @errors;
xCAT_plugin::dhcp::process_request({_xcatpreprocessed => [1], node => ['cn1'], arg => []},
sub { push @errors, @{$_[0]{error} || []}; });
die join("\n", @errors) if @errors;
package HTTPTestBackend;
sub name { return 'isc'; }
package HTTPTestTable;
sub getNodeAttribs { return {ip => '192.0.2.10'} if $_[0]{name} eq 'hosts'; return; }
sub getNodesAttribs {
my %rows = (
noderes => {netboot => 'petitboot', tftpserver => '192.0.2.1'},
mac => {mac => '52:54:00:00:00:10'}, nodetype => {os => 'rhels9'},
chain => {currstate => 'shell'},
);
return $rows{$_[0]{name}} ? {cn1 => [$rows{$_[0]{name}}]} : {};
}
sub getAllAttribs {
return () unless $_[0]{name} eq 'networks';
return {net => '192.0.2.0', mask => '255.255.255.0', mgtifname => 'eth0',
domain => 'example.invalid', nameservers => '192.0.2.1'};
}
sub getAttribs {
return {username => 'xcat_key', password => 'dGVzdA=='} if $_[0]{name} eq 'passwd';
return {domain => 'example.invalid', nameservers => '192.0.2.1', tftpserver => '192.0.2.1'};
}
sub close { return; }
+28
View File
@@ -1903,4 +1903,32 @@ foreach my $case (@invalid_mac_cases) {
);
}
for my $case ([undef, ''], ['', ''], [0, ''], ['0', ''], ['80', ''], ['080', ':080'], ['8080', ':8080']) {
my ($port, $suffix) = @$case;
no warnings 'redefine';
local *xCAT::TableUtils::get_site_attribute = sub {
return ($port) if $_[-1] eq 'httpport' && defined($port);
return;
};
for my $method (qw(onie petitboot)) {
my $boot = xCAT_plugin::dhcp::kea_boot_for_node('cn1', {netboot => $method},
{currstate => 'install'}, {}, {}, '192.0.2.1');
my $path = $method eq 'onie' ? '/install/onie/onie-installer' : '/tftpboot/petitboot/cn1';
is($boot->{'option-data'}[0]{data}, "http://192.0.2.1$suffix$path",
"$method reservation preserves site port defaulting");
}
}
for my $case (['80', ''], ['080', ':080'], ['8080', ':8080']) {
my ($port, $suffix) = @$case;
my $opal = xCAT_plugin::dhcp::kea_opal_client_class('192.0.2.0', 24, '192.0.2.1', $port);
is($opal->{'option-data'}[0]{data}, "http://192.0.2.1$suffix/tftpboot/pxelinux.cfg/p/192.0.2.0_24",
'OPAL preserves the supplied port');
my $subnet = xCAT_plugin::dhcp::kea_subnet4_intent(
DHCPKeaIntentNetTable->new(\%network_entry), '10.0.0.0', '255.255.255.0', 'eth0', 0, 1, $port,
);
my ($onie) = grep { $_->{name} eq 'xcat-onie-10.0.0.0_24' } @{$subnet->{client_classes}};
is($onie->{'option-data'}[0]{data}, "http://10.0.0.1$suffix/install/onie/onie-installer",
'subnet generation preserves the supplied port');
}
done_testing();
+50
View File
@@ -0,0 +1,50 @@
#!/usr/bin/env perl
use strict;
use warnings;
use FindBin;
use lib "$FindBin::Bin/../../perl-xCAT";
use File::Path qw(make_path);
use File::Slurper qw(write_text);
use File::Temp qw(tempdir);
use Test::More;
use xCAT::DHCP::BootPolicy;
my $root = tempdir(CLEANUP => 1);
make_path("$root/boot/grub2");
write_text("$root/boot/grub2/grub2.riscv64", 'loader');
my %network = (net => '192.0.2.0', prefix => 24, next_server => '192.0.2.1');
for my $case ([undef, ''], ['', ''], [0, ''], ['0', ''], ['80', ''], ['080', ':080'], ['8080', ':8080']) {
my ($port, $suffix) = @$case;
my $base = "http://192.0.2.1$suffix";
my $http = xCAT::DHCP::BootPolicy->kea_httpboot_network_classes(
%network, httpport => $port, tftpdir => $root,
);
is_deeply([map { $_->{'boot-file-name'} } @$http], ["$base/tftpboot/boot/grub2/grub2.riscv64"],
'HTTP boot preserves the site port default');
my $onie = xCAT::DHCP::BootPolicy->kea_onie_network_classes(%network, httpport => $port);
is($onie->[0]{'option-data'}[0]{data}, "$base/install/onie/onie-installer",
'ONIE preserves the site port default');
my $net = xCAT::DHCP::BootPolicy->kea_xnba_network_classes(
%network, httpport => $port, ipxe_bios => 1, ipxe_uefi => 1,
);
is_deeply([map { $_->{'boot-file-name'} } @$net], [
"$base/tftpboot/xcat/ipxe/nets/192.0.2.0_24",
"$base/tftpboot/xcat/ipxe/nets/192.0.2.0_24.uefi",
], 'BIOS and UEFI discovery URLs preserve the site port default');
my $node = xCAT::DHCP::BootPolicy->kea_xnba_node_classes(nodes => [{
node => 'cn1', mac => '52:54:00:00:00:01', netboot => 'ipxe',
next_server => '192.0.2.1', httpport => $port,
}]);
is_deeply([map { $_->{'boot-file-name'} } @$node], [
"$base/tftpboot/xcat/ipxe/nodes/cn1",
"$base/tftpboot/xcat/ipxe/nodes/cn1.uefi",
'xcat/ipxe/i386/undionly.kpxe',
'xcat/ipxe/x86_64-sb/snponly-shim.efi',
], 'per-node BIOS and UEFI URLs preserve the site port default');
}
done_testing();
+22
View File
@@ -698,4 +698,26 @@ ok(!-e $s390x_qemu_path, 'a :noboot network gets no QEMU s390x configuration');
%xCAT::TableUtils::site_extra = ();
$xCAT::NetworkUtils::nic_ips = undef;
%xCAT::TableUtils::site_extra = ();
use_reporter_address_maps();
for my $case ([undef, ''], ['', ''], [0, ''], ['0', ''], ['80', ''], ['080', ':080'], ['8080', ':8080']) {
my ($port, $suffix) = @$case;
$xCAT::TableUtils::site_httpport = $port;
prepare_tftpdir($tmpdir, 'http-port', 'x86_64');
generation_succeeded(run_mknb('x86_64'), 'mknb renders the HTTP-port case');
for my $loader (qw(xnba ipxe)) {
for my $mode ('', '.uefi') {
my $script = read_config("$xCAT::TableUtils::tftpdir/xcat/$loader/nets/192.168.144.0_20$mode");
my @authorities = $script =~ m{^imgfetch -n \w+ (http://[^/\s]+)}mg;
is_deeply(\@authorities, [('http://${next-server}' . $suffix) x 2],
"$loader$mode preserves HTTP port defaulting for kernel and initrd");
}
}
prepare_tftpdir($tmpdir, 'http-port-grub', 'riscv64');
generation_succeeded(run_mknb('riscv64'), 'mknb renders the GRUB HTTP-port case');
like(read_config("$xCAT::TableUtils::tftpdir/boot/grub2/grub.cfg-C0A89"),
qr/^ set root=\Qhttp,192.168.148.10$suffix\E$/m,
'GRUB discovery preserves HTTP port defaulting');
}
done_testing();
+10 -8
View File
@@ -13,20 +13,15 @@ use Test::More;
use XCAT::Test::File qw(repo_path);
my $module = repo_path('xCAT-server/lib/perl/xCAT/Template.pm');
plan skip_all => 'Template.pm not found' unless -r $module;
my @incs = (
repo_path('perl-xCAT'),
repo_path('xCAT-server/lib/perl'),
);
# A mismatched DBI aborts the process instead of dying, so ask a child before
# loading the module in this process.
my $devnull = File::Spec->devnull();
my $probe = join( ' ', $^X, ( map { "-I$_" } @incs ),
'-e', "'require xCAT::Template; 1'", ">$devnull", "2>&1" );
plan skip_all => 'xCAT::Template cannot be loaded here' if system($probe) != 0;
my $config = File::Temp->newdir();
$ENV{XCATROOT} = repo_path('xCAT-server');
$ENV{XCATCFG} = "$config";
require lib;
lib->import(@incs);
require xCAT::Template;
@@ -130,4 +125,11 @@ local *xCAT::TableUtils::get_site_Master = sub { return '192.0.2.10'; };
'a local mirror keeps a custom port' );
}
for my $case ([undef, ''], ['', ''], [0, ':0'], ['0', ':0'], ['80', ''], ['080', ':080'], ['8080', ':8080']) {
my ($port, $suffix) = @$case;
is(suffix($port), $suffix, 'Template keeps its defined-value defaulting');
like($render->($port), qr{^url --url http://192\.0\.2\.10\Q$suffix\E/install/pkg$}m,
'rendered installer URL keeps the same port');
}
done_testing();
+13
View File
@@ -126,6 +126,19 @@ write_text("$root/tftp/xcat/pxelinux.0", 'loader');
is_deeply(nodeset('present', 'install', {kernel => 'xcat/memdisk', initrd => 'initrd', kcmdline => 'quiet'}),
[], 'an installed pxelinux needs no warning');
for my $case ([undef, ''], ['', ''], [0, ''], ['0', ''], ['80', ''], ['080', ':080'], ['8080', ':8080']) {
my ($value, $suffix) = @$case;
$port = $value;
nodeset('port', 'install', {kernel => 'xcat/ubuntu24.04/vmlinuz', initrd => 'xcat/initrd', kcmdline => 'quiet'});
for my $name ('port', 'port.uefi') {
my @urls = script($name) =~ /^imgfetch -n \w+ (\S+)$/mg;
is_deeply(\@urls, [
'http://${next-server}' . $suffix . '/tftpboot/xcat/ubuntu24.04/vmlinuz',
'http://${next-server}' . $suffix . '/tftpboot/xcat/initrd',
], "$name retains its HTTP port defaulting");
}
}
done_testing();
package Local::BootTable;