mirror of
https://github.com/xcat2/xcat-core.git
synced 2026-09-21 16:39:30 +00:00
fix(mknb): avoid transient discovery addresses
This commit is contained in:
@@ -34,6 +34,8 @@ for the same architecture that the management node is. So you normally do not n
|
||||
|
||||
If you make custom changes to the network boot root image, you will need to run \ **mknb**\ again to regenerate the diskless image to include your changes. If you have an xCAT Hierarchical Cluster with Service Nodes having local /tftpboot directories (site.sharedtftp=0), you will need to copy the generated root image to each Service Node.
|
||||
|
||||
When multiple IPv4 addresses are configured for the same network, \ **mknb**\ uses a locally assigned ``site.master`` for the xcatd endpoint, or the first address reported by the operating system when ``site.master`` is not local. POWER discovery configurations also use this address for their kernel and initrd URLs.
|
||||
|
||||
Presently, the architectures x86_64 and ppc64 are supported. For ppc64le, use the ppc64 architecture.
|
||||
|
||||
|
||||
|
||||
@@ -907,7 +907,8 @@ sub classful_networks_for_net_and_mask
|
||||
=head3 my_hexnets
|
||||
|
||||
Arguments:
|
||||
none
|
||||
Optional: 'all' returns every IPv4 address found for each network in order.
|
||||
The default behavior returns the last address found.
|
||||
Returns:
|
||||
Globals:
|
||||
none
|
||||
@@ -922,6 +923,7 @@ sub classful_networks_for_net_and_mask
|
||||
#-------------------------------------------------------------------------------
|
||||
sub my_hexnets
|
||||
{
|
||||
my $returnall = @_ && $_[-1] eq 'all';
|
||||
my $rethash;
|
||||
my @nets = split /\n/, `/sbin/ip addr`;
|
||||
foreach (@nets)
|
||||
@@ -945,7 +947,12 @@ sub my_hexnets
|
||||
while ($nown <= $highn)
|
||||
{
|
||||
my $nowhex = sprintf("%08x", $nown);
|
||||
$rethash->{ substr($nowhex, 0, $numchars) } = $curnet;
|
||||
my $hexnet = substr($nowhex, 0, $numchars);
|
||||
if ($returnall) {
|
||||
push @{ $rethash->{$hexnet} }, $curnet;
|
||||
} else {
|
||||
$rethash->{$hexnet} = $curnet;
|
||||
}
|
||||
$nown += 1 << (32 - $maskbits - $bitstoeven);
|
||||
}
|
||||
}
|
||||
@@ -1046,7 +1053,8 @@ sub isPingable
|
||||
Return a hash ref that contains all subnet and netmask on the mn (or sn). This subroutine can be invoked on both Linux and AIX.
|
||||
|
||||
Arguments:
|
||||
none.
|
||||
Optional: 'all' returns every address found for each network in order.
|
||||
The default behavior returns the last address found.
|
||||
|
||||
Returns:
|
||||
Return a hash ref. Each entry will be: <subnet/mask>=><existing ip>;
|
||||
@@ -1070,6 +1078,7 @@ For an example
|
||||
#-----------------------------------------------------------------------
|
||||
sub my_nets
|
||||
{
|
||||
my $returnall = @_ && $_[-1] eq 'all';
|
||||
require xCAT::Table;
|
||||
my $rethash;
|
||||
my @nets;
|
||||
@@ -1122,11 +1131,19 @@ sub my_nets
|
||||
$nown = $nown & $curmask;
|
||||
my $textnet = inet_ntoa(pack("N", $nown));
|
||||
$textnet .= "/$maskbits";
|
||||
$rethash->{$textnet} = $curnet;
|
||||
if ($returnall) {
|
||||
push @{ $rethash->{$textnet} }, $curnet;
|
||||
} else {
|
||||
$rethash->{$textnet} = $curnet;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
$rethash->{$v6net} = $v6ip;
|
||||
if ($returnall) {
|
||||
push @{ $rethash->{$v6net} }, $v6ip;
|
||||
} else {
|
||||
$rethash->{$v6net} = $v6ip;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1154,7 +1171,11 @@ sub my_nets
|
||||
$n .= "/$nm";
|
||||
|
||||
#$rethash->{$n} = $if;
|
||||
$rethash->{$n} = $master;
|
||||
if ($returnall) {
|
||||
push @{ $rethash->{$n} }, $master;
|
||||
} else {
|
||||
$rethash->{$n} = $master;
|
||||
}
|
||||
}
|
||||
}
|
||||
return $rethash;
|
||||
|
||||
@@ -16,6 +16,8 @@ B<mknb> command yourself.
|
||||
|
||||
If you make custom changes to the network boot root image, you will need to run B<mknb> again to regenerate the diskless image to include your changes. If you have an xCAT Hierarchical Cluster with Service Nodes having local /tftpboot directories (site.sharedtftp=0), you will need to copy the generated root image to each Service Node.
|
||||
|
||||
When multiple IPv4 addresses are configured for the same network, B<mknb> uses a locally assigned C<site.master> for the xcatd endpoint, or the first address reported by the operating system when C<site.master> is not local. POWER discovery configurations also use this address for their kernel and initrd URLs.
|
||||
|
||||
Presently, the architectures x86_64 and ppc64 are supported. For ppc64le, use the ppc64 architecture.
|
||||
|
||||
=head1 OPTIONS
|
||||
|
||||
@@ -13,6 +13,28 @@ sub handled_commands {
|
||||
};
|
||||
}
|
||||
|
||||
sub _select_network_addresses {
|
||||
my ($network_addresses, $preferred_addresses) = @_;
|
||||
my %preferred = map { $_ => 1 } grep { defined($_) } @{$preferred_addresses};
|
||||
my %legacy;
|
||||
my %selected;
|
||||
|
||||
foreach my $network (keys %{$network_addresses}) {
|
||||
my $addresses = $network_addresses->{$network};
|
||||
next unless @{$addresses};
|
||||
$legacy{$network} = $addresses->[-1];
|
||||
$selected{$network} = $addresses->[0];
|
||||
foreach my $address (@{$addresses}) {
|
||||
if (defined($address) && $preferred{$address}) {
|
||||
$selected{$network} = $address;
|
||||
last;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return (\%legacy, \%selected);
|
||||
}
|
||||
|
||||
sub process_request {
|
||||
my $request = shift;
|
||||
my $callback = shift;
|
||||
@@ -272,8 +294,21 @@ sub process_request {
|
||||
return;
|
||||
}
|
||||
}
|
||||
my $hexnets = xCAT::NetworkUtils->my_hexnets();
|
||||
my $normnets = xCAT::NetworkUtils->my_nets();
|
||||
my $hexnet_addresses = xCAT::NetworkUtils->my_hexnets('all');
|
||||
my $normnet_addresses = xCAT::NetworkUtils->my_nets('all');
|
||||
my @masters = xCAT::TableUtils->get_site_attribute("master");
|
||||
my @master_addresses;
|
||||
if ($masters[0]) {
|
||||
@master_addresses = xCAT::NetworkUtils->getipaddr(
|
||||
$masters[0], OnlyV4 => 1, GetAllAddresses => 1
|
||||
);
|
||||
}
|
||||
my ($hexnets, $xcatdhexnets) = _select_network_addresses(
|
||||
$hexnet_addresses, \@master_addresses
|
||||
);
|
||||
my ($normnets, $xcatdnormnets) = _select_network_addresses(
|
||||
$normnet_addresses, \@master_addresses
|
||||
);
|
||||
my $consolecmdline;
|
||||
if (defined($serialport) and $serialspeed) {
|
||||
if ($arch =~ /ppc/) {
|
||||
@@ -311,6 +346,7 @@ sub process_request {
|
||||
foreach (keys %{$normnets}) {
|
||||
my $net = $_;
|
||||
my $nicip = $normnets->{$net};
|
||||
my $xcatd_address = defined($xcatdnormnets->{$net}) ? $xcatdnormnets->{$net} : $nicip;
|
||||
$net =~ s/\//_/;
|
||||
if (defined($nobootnicips{$nicip})) {
|
||||
if ($arch =~ /ppc/ and -r "$tftpdir/pxelinux.cfg/p/$net") {
|
||||
@@ -342,10 +378,10 @@ sub process_request {
|
||||
open($cfg, ">", "$tftpdir/xcat/xnba/nets/$net");
|
||||
print $cfg "#!gpxe\n";
|
||||
if ($invisibletouch) {
|
||||
print $cfg 'imgfetch -n kernel http://${next-server}:'.$httpport.'/tftpboot/xcat/genesis.kernel.' . "$arch xcatd=" . $normnets->{$_} . ":$xcatdport $consolecmdline BOOTIF=01-" . '${netX/machyp}' . "\n";
|
||||
print $cfg 'imgfetch -n kernel http://${next-server}:'.$httpport.'/tftpboot/xcat/genesis.kernel.' . "$arch xcatd=" . $xcatd_address . ":$xcatdport $consolecmdline BOOTIF=01-" . '${netX/machyp}' . "\n";
|
||||
print $cfg 'imgfetch -n nbfs http://${next-server}:'.$httpport . "$initrd_file\n";
|
||||
} else {
|
||||
print $cfg 'imgfetch -n kernel http://${next-server}:'.$httpport.'/tftpboot/xcat/nbk.' . "$arch xcatd=" . $normnets->{$_} . ":$xcatdport $consolecmdline\n";
|
||||
print $cfg 'imgfetch -n kernel http://${next-server}:'.$httpport.'/tftpboot/xcat/nbk.' . "$arch xcatd=" . $xcatd_address . ":$xcatdport $consolecmdline\n";
|
||||
print $cfg 'imgfetch -n nbfs http://${next-server}:'.$httpport . "$initrd_file\n";
|
||||
}
|
||||
print $cfg "imgload kernel\n";
|
||||
@@ -358,12 +394,12 @@ sub process_request {
|
||||
print $cfg ' image=/tftpboot/xcat/genesis.kernel.' . "$arch\n";
|
||||
print $cfg " label=\"xCAT Genesis (" . $normnets->{$_} . ")\"\n";
|
||||
print $cfg " initrd=$initrd_file\n";
|
||||
print $cfg " append=\"xcatd=" . $normnets->{$_} . ":$xcatdport destiny=discover $consolecmdline BOOTIF=%B\"\n";
|
||||
print $cfg " append=\"xcatd=" . $xcatd_address . ":$xcatdport destiny=discover $consolecmdline BOOTIF=%B\"\n";
|
||||
close($cfg);
|
||||
open($cfg, ">", "$tftpdir/xcat/xnba/nets/$net.uefi");
|
||||
print $cfg "#!gpxe\n";
|
||||
print $cfg 'imgfetch -n kernel http://${next-server}:'.$httpport.'/tftpboot/xcat/genesis.kernel.' . "$arch\nimgload kernel\n";
|
||||
print $cfg "imgargs kernel xcatd=" . $normnets->{$_} . ":$xcatdport $consolecmdline BOOTIF=01-" . '${netX/mac:hexhyp}' . " destiny=discover initrd=initrd\n";
|
||||
print $cfg "imgargs kernel xcatd=" . $xcatd_address . ":$xcatdport $consolecmdline BOOTIF=01-" . '${netX/mac:hexhyp}' . " destiny=discover initrd=initrd\n";
|
||||
print $cfg 'imgfetch -n initrd http://${next-server}:'.$httpport . "$initrd_file\nimgexec kernel\n";
|
||||
close($cfg);
|
||||
}
|
||||
@@ -372,14 +408,15 @@ sub process_request {
|
||||
print $cfgfile "default \"xCAT Genesis (" . $normnets->{$_} . ")\"\n";
|
||||
print $cfgfile " delay=10\n";
|
||||
print $cfgfile " label \"xCAT Genesis (" . $normnets->{$_} . ")\"\n";
|
||||
print $cfgfile " kernel http://" . $normnets->{$_} . ":$httpport/$tftpdir/xcat/genesis.kernel.$arch\n";
|
||||
print $cfgfile " initrd http://" . $normnets->{$_} . ":$httpport/$initrd_file\n";
|
||||
print $cfgfile ' append "xcatd=' . $normnets->{$_} . ":$xcatdport $consolecmdline\"\n";
|
||||
print $cfgfile " kernel http://" . $xcatd_address . ":$httpport/$tftpdir/xcat/genesis.kernel.$arch\n";
|
||||
print $cfgfile " initrd http://" . $xcatd_address . ":$httpport/$initrd_file\n";
|
||||
print $cfgfile ' append "xcatd=' . $xcatd_address . ":$xcatdport $consolecmdline\"\n";
|
||||
close($cfgfile);
|
||||
}
|
||||
}
|
||||
$dopxe = 0;
|
||||
foreach (keys %{$hexnets}) {
|
||||
my $xcatd_address = defined($xcatdhexnets->{$_}) ? $xcatdhexnets->{$_} : $hexnets->{$_};
|
||||
$dopxe = 0;
|
||||
if ($arch =~ /x86/) { #only do pxe if just x86 or x86_64 and no x86
|
||||
if ($arch =~ /x86_64/) {
|
||||
@@ -404,16 +441,16 @@ sub process_request {
|
||||
print $cfgfile "DEFAULT xCAT\n";
|
||||
print $cfgfile " LABEL xCAT\n";
|
||||
print $cfgfile " KERNEL xcat/nbk.$arch\n";
|
||||
print $cfgfile " APPEND initrd=$tftp_initrd xcatd=" . $hexnets->{$_} . ":$xcatdport $consolecmdline\n";
|
||||
print $cfgfile " APPEND initrd=$tftp_initrd xcatd=" . $xcatd_address . ":$xcatdport $consolecmdline\n";
|
||||
close($cfgfile);
|
||||
} elsif ($arch =~ /ppc/) {
|
||||
open($cfgfile, ">", "$tftpdir/etc/" . lc($_));
|
||||
print $cfgfile "default \"xCAT Genesis (" . $normnets->{$_} . ")\"\n";
|
||||
print $cfgfile " delay=10\n";
|
||||
print $cfgfile " label \"xCAT Genesis (" . $normnets->{$_} . ")\"\n";
|
||||
print $cfgfile " kernel http://" . $hexnets->{$_} . ":$httpport/$tftpdir/xcat/genesis.kernel.$arch\n";
|
||||
print $cfgfile " initrd http://" . $hexnets->{$_} . ":$httpport/$initrd_file\n";
|
||||
print $cfgfile ' append "xcatd=' . $hexnets->{$_} . ":$xcatdport $consolecmdline\"\n";
|
||||
print $cfgfile " kernel http://" . $xcatd_address . ":$httpport/$tftpdir/xcat/genesis.kernel.$arch\n";
|
||||
print $cfgfile " initrd http://" . $xcatd_address . ":$httpport/$initrd_file\n";
|
||||
print $cfgfile ' append "xcatd=' . $xcatd_address . ":$xcatdport $consolecmdline\"\n";
|
||||
close($cfgfile);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,271 @@
|
||||
#!/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);
|
||||
sub getTftpDir { return $tftpdir; }
|
||||
sub get_site_attribute {
|
||||
my $attribute = $_[-1];
|
||||
return ($site_master) if $attribute eq 'master';
|
||||
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) = @_;
|
||||
$xCAT::TableUtils::tftpdir = "$root/$name";
|
||||
make_path(
|
||||
"$xCAT::TableUtils::tftpdir/xcat",
|
||||
"$xCAT::TableUtils::tftpdir/etc",
|
||||
);
|
||||
foreach my $file (
|
||||
"$xCAT::TableUtils::tftpdir/xcat/genesis.kernel.$arch",
|
||||
"$xCAT::TableUtils::tftpdir/xcat/genesis.fs.$arch.gz",
|
||||
) {
|
||||
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');
|
||||
|
||||
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-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:80\//,
|
||||
"$relative_path uses the first address for the kernel URL",
|
||||
);
|
||||
like(
|
||||
$content,
|
||||
qr/initrd http:\/\/192\.168\.148\.10:80\//,
|
||||
"$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:80\/|xcatd=192\.168\.149\.100:3001/,
|
||||
"$relative_path has no functional endpoint using the later floating address",
|
||||
);
|
||||
}
|
||||
|
||||
$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();
|
||||
@@ -0,0 +1,116 @@
|
||||
#!/usr/bin/env perl
|
||||
use strict;
|
||||
use warnings;
|
||||
## no critic (Modules::RequireFilenameMatchesPackage, TestingAndDebugging::ProhibitNoWarnings)
|
||||
|
||||
use FindBin;
|
||||
use lib "$FindBin::Bin/../../perl-xCAT";
|
||||
use Test::More;
|
||||
|
||||
BEGIN {
|
||||
package NetworkUtilsTestCommand;
|
||||
our $ip_addr_output = '';
|
||||
|
||||
package xCAT::Table;
|
||||
our @network_entries;
|
||||
sub new { return bless {}, shift; }
|
||||
sub getAllAttribs { return @network_entries; }
|
||||
$INC{'xCAT/Table.pm'} = __FILE__;
|
||||
|
||||
package xCAT::TableUtils;
|
||||
sub get_site_attribute {
|
||||
my ($attribute) = @_;
|
||||
return ('192.0.2.1') if $attribute eq 'master';
|
||||
return;
|
||||
}
|
||||
$INC{'xCAT/TableUtils.pm'} = __FILE__;
|
||||
|
||||
package main;
|
||||
*CORE::GLOBAL::readpipe = sub {
|
||||
my ($command) = @_;
|
||||
return $NetworkUtilsTestCommand::ip_addr_output
|
||||
if $command eq '/sbin/ip addr';
|
||||
die "Unexpected command in NetworkUtils unit test: $command";
|
||||
};
|
||||
}
|
||||
|
||||
require xCAT::NetworkUtils;
|
||||
|
||||
sub set_ip_addr_output {
|
||||
$NetworkUtilsTestCommand::ip_addr_output = join('', @_);
|
||||
@xCAT::Table::network_entries = ();
|
||||
}
|
||||
|
||||
set_ip_addr_output(
|
||||
"2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500\n",
|
||||
" inet 192.168.148.10/20 brd 192.168.159.255 scope global eth0\n",
|
||||
" valid_lft forever preferred_lft forever\n",
|
||||
" inet 192.168.149.100/20 scope global secondary eth0\n",
|
||||
" valid_lft forever preferred_lft forever\n",
|
||||
" inet6 2001:db8:1::10/64 scope global\n",
|
||||
);
|
||||
|
||||
is_deeply(
|
||||
xCAT::NetworkUtils->my_nets(),
|
||||
{ '192.168.144.0/20' => '192.168.149.100' },
|
||||
'my_nets default behavior remains last-address-wins',
|
||||
);
|
||||
is_deeply(
|
||||
xCAT::NetworkUtils->my_nets('all'),
|
||||
{
|
||||
'192.168.144.0/20' => [
|
||||
'192.168.148.10',
|
||||
'192.168.149.100',
|
||||
],
|
||||
},
|
||||
'my_nets all mode preserves every address in operating-system order',
|
||||
);
|
||||
is_deeply(
|
||||
xCAT::NetworkUtils->my_hexnets(),
|
||||
{ c0a89 => '192.168.149.100' },
|
||||
'my_hexnets default behavior remains last-address-wins',
|
||||
);
|
||||
is_deeply(
|
||||
xCAT::NetworkUtils->my_hexnets('all'),
|
||||
{
|
||||
c0a89 => [
|
||||
'192.168.148.10',
|
||||
'192.168.149.100',
|
||||
],
|
||||
},
|
||||
'my_hexnets all mode preserves every address in operating-system order',
|
||||
);
|
||||
|
||||
set_ip_addr_output(
|
||||
"2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500\n",
|
||||
" inet 192.168.148.10/20 brd 192.168.159.255 scope global eth0\n",
|
||||
" inet6 2001:db8:1::10/64 scope global\n",
|
||||
);
|
||||
|
||||
is_deeply(
|
||||
xCAT::NetworkUtils->my_nets(),
|
||||
{ '192.168.144.0/20' => '192.168.148.10' },
|
||||
'my_nets default output is unchanged when there is no floating address',
|
||||
);
|
||||
is_deeply(
|
||||
xCAT::NetworkUtils->my_nets('all'),
|
||||
{ '192.168.144.0/20' => ['192.168.148.10'] },
|
||||
'my_nets all mode returns one candidate when there is no floating address',
|
||||
);
|
||||
is_deeply(
|
||||
xCAT::NetworkUtils->my_hexnets(),
|
||||
{ c0a89 => '192.168.148.10' },
|
||||
'my_hexnets default output is unchanged when there is no floating address',
|
||||
);
|
||||
is_deeply(
|
||||
xCAT::NetworkUtils->my_hexnets('all'),
|
||||
{ c0a89 => ['192.168.148.10'] },
|
||||
'my_hexnets all mode returns one candidate when there is no floating address',
|
||||
);
|
||||
is_deeply(
|
||||
xCAT::NetworkUtils->my_nets('all'),
|
||||
{ '192.168.144.0/20' => ['192.168.148.10'] },
|
||||
'Linux IPv6 addresses remain outside the all-address result',
|
||||
);
|
||||
|
||||
done_testing();
|
||||
Reference in New Issue
Block a user