2
0
mirror of https://github.com/xcat2/xcat-core.git synced 2026-09-30 06:51:17 +00:00
Files
xcat-core/xCAT-test/unit/mknb_xcatd_address.t
T
2026-08-10 15:08:28 -03:00

338 lines
9.8 KiB
Perl

#!/usr/bin/env perl
use strict;
use warnings;
## no critic (Modules::RequireFilenameMatchesPackage, TestingAndDebugging::ProhibitNoStrict, TestingAndDebugging::ProhibitNoWarnings)
use FindBin;
use File::Path qw(make_path);
use File::Temp qw(tempdir);
use Test::More;
BEGIN {
package xCAT::Utils;
$INC{'xCAT/Utils.pm'} = __FILE__;
package xCAT::TableUtils;
our ($tftpdir, $site_master, $site_httpport);
sub getTftpDir { return $tftpdir; }
sub get_site_attribute {
my $attribute = $_[-1];
return ($site_master) if $attribute eq 'master';
return ($site_httpport) if $attribute eq 'httpport' and defined $site_httpport;
return;
}
$INC{'xCAT/TableUtils.pm'} = __FILE__;
package xCAT::NetworkUtils;
our ($normnet_addresses, $hexnet_addresses, @master_addresses);
sub my_nets {
die "mknb did not request all normalized-network addresses"
unless $_[-1] eq 'all';
return $normnet_addresses;
}
sub my_hexnets {
die "mknb did not request all hexadecimal-network addresses"
unless $_[-1] eq 'all';
return $hexnet_addresses;
}
sub getipaddr { return @master_addresses; }
$INC{'xCAT/NetworkUtils.pm'} = __FILE__;
package xCAT::NodeRange;
sub import {
my $caller = caller;
no strict 'refs';
*{"${caller}::noderange"} = sub { return; };
}
$INC{'xCAT/NodeRange.pm'} = __FILE__;
}
my $source_mknb_plugin = "$FindBin::Bin/../../xCAT-server/lib/xcat/plugins/mknb.pm";
if (-f $source_mknb_plugin) {
require $source_mknb_plugin;
} else {
require xCAT_plugin::mknb;
}
my ($legacy, $selected) = xCAT_plugin::mknb::_select_network_addresses(
{
'10.20.30.0/24' => [
'10.20.30.10',
'10.20.30.250',
],
},
['10.20.30.250'],
);
is_deeply(
$legacy,
{ '10.20.30.0/24' => '10.20.30.250' },
'Linux HA keeps the last address as the legacy network address',
);
is_deeply(
$selected,
{ '10.20.30.0/24' => '10.20.30.250' },
'Linux HA selects the local site.master virtual address',
);
($legacy, $selected) = xCAT_plugin::mknb::_select_network_addresses(
{
'10.30.40.0/24' => [
'10.30.40.20',
'10.30.40.100',
],
},
['192.0.2.1'],
);
is_deeply(
$legacy,
{ '10.30.40.0/24' => '10.30.40.100' },
'a service node keeps its last address as the legacy network address',
);
is_deeply(
$selected,
{ '10.30.40.0/24' => '10.30.40.20' },
'a service node ignores a remote site.master address and selects its first local address',
);
($legacy, $selected) = xCAT_plugin::mknb::_select_network_addresses(
{
'192.168.144.0/20' => [
'192.168.148.10',
'192.168.149.100',
],
'198.51.100.0/24' => [],
},
[],
);
is_deeply(
$legacy,
{ '192.168.144.0/20' => '192.168.149.100' },
'missing site.master preference preserves the last-address legacy value',
);
is_deeply(
$selected,
{ '192.168.144.0/20' => '192.168.148.10' },
'missing site.master preference falls back to the first candidate and skips empty networks',
);
sub prepare_tftpdir {
my ($root, $name, $arch, $image_type) = @_;
$image_type //= 'genesis';
$xCAT::TableUtils::tftpdir = "$root/$name";
make_path(
"$xCAT::TableUtils::tftpdir/xcat",
"$xCAT::TableUtils::tftpdir/etc",
);
my @files = ("$xCAT::TableUtils::tftpdir/xcat/genesis.kernel.$arch");
if ($image_type eq 'legacy') {
push @files,
"$xCAT::TableUtils::tftpdir/xcat/nbk.$arch",
"$xCAT::TableUtils::tftpdir/xcat/nbfs.$arch.gz";
} else {
push @files, "$xCAT::TableUtils::tftpdir/xcat/genesis.fs.$arch.gz";
}
foreach my $file (@files) {
open(my $fh, '>', $file) or die "Unable to create $file: $!";
close($fh);
}
}
sub run_mknb {
my ($arch) = @_;
my @responses;
xCAT_plugin::mknb::process_request(
{ arg => [$arch, '--configfileonly'] },
sub { push @responses, @_; },
);
return \@responses;
}
sub read_config {
my ($path) = @_;
open(my $fh, '<', $path) or die "Unable to read $path: $!";
my $content = do { local $/; <$fh> };
close($fh);
return $content;
}
sub generation_succeeded {
my ($responses, $description) = @_;
ok(
!grep({ ref($_) eq 'HASH' && $_->{error} } @{$responses}),
$description,
);
}
sub use_reporter_address_maps {
$xCAT::NetworkUtils::normnet_addresses = {
'192.168.144.0/20' => [
'192.168.148.10',
'192.168.149.100',
],
};
$xCAT::NetworkUtils::hexnet_addresses = {
c0a89 => [
'192.168.148.10',
'192.168.149.100',
],
};
$xCAT::TableUtils::site_master = 'master.example.com';
@xCAT::NetworkUtils::master_addresses = ('203.0.113.10');
}
my $tmpdir = tempdir(CLEANUP => 1);
$::XCATROOT = "$tmpdir/xcatroot";
make_path(
"$::XCATROOT/share/xcat/netboot/genesis/x86_64",
"$::XCATROOT/share/xcat/netboot/genesis/ppc64",
);
use_reporter_address_maps();
prepare_tftpdir($tmpdir, 'tftpboot-x86', 'x86_64');
my $responses = run_mknb('x86_64');
generation_succeeded($responses, 'x86 configuration generation succeeds');
my $genesis_pxe = read_config(
"$xCAT::TableUtils::tftpdir/pxelinux.cfg/C0A89"
);
like(
$genesis_pxe,
qr/^ KERNEL xcat\/genesis\.kernel\.x86_64$/m,
'PXELINUX selects the Genesis kernel',
);
like(
$genesis_pxe,
qr/^ APPEND initrd=xcat\/genesis\.fs\.x86_64\.gz /m,
'PXELINUX makes the Genesis initramfs relative to the configured TFTP root',
);
unlike(
$genesis_pxe,
qr/\Q$xCAT::TableUtils::tftpdir\E/,
'PXELINUX does not expose the configured TFTP root',
);
foreach my $relative_path (
'xcat/xnba/nets/192.168.144.0_20',
'pxelinux.cfg/C0A89',
) {
my $content = read_config("$xCAT::TableUtils::tftpdir/$relative_path");
like(
$content,
qr/xcatd=192\.168\.148\.10:3001/,
"$relative_path uses the first address as the xcatd endpoint",
);
unlike(
$content,
qr/xcatd=192\.168\.149\.100:3001/,
"$relative_path does not use the later floating address as the xcatd endpoint",
);
}
use_reporter_address_maps();
prepare_tftpdir($tmpdir, 'tftpboot-x86-legacy', 'x86_64', 'legacy');
$responses = run_mknb('x86_64');
generation_succeeded($responses, 'legacy x86 configuration generation succeeds');
my $legacy_pxe = read_config(
"$xCAT::TableUtils::tftpdir/pxelinux.cfg/C0A89"
);
like(
$legacy_pxe,
qr/^ KERNEL xcat\/nbk\.x86_64$/m,
'PXELINUX keeps the legacy kernel',
);
like(
$legacy_pxe,
qr/^ APPEND initrd=xcat\/nbfs\.x86_64\.gz /m,
'PXELINUX keeps the legacy initramfs path',
);
use_reporter_address_maps();
prepare_tftpdir($tmpdir, 'tftpboot-power', 'ppc64');
$responses = run_mknb('ppc64');
generation_succeeded($responses, 'POWER configuration generation succeeds');
foreach my $relative_path (
'pxelinux.cfg/p/192.168.144.0_20',
'etc/c0a89',
) {
my $content = read_config("$xCAT::TableUtils::tftpdir/$relative_path");
like(
$content,
qr/kernel http:\/\/192\.168\.148\.10\//,
"$relative_path uses the first address for the kernel URL",
);
like(
$content,
qr/initrd http:\/\/192\.168\.148\.10\//,
"$relative_path uses the first address for the initrd URL",
);
like(
$content,
qr/xcatd=192\.168\.148\.10:3001/,
"$relative_path uses the first address as the xcatd endpoint",
);
unlike(
$content,
qr/(?:kernel|initrd) http:\/\/192\.168\.149\.100\/|xcatd=192\.168\.149\.100:3001/,
"$relative_path has no functional endpoint using the later floating address",
);
}
# the default HTTP port is left out of the generated URLs, but a port that is
# not the default still has to be carried through
$xCAT::TableUtils::site_httpport = '8080';
use_reporter_address_maps();
prepare_tftpdir($tmpdir, 'tftpboot-power-altport', 'ppc64');
$responses = run_mknb('ppc64');
generation_succeeded($responses, 'POWER configuration generation succeeds with a non-default HTTP port');
my $altport_content = read_config("$xCAT::TableUtils::tftpdir/pxelinux.cfg/p/192.168.144.0_20");
like(
$altport_content,
qr/kernel http:\/\/192\.168\.148\.10:8080\//,
'a non-default HTTP port is kept in the kernel URL',
);
like(
$altport_content,
qr/initrd http:\/\/192\.168\.148\.10:8080\//,
'a non-default HTTP port is kept in the initrd URL',
);
$xCAT::TableUtils::site_httpport = undef;
$xCAT::NetworkUtils::normnet_addresses = {
'192.168.144.0/20' => ['192.168.148.10'],
};
$xCAT::NetworkUtils::hexnet_addresses = {
c0a89 => ['192.168.148.10'],
};
$xCAT::TableUtils::site_master = 'master.example.com';
@xCAT::NetworkUtils::master_addresses = ('203.0.113.10');
prepare_tftpdir($tmpdir, 'tftpboot-no-floating', 'x86_64');
$responses = run_mknb('x86_64');
generation_succeeded($responses, 'configuration generation without a floating address succeeds');
my $no_floating_xnba = read_config(
"$xCAT::TableUtils::tftpdir/xcat/xnba/nets/192.168.144.0_20"
);
my $no_floating_pxe = read_config(
"$xCAT::TableUtils::tftpdir/pxelinux.cfg/C0A89"
);
$xCAT::TableUtils::site_master = undef;
@xCAT::NetworkUtils::master_addresses = ();
prepare_tftpdir($tmpdir, 'tftpboot-no-floating', 'x86_64');
$responses = run_mknb('x86_64');
generation_succeeded($responses, 'configuration generation without site.master succeeds');
is(
read_config("$xCAT::TableUtils::tftpdir/xcat/xnba/nets/192.168.144.0_20"),
$no_floating_xnba,
'xNBA output is byte-identical without a site.master preference',
);
is(
read_config("$xCAT::TableUtils::tftpdir/pxelinux.cfg/C0A89"),
$no_floating_pxe,
'legacy PXE output is byte-identical without a site.master preference',
);
done_testing();