mirror of
https://github.com/xcat2/xcat-core.git
synced 2026-09-04 20:17:55 +00:00
Merge pull request #7777 from VersatusHPC/fix/dhcp-infiniband-twin-entry
fix(dhcp): register the InfiniBand identity of a node that boots over IPoIB
This commit is contained in:
@@ -232,22 +232,41 @@ sub _isc_static_host_fallback
|
||||
|
||||
sub _delete_isc_static_host
|
||||
{
|
||||
my $node = shift;
|
||||
my ($node, $config, $hostname) = @_;
|
||||
$config ||= \@dhcpconf;
|
||||
|
||||
my $start_marker = defined($hostname)
|
||||
? qr/^#xCAT host declaration for \Q$node\E aka host \Q$hostname\E start$/
|
||||
: qr/^#xCAT host declaration for \Q$node\E aka host .* start$/;
|
||||
my $end_marker = defined($hostname)
|
||||
? qr/^(?:\}\s*)?#xCAT host declaration for \Q$node\E aka host \Q$hostname\E end$/
|
||||
: qr/^(?:\}\s*)?#xCAT host declaration for \Q$node\E aka host .* end$/;
|
||||
|
||||
my @updated;
|
||||
my $skip = 0;
|
||||
foreach my $line (@dhcpconf) {
|
||||
if ($line =~ /^#xCAT host declaration for \Q$node\E\b.* start$/) {
|
||||
foreach my $line (@{$config}) {
|
||||
if ($line =~ $start_marker) {
|
||||
$skip = 1;
|
||||
next;
|
||||
}
|
||||
if ($skip && $line =~ /^#xCAT host declaration for \Q$node\E\b.* end$/) {
|
||||
if ($skip && $line =~ $end_marker) {
|
||||
$skip = 0;
|
||||
next;
|
||||
}
|
||||
push @updated, $line unless $skip;
|
||||
}
|
||||
@dhcpconf = @updated;
|
||||
@{$config} = @updated;
|
||||
}
|
||||
|
||||
sub _begin_isc_static_host_update
|
||||
{
|
||||
my ($node, $enabled, $config) = @_;
|
||||
|
||||
return 0 unless $enabled;
|
||||
$config ||= \@dhcpconf;
|
||||
my $line_count = scalar(@{$config});
|
||||
_delete_isc_static_host($node, $config);
|
||||
return scalar(@{$config}) != $line_count;
|
||||
}
|
||||
|
||||
sub _static_host_statements
|
||||
@@ -261,21 +280,51 @@ sub _static_host_statements
|
||||
return $statements;
|
||||
}
|
||||
|
||||
sub _node_host_statements
|
||||
{
|
||||
my ($node, $statements) = @_;
|
||||
|
||||
return 'ddns-hostname \"' . $node . '\"; send host-name \"'
|
||||
. $node . '\";' . ($statements || '');
|
||||
}
|
||||
|
||||
sub _noip_hostname
|
||||
{
|
||||
my ($node, $mac) = @_;
|
||||
my $hostname = $node . '-noip' . $mac;
|
||||
$hostname =~ s/://g;
|
||||
return $hostname;
|
||||
}
|
||||
|
||||
sub _add_isc_static_host
|
||||
{
|
||||
my ($node, $hostname, $mac, $ip, $statements) = @_;
|
||||
my ($node, $hostname, $mac, $hardwaretype, $mgtifname, $ip, $statements,
|
||||
$has_infiniband_identity, $config, $update_started) = @_;
|
||||
$config ||= \@dhcpconf;
|
||||
|
||||
return unless $ip && $ip ne 'DENIED';
|
||||
|
||||
_delete_isc_static_host($node);
|
||||
if ($update_started && !${$update_started}) {
|
||||
$restartdhcp = 1 if _begin_isc_static_host_update($node, 1, $config);
|
||||
${$update_started} = 1;
|
||||
}
|
||||
|
||||
$mac = normalize_mac($mac) || $mac;
|
||||
_delete_isc_static_host($node, $config, $hostname);
|
||||
|
||||
my $host_statements = _static_host_statements($statements);
|
||||
push @dhcpconf, "#xCAT host declaration for $node aka host $hostname start\n";
|
||||
push @dhcpconf, "host $hostname {\n";
|
||||
push @dhcpconf, " hardware ethernet $mac;\n";
|
||||
push @dhcpconf, " fixed-address $ip;\n";
|
||||
push @dhcpconf, " $host_statements\n" if $host_statements;
|
||||
push @dhcpconf, "} #xCAT host declaration for $node aka host $hostname end\n";
|
||||
my $hardware_kind = $hardwaretype == 32 ? 'infiniband' : 'ethernet';
|
||||
push @{$config}, "#xCAT host declaration for $node aka host $hostname start\n";
|
||||
push @{$config}, "host $hostname {\n";
|
||||
push @{$config}, " hardware $hardware_kind $mac;\n";
|
||||
push @{$config}, " fixed-address $ip;\n";
|
||||
push @{$config}, " $host_statements\n" if $host_statements;
|
||||
push @{$config}, "}\n";
|
||||
push @{$config}, _infiniband_twin_static_lines(
|
||||
$hostname, $mac, $hardwaretype, $mgtifname, $ip,
|
||||
$host_statements, $has_infiniband_identity
|
||||
);
|
||||
push @{$config}, "#xCAT host declaration for $node aka host $hostname end\n";
|
||||
|
||||
$restartdhcp = 1;
|
||||
}
|
||||
@@ -491,6 +540,7 @@ sub delnode
|
||||
if ($ent and $ent->{mac})
|
||||
{
|
||||
my @macs = split(/\|/, $ent->{mac});
|
||||
my $has_infiniband_identity = _infiniband_identity_present(@macs);
|
||||
my $mace;
|
||||
my $count = 0;
|
||||
foreach $mace (@macs)
|
||||
@@ -505,13 +555,19 @@ sub delnode
|
||||
} #Default to hostname equal to nodename
|
||||
unless ($mac) { next; } #Skip corrupt format
|
||||
|
||||
if (!grep /:/, $mac) {
|
||||
my $normalized_mac = normalize_mac($mac);
|
||||
if ($normalized_mac) {
|
||||
$mac = $normalized_mac;
|
||||
} elsif (!grep /:/, $mac) {
|
||||
$mac = lc($mac);
|
||||
$mac =~ s/(\w{2})/$1:/g;
|
||||
$mac =~ s/:$//;
|
||||
}
|
||||
my $hostname = $hname;
|
||||
my %client_nethash = xCAT::DBobjUtils->getNetwkInfo([$node]);
|
||||
my $hardwaretype = _hardware_type_for(
|
||||
$mac, $client_nethash{$node}{mgtifname}
|
||||
);
|
||||
if ($client_nethash{$node}{mgtifname} =~ /hf/)
|
||||
{
|
||||
if (scalar(@macs) > 1) {
|
||||
@@ -532,14 +588,21 @@ sub delnode
|
||||
print $omshell "remove\n";
|
||||
print $omshell "close\n";
|
||||
|
||||
if ($mac)
|
||||
my ($ibnamecommands, $ibaddresscommands) =
|
||||
_infiniband_twin_delete_commands(
|
||||
$hostname, $mac, $hardwaretype,
|
||||
$client_nethash{$node}{mgtifname},
|
||||
_omapi_pre_create_cleanup_supported(),
|
||||
$has_infiniband_identity
|
||||
);
|
||||
print $omshell $ibnamecommands if ($ibnamecommands);
|
||||
|
||||
my $hardwarecommands =
|
||||
_hardware_address_delete_commands($mac, $hardwaretype);
|
||||
if ($hardwarecommands)
|
||||
{
|
||||
print $omshell "new host\n";
|
||||
print $omshell "set hardware-address = " . $mac
|
||||
. "\n"; #find and destroy mac conflict
|
||||
print $omshell "open\n";
|
||||
print $omshell "remove\n";
|
||||
print $omshell "close\n";
|
||||
print $omshell $hardwarecommands;
|
||||
print $omshell $ibaddresscommands if ($ibaddresscommands);
|
||||
}
|
||||
if ($inetn and _omapi_ip_lookup_supported())
|
||||
{
|
||||
@@ -649,6 +712,182 @@ sub addnode6 {
|
||||
|
||||
}
|
||||
|
||||
sub _infiniband_twin_mac
|
||||
{
|
||||
my $mac = shift;
|
||||
|
||||
$mac = normalize_mac($mac);
|
||||
return unless defined($mac) and length($mac) == 17;
|
||||
return substr($mac, 0, 8) . ":03:00" . substr($mac, 8);
|
||||
}
|
||||
|
||||
sub _infiniband_identity_present
|
||||
{
|
||||
foreach my $entry (@_) {
|
||||
my ($address) = split(/!/, $entry);
|
||||
$address = normalize_mac($address);
|
||||
return 1
|
||||
if defined($address)
|
||||
&& (length($address) == 23 || length($address) == 26);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
sub _hardware_type_for
|
||||
{
|
||||
my ($mac, $mgtifname) = @_;
|
||||
|
||||
return 37 if defined($mgtifname) && $mgtifname =~ /hf/;
|
||||
$mac = normalize_mac($mac) || $mac || '';
|
||||
return 32 if length($mac) == 23 || length($mac) == 26;
|
||||
return 1;
|
||||
}
|
||||
|
||||
sub _is_infiniband_interface
|
||||
{
|
||||
my $mgtifname = shift;
|
||||
return defined($mgtifname) && $mgtifname =~ /(?:^|!)ib[^!]*(?:!|$)/;
|
||||
}
|
||||
|
||||
sub _infiniband_twin_identity
|
||||
{
|
||||
my ($hostname, $mac, $hardwaretype, $mgtifname,
|
||||
$has_infiniband_identity) = @_;
|
||||
my $ibmac = _infiniband_twin_mac($mac);
|
||||
|
||||
return if $hardwaretype != 1
|
||||
|| !$ibmac
|
||||
|| !_is_infiniband_interface($mgtifname)
|
||||
|| $has_infiniband_identity;
|
||||
return ("$hostname-xcat-ib", $ibmac);
|
||||
}
|
||||
|
||||
sub _infiniband_twin_create_commands
|
||||
{
|
||||
my ($hostname, $mac, $hardwaretype, $mgtifname, $ip, $hoststatements,
|
||||
$cleanup_supported, $has_infiniband_identity) = @_;
|
||||
my ($ibhostname, $ibmac) = _infiniband_twin_identity(
|
||||
$hostname, $mac, $hardwaretype, $mgtifname,
|
||||
$has_infiniband_identity
|
||||
);
|
||||
|
||||
return unless $ibmac;
|
||||
|
||||
my $commands = '';
|
||||
if ($cleanup_supported && _is_infiniband_interface($mgtifname)) {
|
||||
$commands .= "new host\n"
|
||||
. "set name = \"$ibhostname\"\n"
|
||||
. "open\n"
|
||||
. "remove\n"
|
||||
. "close\n";
|
||||
}
|
||||
$commands .= "new host\n"
|
||||
. "set name = \"$ibhostname\"\n"
|
||||
. "set hardware-address = $ibmac\n"
|
||||
. "set dhcp-client-identifier = $ibmac\n"
|
||||
. "set hardware-type = 32\n";
|
||||
|
||||
if ($ip eq "DENIED") {
|
||||
$commands .= "set statements = \"deny booting;\"\n";
|
||||
} else {
|
||||
$commands .= "set ip-address = $ip\n" if ($ip);
|
||||
$commands .= "set statements = \"$hoststatements\"\n" if ($hoststatements);
|
||||
}
|
||||
|
||||
return $commands . "create\nclose\n";
|
||||
}
|
||||
|
||||
sub _infiniband_twin_static_lines
|
||||
{
|
||||
my ($hostname, $mac, $hardwaretype, $mgtifname, $ip, $hoststatements,
|
||||
$has_infiniband_identity) = @_;
|
||||
my ($ibhostname, $ibmac) = _infiniband_twin_identity(
|
||||
$hostname, $mac, $hardwaretype, $mgtifname,
|
||||
$has_infiniband_identity
|
||||
);
|
||||
|
||||
return unless $ibmac && $ip && $ip ne 'DENIED';
|
||||
|
||||
my @lines = (
|
||||
"host $ibhostname {\n",
|
||||
" hardware infiniband $ibmac;\n",
|
||||
" fixed-address $ip;\n",
|
||||
);
|
||||
push @lines, " $hoststatements\n" if $hoststatements;
|
||||
push @lines, "}\n";
|
||||
return @lines;
|
||||
}
|
||||
|
||||
sub _infiniband_twin_delete_commands
|
||||
{
|
||||
my ($hostname, $mac, $hardwaretype, $mgtifname, $cleanup_supported,
|
||||
$has_infiniband_identity) = @_;
|
||||
my $ibmac = _infiniband_twin_mac($mac);
|
||||
return unless $ibmac;
|
||||
if (!$cleanup_supported) {
|
||||
my (undef, $current_ibmac) = _infiniband_twin_identity(
|
||||
$hostname, $mac, $hardwaretype, $mgtifname,
|
||||
$has_infiniband_identity
|
||||
);
|
||||
return unless $current_ibmac;
|
||||
}
|
||||
my $ibhostname = "$hostname-xcat-ib";
|
||||
|
||||
my $namecommands = "new host\n"
|
||||
. "set name = \"$ibhostname\"\n"
|
||||
. "open\n"
|
||||
. "remove\n"
|
||||
. "close\n";
|
||||
my $addresscommands;
|
||||
|
||||
if ($cleanup_supported && _is_infiniband_interface($mgtifname)) {
|
||||
$addresscommands = "new host\n"
|
||||
. "set hardware-address = $ibmac\n"
|
||||
. "set hardware-type = 32\n"
|
||||
. "open\n"
|
||||
. "remove\n"
|
||||
. "close\n";
|
||||
}
|
||||
|
||||
return ($namecommands, $addresscommands);
|
||||
}
|
||||
|
||||
sub _hardware_address_delete_commands
|
||||
{
|
||||
my ($mac, $hardwaretype) = @_;
|
||||
return unless $mac;
|
||||
|
||||
my $commands = "new host\n"
|
||||
. "set hardware-address = $mac\n";
|
||||
$commands .= "set hardware-type = $hardwaretype\n"
|
||||
if $hardwaretype != 1;
|
||||
|
||||
return $commands . "open\nremove\nclose\n";
|
||||
}
|
||||
|
||||
sub _infiniband_twin_update_commands
|
||||
{
|
||||
my ($hostname, $mac, $hardwaretype, $mgtifname, $ip, $hoststatements,
|
||||
$cleanup_supported, $has_infiniband_identity) = @_;
|
||||
my ($namecommands, $addresscommands);
|
||||
|
||||
if ($cleanup_supported) {
|
||||
($namecommands, $addresscommands) =
|
||||
_infiniband_twin_delete_commands(
|
||||
$hostname, $mac, $hardwaretype, $mgtifname,
|
||||
$cleanup_supported, $has_infiniband_identity
|
||||
);
|
||||
undef $addresscommands if $has_infiniband_identity;
|
||||
}
|
||||
my $createcommands = _infiniband_twin_create_commands(
|
||||
$hostname, $mac, $hardwaretype, $mgtifname, $ip,
|
||||
$hoststatements, 0, $has_infiniband_identity
|
||||
);
|
||||
|
||||
return ($namecommands, $addresscommands, $createcommands);
|
||||
}
|
||||
|
||||
|
||||
sub addnode
|
||||
{
|
||||
|
||||
@@ -772,6 +1011,9 @@ sub addnode
|
||||
}
|
||||
|
||||
my @macs = split(/\|/, $ent->{mac});
|
||||
my $has_infiniband_identity = _infiniband_identity_present(@macs);
|
||||
my $static_host_fallback = _isc_static_host_fallback();
|
||||
my $static_host_update_started = 0;
|
||||
my $mace;
|
||||
my $deflstaments = $lstatements;
|
||||
my $count = 0;
|
||||
@@ -797,10 +1039,11 @@ sub addnode
|
||||
);
|
||||
next;
|
||||
}
|
||||
my $noip_mac = $mac;
|
||||
$mac = normalize_mac($mac);
|
||||
my $ip = getipaddr($hname, OnlyV4 => 1);
|
||||
if ($hname eq '*NOIP*') {
|
||||
$hname = $node . "-noip" . $mac;
|
||||
$hname =~ s/://g;
|
||||
$hname = _noip_hostname($node, $noip_mac);
|
||||
$ip = 'DENIED';
|
||||
|
||||
# } #if 'guess_next_server', inherit from the network provided value... see how this pans out
|
||||
@@ -928,17 +1171,13 @@ sub addnode
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!grep /:/, $mac) {
|
||||
$mac = lc($mac);
|
||||
$mac =~ s/(\w{2})/$1:/g;
|
||||
$mac =~ s/:$//;
|
||||
}
|
||||
my $hostname = $hname;
|
||||
my $hardwaretype = 1;
|
||||
my %client_nethash = xCAT::DBobjUtils->getNetwkInfo([$node]);
|
||||
if ($client_nethash{$node}{mgtifname} =~ /hf/)
|
||||
my $hardwaretype = _hardware_type_for(
|
||||
$mac, $client_nethash{$node}{mgtifname}
|
||||
);
|
||||
if ($hardwaretype == 37)
|
||||
{
|
||||
$hardwaretype = 37;
|
||||
if (scalar(@macs) > 1) {
|
||||
if ($hname !~ /^(.*)-hf(.*)$/) {
|
||||
$hostname = $hname . "-hf" . $count;
|
||||
@@ -946,27 +1185,35 @@ sub addnode
|
||||
$hostname = $1 . "-hf" . $count;
|
||||
}
|
||||
}
|
||||
} elsif (length($mac) == 23 || length($mac) == 26) { # 8 or 9 bytes of mac address
|
||||
# Currently the only thing that has 8 or 9 bytes is an infiniband
|
||||
# or infiniband like device, which is type 32 (0x20).
|
||||
$hardwaretype = 32;
|
||||
}
|
||||
|
||||
if (_isc_static_host_fallback()) {
|
||||
if ($static_host_fallback) {
|
||||
if ($ip ne "DENIED") {
|
||||
if ($lstatements) {
|
||||
$lstatements = 'ddns-hostname \"' . $node . '\"; send host-name \"' . $node . '\";' . $lstatements;
|
||||
} else {
|
||||
$lstatements = 'ddns-hostname \"' . $node . '\"; send host-name \"' . $node . '\";';
|
||||
}
|
||||
$lstatements = _node_host_statements($node, $lstatements);
|
||||
} else {
|
||||
$lstatements = "deny booting;";
|
||||
}
|
||||
_add_isc_static_host($node, $hostname, $mac, $ip, $lstatements);
|
||||
_add_isc_static_host(
|
||||
$node, $hostname, $mac, $hardwaretype,
|
||||
$client_nethash{$node}{mgtifname}, $ip, $lstatements,
|
||||
$has_infiniband_identity, undef,
|
||||
\$static_host_update_started
|
||||
);
|
||||
$count = $count + 2;
|
||||
next;
|
||||
}
|
||||
|
||||
if ($ip ne "DENIED") {
|
||||
$lstatements = _node_host_statements($node, $lstatements);
|
||||
}
|
||||
my ($ibnamecommands, $ibaddresscommands, $ibcreatecommands) =
|
||||
_infiniband_twin_update_commands(
|
||||
$hostname, $mac, $hardwaretype,
|
||||
$client_nethash{$node}{mgtifname}, $ip, $lstatements,
|
||||
_omapi_pre_create_cleanup_supported(),
|
||||
$has_infiniband_identity
|
||||
);
|
||||
|
||||
#syslog("local4|err", "Setting $node ($hname|$ip) to " . $mac);
|
||||
if (_omapi_pre_create_cleanup_supported()) {
|
||||
print $omshell "new host\n";
|
||||
@@ -975,6 +1222,7 @@ sub addnode
|
||||
print $omshell "open\n";
|
||||
print $omshell "remove\n";
|
||||
print $omshell "close\n";
|
||||
print $omshell $ibnamecommands if ($ibnamecommands);
|
||||
}
|
||||
if ($ip and $ip ne 'DENIED' and _omapi_ip_lookup_supported()) {
|
||||
print $omshell "new host\n";
|
||||
@@ -984,12 +1232,9 @@ sub addnode
|
||||
print $omshell "close\n";
|
||||
}
|
||||
if (_omapi_pre_create_cleanup_supported()) {
|
||||
print $omshell "new host\n";
|
||||
print $omshell "set hardware-address = " . $mac
|
||||
. "\n"; #find and destroy mac conflict
|
||||
print $omshell "open\n";
|
||||
print $omshell "remove\n";
|
||||
print $omshell "close\n";
|
||||
print $omshell
|
||||
_hardware_address_delete_commands($mac, $hardwaretype);
|
||||
print $omshell $ibaddresscommands if ($ibaddresscommands);
|
||||
}
|
||||
print $omshell "new host\n";
|
||||
print $omshell "set name = \"$hostname\"\n";
|
||||
@@ -1006,18 +1251,12 @@ sub addnode
|
||||
if ($ip) {
|
||||
print $omshell "set ip-address = $ip\n";
|
||||
}
|
||||
if ($lstatements)
|
||||
{
|
||||
$lstatements = 'ddns-hostname \"' . $node . '\"; send host-name \"' . $node . '\";' . $lstatements;
|
||||
|
||||
} else {
|
||||
$lstatements = 'ddns-hostname \"' . $node . '\"; send host-name \"' . $node . '\";';
|
||||
}
|
||||
print $omshell "set statements = \"$lstatements\"\n";
|
||||
}
|
||||
|
||||
print $omshell "create\n";
|
||||
print $omshell "close\n";
|
||||
print $omshell $ibcreatecommands if ($ibcreatecommands);
|
||||
unless ($::XCATSITEVALS{externaldhcpservers}) {
|
||||
unless (grep /#definition for host $node aka host $hostname/, @dhcpconf)
|
||||
{
|
||||
@@ -3319,7 +3558,7 @@ sub kea_xnba_client_classes_for_nodes
|
||||
);
|
||||
}
|
||||
|
||||
sub kea_normalize_mac
|
||||
sub normalize_mac
|
||||
{
|
||||
my ($mac) = @_;
|
||||
|
||||
@@ -3329,6 +3568,11 @@ sub kea_normalize_mac
|
||||
return lc($mac);
|
||||
}
|
||||
|
||||
sub kea_normalize_mac
|
||||
{
|
||||
return normalize_mac(shift);
|
||||
}
|
||||
|
||||
sub kea_node_reservations6
|
||||
{
|
||||
my ( $backend, $config, $node ) = @_;
|
||||
|
||||
@@ -0,0 +1,343 @@
|
||||
#!/usr/bin/env perl
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
use FindBin;
|
||||
use lib "$FindBin::Bin/../../xCAT-server/lib";
|
||||
use lib "$FindBin::Bin/../../xCAT-server/lib/perl";
|
||||
use lib "$FindBin::Bin/../../perl-xCAT";
|
||||
|
||||
use Test::More;
|
||||
|
||||
$ENV{XCATCFG} ||= 'SQLite:/tmp';
|
||||
|
||||
my $source_dhcp_plugin = "$FindBin::Bin/../../xCAT-server/lib/xcat/plugins/dhcp.pm";
|
||||
if ( -f $source_dhcp_plugin ) {
|
||||
require $source_dhcp_plugin;
|
||||
} else {
|
||||
require xCAT_plugin::dhcp;
|
||||
}
|
||||
|
||||
sub twin { return xCAT_plugin::dhcp::_infiniband_twin_mac( $_[0] ); }
|
||||
|
||||
is(
|
||||
xCAT_plugin::dhcp::normalize_mac('B8-3F-D2-4A-68-AA'),
|
||||
'b8:3f:d2:4a:68:aa',
|
||||
'the shared MAC normalizer canonicalizes case and separators',
|
||||
);
|
||||
is( twin('b8:3f:d2:4a:68:aa'), 'b8:3f:d2:03:00:4a:68:aa',
|
||||
'the port GUID of the first adapter is derived from its mac' );
|
||||
is( twin('b8:3f:d2:4a:68:b2'), 'b8:3f:d2:03:00:4a:68:b2',
|
||||
'the port GUID of the second adapter is derived from its mac' );
|
||||
is( twin('b8-3f-d2-4a-68-aa'), 'b8:3f:d2:03:00:4a:68:aa',
|
||||
'a dash-separated mac produces a canonical InfiniBand identity' );
|
||||
is( length( twin('b8:3f:d2:4a:68:aa') ), 23,
|
||||
'the derived address is eight bytes' );
|
||||
|
||||
foreach my $other ( 'b8:3f:d2:03:00:4a:68:aa', '00:11:22:33:44', '', 'notamac' ) {
|
||||
is( twin($other), undef, "'$other' gives no derived address" );
|
||||
}
|
||||
is( twin(undef), undef, 'no mac gives no derived address' );
|
||||
ok(
|
||||
xCAT_plugin::dhcp::_infiniband_identity_present(
|
||||
'b8:3f:d2:4a:68:aa!node01',
|
||||
'b8:3f:d2:03:00:4a:68:aa!node01-ib',
|
||||
),
|
||||
'an explicit InfiniBand identity is detected in a node mac list',
|
||||
);
|
||||
ok(
|
||||
!xCAT_plugin::dhcp::_infiniband_identity_present(
|
||||
'b83fd203004a68aa!node01-ib',
|
||||
),
|
||||
'a colonless address rejected by addnode is not treated as an identity',
|
||||
);
|
||||
ok(
|
||||
xCAT_plugin::dhcp::_infiniband_identity_present(
|
||||
'b8-3f-d2-03-00-4a-68-aa!node01-ib',
|
||||
),
|
||||
'a valid dashed InfiniBand identity is detected in a node mac list',
|
||||
);
|
||||
ok(
|
||||
!xCAT_plugin::dhcp::_infiniband_identity_present(
|
||||
'b8:3f:d2:4a:68:aa!node01',
|
||||
),
|
||||
'an Ethernet-only mac list needs the derived identity',
|
||||
);
|
||||
is(
|
||||
xCAT_plugin::dhcp::_hardware_type_for('b8:3f:d2:4a:68:aa', 'eth0'),
|
||||
1,
|
||||
'an Ethernet interface uses the Ethernet hardware type',
|
||||
);
|
||||
is(
|
||||
xCAT_plugin::dhcp::_hardware_type_for(
|
||||
'b8:3f:d2:03:00:4a:68:aa', 'ib0'
|
||||
),
|
||||
32,
|
||||
'an eight-byte fabric address uses the InfiniBand hardware type',
|
||||
);
|
||||
is(
|
||||
xCAT_plugin::dhcp::_hardware_type_for('b8:3f:d2:4a:68:aa', 'hf0'),
|
||||
37,
|
||||
'an HFI interface uses the HFI hardware type',
|
||||
);
|
||||
|
||||
is(
|
||||
xCAT_plugin::dhcp::_node_host_statements('node01', ''),
|
||||
'ddns-hostname \"node01\"; send host-name \"node01\";',
|
||||
'the default host statements identify the node',
|
||||
);
|
||||
is(
|
||||
xCAT_plugin::dhcp::_node_host_statements(
|
||||
'node01', 'filename = \"bootfile\";'
|
||||
),
|
||||
'ddns-hostname \"node01\"; send host-name \"node01\";filename = \"bootfile\";',
|
||||
'node identity is prepended to existing host statements',
|
||||
);
|
||||
is(
|
||||
xCAT_plugin::dhcp::_noip_hostname('node01', 'B8:3F:D2:4A:68:AA'),
|
||||
'node01-noipB83FD24A68AA',
|
||||
'the denied-host name preserves the legacy MAC case',
|
||||
);
|
||||
is(
|
||||
xCAT_plugin::dhcp::_noip_hostname('node01', 'B8-3F-D2-4A-68-AA'),
|
||||
'node01-noipB8-3F-D2-4A-68-AA',
|
||||
'the denied-host name preserves legacy dash separators',
|
||||
);
|
||||
|
||||
my $create_commands = <<'OMAPI';
|
||||
new host
|
||||
set name = "node01-xcat-ib"
|
||||
open
|
||||
remove
|
||||
close
|
||||
new host
|
||||
set name = "node01-xcat-ib"
|
||||
set hardware-address = b8:3f:d2:03:00:4a:68:aa
|
||||
set dhcp-client-identifier = b8:3f:d2:03:00:4a:68:aa
|
||||
set hardware-type = 32
|
||||
set ip-address = 192.0.2.10
|
||||
set statements = "ddns-hostname \"node01\"; send host-name \"node01\";"
|
||||
create
|
||||
close
|
||||
OMAPI
|
||||
|
||||
is(
|
||||
xCAT_plugin::dhcp::_infiniband_twin_create_commands(
|
||||
'node01', 'b8:3f:d2:4a:68:aa', 1, 'ib0', '192.0.2.10',
|
||||
'ddns-hostname \"node01\"; send host-name \"node01\";', 1, 0
|
||||
),
|
||||
$create_commands,
|
||||
'an Ethernet identity on an IPoIB network creates the InfiniBand twin',
|
||||
);
|
||||
|
||||
is(
|
||||
xCAT_plugin::dhcp::_infiniband_twin_create_commands(
|
||||
'node01', 'b8:3f:d2:4a:68:aa', 1, '!service!ib0', '192.0.2.10',
|
||||
'ddns-hostname \"node01\"; send host-name \"node01\";', 1, 0
|
||||
),
|
||||
$create_commands,
|
||||
'a relayed IPoIB interface creates the InfiniBand twin',
|
||||
);
|
||||
|
||||
is(
|
||||
xCAT_plugin::dhcp::_infiniband_twin_create_commands(
|
||||
'node01', 'b8:3f:d2:4a:68:aa', 1, 'ib0', 'DENIED', '', 1, 0
|
||||
),
|
||||
join( '', ( split( /^/m, $create_commands ) )[ 0 .. 9 ] )
|
||||
. "set statements = \"deny booting;\"\ncreate\nclose\n",
|
||||
'a denied Ethernet identity creates a denied InfiniBand twin',
|
||||
);
|
||||
|
||||
is(
|
||||
xCAT_plugin::dhcp::_infiniband_twin_create_commands(
|
||||
'node01', 'b8:3f:d2:4a:68:aa', 32, 'ib0', '192.0.2.10', '', 1, 1
|
||||
),
|
||||
undef,
|
||||
'an existing InfiniBand identity does not create another twin',
|
||||
);
|
||||
is(
|
||||
xCAT_plugin::dhcp::_infiniband_twin_create_commands(
|
||||
'node01', 'b8:3f:d2:4a:68:aa', 1, 'eth0', '192.0.2.10', '', 1, 0
|
||||
),
|
||||
undef,
|
||||
'an Ethernet network does not create an InfiniBand twin',
|
||||
);
|
||||
|
||||
my $create_without_cleanup = <<'OMAPI';
|
||||
new host
|
||||
set name = "node01-xcat-ib"
|
||||
set hardware-address = b8:3f:d2:03:00:4a:68:aa
|
||||
set dhcp-client-identifier = b8:3f:d2:03:00:4a:68:aa
|
||||
set hardware-type = 32
|
||||
set ip-address = 192.0.2.10
|
||||
set statements = "ddns-hostname \"node01\"; send host-name \"node01\";"
|
||||
create
|
||||
close
|
||||
OMAPI
|
||||
is(
|
||||
xCAT_plugin::dhcp::_infiniband_twin_create_commands(
|
||||
'node01', 'b8:3f:d2:4a:68:aa', 1, 'ib0', '192.0.2.10',
|
||||
'ddns-hostname \"node01\"; send host-name \"node01\";', 0, 0
|
||||
),
|
||||
$create_without_cleanup,
|
||||
'the Ubuntu-limited OMAPI path creates the twin without a failed-open cleanup',
|
||||
);
|
||||
my $create_without_address = $create_without_cleanup;
|
||||
$create_without_address =~ s/^set ip-address = .*\n//m;
|
||||
is(
|
||||
xCAT_plugin::dhcp::_infiniband_twin_create_commands(
|
||||
'node01', 'b8:3f:d2:4a:68:aa', 1, 'ib0', undef,
|
||||
'ddns-hostname \"node01\"; send host-name \"node01\";', 0, 0
|
||||
),
|
||||
$create_without_address,
|
||||
'an unresolved IP omits only the twin address',
|
||||
);
|
||||
is(
|
||||
xCAT_plugin::dhcp::_infiniband_twin_create_commands(
|
||||
'node01', 'b8:3f:d2:4a:68:aa', 1, 'ib0', '192.0.2.10', '', 1, 1
|
||||
),
|
||||
undef,
|
||||
'an explicit InfiniBand identity suppresses the derived twin',
|
||||
);
|
||||
|
||||
is_deeply(
|
||||
[ xCAT_plugin::dhcp::_infiniband_twin_static_lines(
|
||||
'node01', 'b8:3f:d2:4a:68:aa', 1, 'ib0', '192.0.2.10',
|
||||
'option host-name "node01";', 0
|
||||
) ],
|
||||
[
|
||||
"host node01-xcat-ib {\n",
|
||||
" hardware infiniband b8:3f:d2:03:00:4a:68:aa;\n",
|
||||
" fixed-address 192.0.2.10;\n",
|
||||
" option host-name \"node01\";\n",
|
||||
"}\n",
|
||||
],
|
||||
'the static-host fallback declares the derived InfiniBand identity',
|
||||
);
|
||||
|
||||
my $delete_name_commands = <<'OMAPI';
|
||||
new host
|
||||
set name = "node01-xcat-ib"
|
||||
open
|
||||
remove
|
||||
close
|
||||
OMAPI
|
||||
my $delete_address_commands = <<'OMAPI';
|
||||
new host
|
||||
set hardware-address = b8:3f:d2:03:00:4a:68:aa
|
||||
set hardware-type = 32
|
||||
open
|
||||
remove
|
||||
close
|
||||
OMAPI
|
||||
|
||||
is(
|
||||
xCAT_plugin::dhcp::_hardware_address_delete_commands(
|
||||
'b8:3f:d2:4a:68:aa', 1
|
||||
),
|
||||
"new host\nset hardware-address = b8:3f:d2:4a:68:aa\nopen\nremove\nclose\n",
|
||||
'Ethernet cleanup keeps the legacy hardware-address lookup',
|
||||
);
|
||||
is(
|
||||
xCAT_plugin::dhcp::_hardware_address_delete_commands(
|
||||
'b8:3f:d2:03:00:4a:68:aa', 32
|
||||
),
|
||||
$delete_address_commands,
|
||||
'InfiniBand cleanup includes its OMAPI hardware type',
|
||||
);
|
||||
|
||||
my @delete_commands = xCAT_plugin::dhcp::_infiniband_twin_delete_commands(
|
||||
'node01', 'b8:3f:d2:4a:68:aa', 1, 'ib0', 1, 0
|
||||
);
|
||||
is_deeply(
|
||||
\@delete_commands,
|
||||
[ $delete_name_commands, $delete_address_commands ],
|
||||
'removing a node produces separate name and address cleanup commands',
|
||||
);
|
||||
my @moved_network_delete_commands =
|
||||
xCAT_plugin::dhcp::_infiniband_twin_delete_commands(
|
||||
'node01', 'b8-3f-d2-4a-68-aa', 1, 'eth0', 1, 1
|
||||
);
|
||||
is_deeply(
|
||||
\@moved_network_delete_commands,
|
||||
[ $delete_name_commands, undef ],
|
||||
'removing a moved node cleans up its old twin by name only',
|
||||
);
|
||||
my @limited_delete_commands =
|
||||
xCAT_plugin::dhcp::_infiniband_twin_delete_commands(
|
||||
'node01', 'b8:3f:d2:4a:68:aa', 1, 'ib0', 0, 0
|
||||
);
|
||||
is_deeply(
|
||||
\@limited_delete_commands,
|
||||
[ $delete_name_commands, undef ],
|
||||
'the Ubuntu-limited OMAPI path still removes the twin by name',
|
||||
);
|
||||
my @limited_ethernet_delete_commands =
|
||||
xCAT_plugin::dhcp::_infiniband_twin_delete_commands(
|
||||
'node01', 'b8:3f:d2:4a:68:aa', 1, 'eth0', 0, 0
|
||||
);
|
||||
is_deeply(
|
||||
\@limited_ethernet_delete_commands,
|
||||
[],
|
||||
'the Ubuntu-limited OMAPI path avoids a failed-open cleanup on Ethernet',
|
||||
);
|
||||
|
||||
my @moved_network_update_commands =
|
||||
xCAT_plugin::dhcp::_infiniband_twin_update_commands(
|
||||
'node01', 'b8:3f:d2:4a:68:aa', 1, 'eth0', '192.0.2.10',
|
||||
'ddns-hostname \"node01\"; send host-name \"node01\";', 1, 0
|
||||
);
|
||||
is_deeply(
|
||||
\@moved_network_update_commands,
|
||||
[ $delete_name_commands, undef, undef ],
|
||||
're-registering a node on Ethernet removes its former twin by name only',
|
||||
);
|
||||
|
||||
my @infiniband_update_commands =
|
||||
xCAT_plugin::dhcp::_infiniband_twin_update_commands(
|
||||
'node01', 'b8:3f:d2:4a:68:aa', 1, 'ib0', '192.0.2.10',
|
||||
'ddns-hostname \"node01\"; send host-name \"node01\";', 1, 0
|
||||
);
|
||||
is_deeply(
|
||||
\@infiniband_update_commands,
|
||||
[ $delete_name_commands, $delete_address_commands, $create_without_cleanup ],
|
||||
're-registering an IPoIB node replaces its generated twin',
|
||||
);
|
||||
|
||||
my @limited_update_commands =
|
||||
xCAT_plugin::dhcp::_infiniband_twin_update_commands(
|
||||
'node01', 'b8:3f:d2:4a:68:aa', 1, 'ib0', '192.0.2.10',
|
||||
'ddns-hostname \"node01\"; send host-name \"node01\";', 0, 0
|
||||
);
|
||||
is_deeply(
|
||||
\@limited_update_commands,
|
||||
[ undef, undef, $create_without_cleanup ],
|
||||
'the limited OMAPI path does not attempt a failed-open cleanup',
|
||||
);
|
||||
|
||||
my @explicit_identity_update_commands =
|
||||
xCAT_plugin::dhcp::_infiniband_twin_update_commands(
|
||||
'node01', 'b8:3f:d2:4a:68:aa', 1, 'ib0', '192.0.2.10',
|
||||
'ddns-hostname \"node01\"; send host-name \"node01\";', 1, 1
|
||||
);
|
||||
is_deeply(
|
||||
\@explicit_identity_update_commands,
|
||||
[ $delete_name_commands, undef, undef ],
|
||||
'updating an explicit InfiniBand identity does not remove it by address',
|
||||
);
|
||||
|
||||
# The mgtifname of a network can name more than one interface, separated by !.
|
||||
# The InfiniBand interface is not always the last one, so a test that only
|
||||
# matches the last name leaves a node on ib0!eth0 without its second entry.
|
||||
foreach my $ifname (qw(ib0 ib0.8001 eth0!ib0 ib0!eth0 ib0!ib1 bond0!ib2)) {
|
||||
ok( xCAT_plugin::dhcp::_is_infiniband_interface($ifname),
|
||||
"'$ifname' is served by an InfiniBand interface" );
|
||||
}
|
||||
foreach my $ifname (qw(eth0 eth0!eth1 bond0 hf0)) {
|
||||
ok( !xCAT_plugin::dhcp::_is_infiniband_interface($ifname),
|
||||
"'$ifname' is not served by an InfiniBand interface" );
|
||||
}
|
||||
ok( !xCAT_plugin::dhcp::_is_infiniband_interface(undef),
|
||||
'a network with no interface name is not served by InfiniBand' );
|
||||
|
||||
done_testing();
|
||||
@@ -0,0 +1,184 @@
|
||||
#!/usr/bin/env perl
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
use FindBin;
|
||||
use lib "$FindBin::Bin/../../xCAT-server/lib";
|
||||
use lib "$FindBin::Bin/../../xCAT-server/lib/perl";
|
||||
use lib "$FindBin::Bin/../../perl-xCAT";
|
||||
|
||||
use Test::More;
|
||||
|
||||
$ENV{XCATCFG} ||= 'SQLite:/tmp';
|
||||
|
||||
my $source_dhcp_plugin = "$FindBin::Bin/../../xCAT-server/lib/xcat/plugins/dhcp.pm";
|
||||
if ( -f $source_dhcp_plugin ) {
|
||||
require $source_dhcp_plugin;
|
||||
} else {
|
||||
require xCAT_plugin::dhcp;
|
||||
}
|
||||
|
||||
my @config;
|
||||
|
||||
my @infiniband_config;
|
||||
xCAT_plugin::dhcp::_add_isc_static_host(
|
||||
'node00', 'node00', 'b8:3f:d2:03:00:4a:68:aa', 32,
|
||||
'ib0', '192.0.2.10', '', 1, \@infiniband_config,
|
||||
);
|
||||
like(
|
||||
join( '', @infiniband_config ),
|
||||
qr/^\s*hardware infiniband b8:3f:d2:03:00:4a:68:aa;$/m,
|
||||
'the static-host fallback keeps an explicit InfiniBand hardware type',
|
||||
);
|
||||
unlike(
|
||||
join( '', @infiniband_config ),
|
||||
qr/^\s*hardware ethernet b8:3f:d2:03:00:4a:68:aa;$/m,
|
||||
'the static-host fallback does not label an InfiniBand identity as Ethernet',
|
||||
);
|
||||
|
||||
my @dashed_mac_config;
|
||||
xCAT_plugin::dhcp::_add_isc_static_host(
|
||||
'node00', 'node00', 'B8-3F-D2-4A-68-AA', 1,
|
||||
'eth0', '192.0.2.11', '', 0, \@dashed_mac_config,
|
||||
);
|
||||
like(
|
||||
join( '', @dashed_mac_config ),
|
||||
qr/^\s*hardware ethernet b8:3f:d2:4a:68:aa;$/m,
|
||||
'the static-host fallback emits a valid canonical dashed MAC',
|
||||
);
|
||||
|
||||
xCAT_plugin::dhcp::_add_isc_static_host(
|
||||
'node01', 'node01', '00:11:22:33:44:55', 1,
|
||||
'eth0', '192.0.2.1', '', 0, \@config,
|
||||
);
|
||||
xCAT_plugin::dhcp::_add_isc_static_host(
|
||||
'node02', 'node02', '00:11:22:33:44:66', 1,
|
||||
'eth0', '192.0.2.2', '', 0, \@config,
|
||||
);
|
||||
|
||||
like(
|
||||
join( '', @config ),
|
||||
qr/^#xCAT host declaration for node01 aka host node01 end$/m,
|
||||
'the static host end marker occupies its own line',
|
||||
);
|
||||
|
||||
xCAT_plugin::dhcp::_delete_isc_static_host('node01', \@config);
|
||||
my $remaining = join( '', @config );
|
||||
unlike($remaining, qr/\bnode01\b/, 'the selected static host is removed');
|
||||
like($remaining, qr/\bnode02\b/, 'the following static host is preserved');
|
||||
|
||||
my @legacy_config = (
|
||||
"#xCAT host declaration for node01 aka host node01 start\n",
|
||||
"host node01 {\n",
|
||||
" hardware ethernet 00:11:22:33:44:55;\n",
|
||||
" fixed-address 192.0.2.1;\n",
|
||||
"} #xCAT host declaration for node01 aka host node01 end\n",
|
||||
"#xCAT host declaration for node02 aka host node02 start\n",
|
||||
"host node02 {\n",
|
||||
" hardware ethernet 00:11:22:33:44:66;\n",
|
||||
" fixed-address 192.0.2.2;\n",
|
||||
"} #xCAT host declaration for node02 aka host node02 end\n",
|
||||
);
|
||||
xCAT_plugin::dhcp::_delete_isc_static_host('node01', \@legacy_config);
|
||||
my $legacy_remaining = join( '', @legacy_config );
|
||||
unlike($legacy_remaining, qr/\bnode01\b/,
|
||||
'a static host written by an older xCAT release is removed');
|
||||
like($legacy_remaining, qr/\bnode02\b/,
|
||||
'deleting an old-format host preserves the following host');
|
||||
|
||||
my @multi_host_config;
|
||||
xCAT_plugin::dhcp::_add_isc_static_host(
|
||||
'node03', 'node03', '00:11:22:33:44:77', 1,
|
||||
'eth0', '192.0.2.3', '', 0, \@multi_host_config,
|
||||
);
|
||||
xCAT_plugin::dhcp::_add_isc_static_host(
|
||||
'node03', 'node03-ib', '00:11:22:33:44:88', 32,
|
||||
'ib0', '192.0.2.3', '', 1, \@multi_host_config,
|
||||
);
|
||||
my $multi_host = join( '', @multi_host_config );
|
||||
like($multi_host, qr/^host node03 \{$/m,
|
||||
'adding a second identity preserves the first host for a node');
|
||||
like($multi_host, qr/^host node03-ib \{$/m,
|
||||
'adding a second identity records its own host for the node');
|
||||
|
||||
my @prefix_config;
|
||||
xCAT_plugin::dhcp::_add_isc_static_host(
|
||||
'node01', 'node01', '00:11:22:33:44:99', 1,
|
||||
'eth0', '192.0.2.1', '', 0, \@prefix_config,
|
||||
);
|
||||
xCAT_plugin::dhcp::_add_isc_static_host(
|
||||
'node01-ib', 'node01-ib', '00:11:22:33:44:aa', 1,
|
||||
'eth0', '192.0.2.4', '', 0, \@prefix_config,
|
||||
);
|
||||
xCAT_plugin::dhcp::_delete_isc_static_host('node01', \@prefix_config);
|
||||
my $prefix_remaining = join( '', @prefix_config );
|
||||
unlike($prefix_remaining, qr/^host node01 \{$/m,
|
||||
'node-wide deletion removes the exact node');
|
||||
like($prefix_remaining, qr/^host node01-ib \{$/m,
|
||||
'node-wide deletion preserves a node with the same prefix');
|
||||
|
||||
my @replacement_config;
|
||||
xCAT_plugin::dhcp::_add_isc_static_host(
|
||||
'node04', 'node04-old', '00:11:22:33:44:bb', 1,
|
||||
'eth0', '192.0.2.5', '', 0, \@replacement_config,
|
||||
);
|
||||
xCAT_plugin::dhcp::_add_isc_static_host(
|
||||
'node04', 'node04-old-ib', '00:11:22:33:44:cc', 32,
|
||||
'ib0', '192.0.2.5', '', 1, \@replacement_config,
|
||||
);
|
||||
xCAT_plugin::dhcp::_add_isc_static_host(
|
||||
'node05', 'node05', '00:11:22:33:44:dd', 1,
|
||||
'eth0', '192.0.2.6', '', 0, \@replacement_config,
|
||||
);
|
||||
ok(
|
||||
xCAT_plugin::dhcp::_begin_isc_static_host_update(
|
||||
'node04', 1, \@replacement_config,
|
||||
),
|
||||
'removing stale identities marks the static configuration as changed',
|
||||
);
|
||||
xCAT_plugin::dhcp::_add_isc_static_host(
|
||||
'node04', 'node04-current', '00:11:22:33:44:ee', 1,
|
||||
'eth0', '192.0.2.5', '', 0, \@replacement_config,
|
||||
);
|
||||
my $replacement = join( '', @replacement_config );
|
||||
unlike($replacement, qr/^host node04-old(?:-ib)? \{$/m,
|
||||
're-registering a node removes identities that are no longer present');
|
||||
like($replacement, qr/^host node04-current \{$/m,
|
||||
're-registering a node writes its current identity');
|
||||
like($replacement, qr/^host node05 \{$/m,
|
||||
're-registering a node preserves other nodes');
|
||||
ok(
|
||||
!xCAT_plugin::dhcp::_begin_isc_static_host_update(
|
||||
'node04', 0, \@replacement_config,
|
||||
),
|
||||
'a disabled static update leaves the configuration unchanged',
|
||||
);
|
||||
|
||||
my @lazy_config;
|
||||
xCAT_plugin::dhcp::_add_isc_static_host(
|
||||
'node06', 'node06-old', '00:11:22:33:44:11', 1,
|
||||
'eth0', '192.0.2.7', '', 0, \@lazy_config,
|
||||
);
|
||||
my $before_failed_update = join( '', @lazy_config );
|
||||
my $update_started = 0;
|
||||
xCAT_plugin::dhcp::_add_isc_static_host(
|
||||
'node06', 'node06-current', '00:11:22:33:44:22', 1,
|
||||
'eth0', undef, '', 0, \@lazy_config, \$update_started,
|
||||
);
|
||||
is(join( '', @lazy_config ), $before_failed_update,
|
||||
'an unresolved replacement preserves the existing static host');
|
||||
is($update_started, 0,
|
||||
'an unresolved replacement does not begin the static update');
|
||||
xCAT_plugin::dhcp::_add_isc_static_host(
|
||||
'node06', 'node06-current', '00:11:22:33:44:22', 1,
|
||||
'eth0', '192.0.2.8', '', 0, \@lazy_config, \$update_started,
|
||||
);
|
||||
my $lazy_replacement = join( '', @lazy_config );
|
||||
unlike($lazy_replacement, qr/^host node06-old \{$/m,
|
||||
'the first valid replacement removes stale node identities');
|
||||
like($lazy_replacement, qr/^host node06-current \{$/m,
|
||||
'the first valid replacement writes the current identity');
|
||||
is($update_started, 1,
|
||||
'the successful replacement records that cleanup has started');
|
||||
|
||||
done_testing();
|
||||
Reference in New Issue
Block a user