mirror of
https://github.com/xcat2/xcat-core.git
synced 2026-09-04 20:17:55 +00:00
Merge pull request #7782 from VersatusHPC/fix/template-install-device
fix(template): honour installnic when the kickstart names the install device
This commit is contained in:
@@ -1052,13 +1052,23 @@ sub kickstartnetwork {
|
||||
unless ($mactab) { $tmplerr = "mac table should always exist prior to template processing when doing autoula"; return; }
|
||||
my $ent = $mactab->getNodeAttribs($node, ['mac'], prefetchcache => 1);
|
||||
unless ($ent and $ent->{mac}) { $tmplerr = "missing mac data for $node"; return; }
|
||||
my $suffix = xCAT::Utils->parseMacTabEntry($ent->{mac}, $node);
|
||||
$suffix = lc($suffix);
|
||||
my ($installnic, $primarynic);
|
||||
my $nrtab = xCAT::Table->new('noderes', -create => 0);
|
||||
if ($nrtab) {
|
||||
my $nrent = $nrtab->getNodeAttribs($node, [ 'installnic', 'primarynic' ], prefetchcache => 1);
|
||||
if ($nrent) {
|
||||
$installnic = $nrent->{installnic};
|
||||
$primarynic = $nrent->{primarynic};
|
||||
}
|
||||
}
|
||||
my $params = install_device_params($installnic, $primarynic, $ent->{mac}, $node);
|
||||
my $macaddr = defined($params->{mac}) ? lc($params->{mac}) : '';
|
||||
my $suffix = defined($params->{nicname}) ? $params->{nicname} : $macaddr;
|
||||
|
||||
if ($::XCATSITEVALS{managedaddressmode} eq "autoula") {
|
||||
unless ($hoststab) { $hoststab = xCAT::Table->new('hosts', -create => 1); }
|
||||
$line .= "static --device=$suffix --noipv4 --ipv6=";
|
||||
my $ulaaddr = autoulaaddress($suffix);
|
||||
my $ulaaddr = autoulaaddress($macaddr);
|
||||
$hoststab->setNodeAttribs($node, { ip => $ulaaddr });
|
||||
$line .= $ulaaddr;
|
||||
} elsif ($::XCATSITEVALS{managedaddressmode} =~ /static/) {
|
||||
@@ -1664,19 +1674,47 @@ sub crydb_or_locked
|
||||
|
||||
#--------------------------------------------------------------------------------
|
||||
|
||||
=head3 subiquity_install_netcfg
|
||||
=head3 install_device_params
|
||||
|
||||
Resolve the interface the INSTALLED system must bring up, in xCAT's own order:
|
||||
noderes.installnic, else noderes.primarynic, else match on mac.mac. Either attribute may name
|
||||
an interface OR carry a MAC address. xCAT::NetworkUtils::gen_net_boot_params already owns that
|
||||
order for the netboot kernel parameters, so it is reused here rather than re-derived -- and in
|
||||
particular the install template never re-derives any part of it in shell.
|
||||
particular an install template never re-derives any part of it in shell.
|
||||
|
||||
Every install template that has to name the install device shares this resolution, so the
|
||||
device an installer configures cannot disagree with the device the netboot kernel parameters
|
||||
name. The resolution carries no boot loader dependency of any kind.
|
||||
|
||||
Arguments:
|
||||
$installnic - noderes.installnic (may be undef or empty)
|
||||
$primarynic - noderes.primarynic (may be undef or empty)
|
||||
$macentry - the raw mac.mac entry (may hold |-separated, !hostname-suffixed entries)
|
||||
$nodename - the node the entry is resolved for
|
||||
Returns:
|
||||
the hash reference from gen_net_boot_params. Of interest to install templates:
|
||||
nicname - the interface name, set only when installnic/primarynic names an interface
|
||||
mac - the address, set whenever one is known
|
||||
|
||||
=cut
|
||||
|
||||
#--------------------------------------------------------------------------------
|
||||
sub install_device_params {
|
||||
my ($installnic, $primarynic, $macentry, $nodename) = @_;
|
||||
|
||||
my $macmac = xCAT::Utils->parseMacTabEntry(defined($macentry) ? $macentry : '', $nodename);
|
||||
return xCAT::NetworkUtils->gen_net_boot_params($installnic, $primarynic, $macmac);
|
||||
}
|
||||
|
||||
#--------------------------------------------------------------------------------
|
||||
|
||||
=head3 subiquity_install_netcfg
|
||||
|
||||
Shape install_device_params for netplan, which matches a device by MAC and optionally renames
|
||||
it.
|
||||
|
||||
Arguments:
|
||||
as install_device_params
|
||||
Returns:
|
||||
($setname, $macaddress)
|
||||
$setname - the name netplan must rename the matched device to, empty when the device is
|
||||
@@ -1689,8 +1727,7 @@ sub crydb_or_locked
|
||||
sub subiquity_install_netcfg {
|
||||
my ($installnic, $primarynic, $macentry, $nodename) = @_;
|
||||
|
||||
my $macmac = xCAT::Utils->parseMacTabEntry(defined($macentry) ? $macentry : '', $nodename);
|
||||
my $params = xCAT::NetworkUtils->gen_net_boot_params($installnic, $primarynic, $macmac);
|
||||
my $params = install_device_params($installnic, $primarynic, $macentry, $nodename);
|
||||
|
||||
my $setname = defined($params->{nicname}) ? $params->{nicname} : '';
|
||||
my $macaddress = defined($params->{mac}) ? lc($params->{mac}) : '';
|
||||
|
||||
@@ -0,0 +1,156 @@
|
||||
#!/usr/bin/env perl
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
use File::Spec;
|
||||
use FindBin;
|
||||
use Test::More;
|
||||
|
||||
BEGIN {
|
||||
push @INC,
|
||||
File::Spec->catdir( $FindBin::Bin, '..', '..', 'perl-xCAT' ),
|
||||
File::Spec->catdir( $FindBin::Bin, '..', '..', 'xCAT-server', 'lib', 'perl' );
|
||||
}
|
||||
|
||||
eval { require xCAT::Template; 1 }
|
||||
or plan skip_all => "xCAT::Template not loadable: $@";
|
||||
|
||||
my $NODE = 'n1';
|
||||
my $MAC1 = 'AA:BB:CC:DD:EE:01';
|
||||
my $MAC2 = 'AA:BB:CC:DD:EE:02';
|
||||
|
||||
# The order is installnic, then primarynic, then mac.mac. Either attribute may
|
||||
# name an interface or carry an address.
|
||||
my $p = xCAT::Template::install_device_params( '', '', $MAC1, $NODE );
|
||||
is( $p->{mac}, $MAC1, 'with neither attribute set the address comes from mac.mac' );
|
||||
is( $p->{nicname}, undef, 'with neither attribute set no interface is named' );
|
||||
|
||||
$p = xCAT::Template::install_device_params( 'eth1', '', $MAC1, $NODE );
|
||||
is( $p->{nicname}, 'eth1', 'installnic naming an interface wins' );
|
||||
is( $p->{mac}, $MAC1, 'the address is still resolved alongside the interface' );
|
||||
|
||||
$p = xCAT::Template::install_device_params( '', 'eth2', $MAC1, $NODE );
|
||||
is( $p->{nicname}, 'eth2', 'primarynic is used when installnic is not set' );
|
||||
|
||||
$p = xCAT::Template::install_device_params( 'eth1', 'eth2', $MAC1, $NODE );
|
||||
is( $p->{nicname}, 'eth1', 'installnic beats primarynic' );
|
||||
|
||||
$p = xCAT::Template::install_device_params( $MAC2, '', $MAC1, $NODE );
|
||||
is( $p->{mac}, $MAC2, 'installnic carrying an address names that address' );
|
||||
is( $p->{nicname}, undef, 'installnic carrying an address names no interface' );
|
||||
|
||||
$p = xCAT::Template::install_device_params( 'mac', '', $MAC1, $NODE );
|
||||
is( $p->{mac}, $MAC1, 'the keyword mac falls back to mac.mac' );
|
||||
is( $p->{nicname}, undef, 'the keyword mac names no interface' );
|
||||
|
||||
# A mac.mac entry may hold several addresses. The entry tagged with the node
|
||||
# name is the one that belongs to the node.
|
||||
$p = xCAT::Template::install_device_params( '', '', "$MAC1!$NODE|$MAC2!other", $NODE );
|
||||
is( $p->{mac}, $MAC1, 'the tagged entry for the node is selected' );
|
||||
|
||||
# Ubuntu keeps its own return shape over the same resolution.
|
||||
my ( $setname, $macaddress ) =
|
||||
xCAT::Template::subiquity_install_netcfg( 'eth1', '', $MAC1, $NODE );
|
||||
is( $setname, 'eth1', 'netplan is given the interface to rename to' );
|
||||
is( $macaddress, lc($MAC1), 'netplan is given the address, lower cased' );
|
||||
|
||||
( $setname, $macaddress ) =
|
||||
xCAT::Template::subiquity_install_netcfg( '', '', $MAC1, $NODE );
|
||||
is( $setname, '', 'netplan renames nothing when no interface is named' );
|
||||
is( $macaddress, lc($MAC1), 'netplan still matches on the address' );
|
||||
|
||||
{
|
||||
package Local::TemplateInstallTable;
|
||||
|
||||
sub getNodeAttribs {
|
||||
my ($self) = @_;
|
||||
return $self->{row};
|
||||
}
|
||||
|
||||
sub setNodeAttribs {
|
||||
my ( $self, undef, $attrs ) = @_;
|
||||
$self->{written} = { %{$attrs} };
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
# Exercise kickstartnetwork itself with in-memory table objects. This verifies
|
||||
# the generated kickstart line rather than the text of Template.pm.
|
||||
sub kickstart_network {
|
||||
my ( $installnic, $primarynic, $macentry, $mode ) = @_;
|
||||
|
||||
my $mactab = bless { row => { mac => $macentry } }, 'Local::TemplateInstallTable';
|
||||
my $nrtab = bless {
|
||||
row => {
|
||||
installnic => $installnic,
|
||||
primarynic => $primarynic,
|
||||
}
|
||||
},
|
||||
'Local::TemplateInstallTable';
|
||||
my $hoststab = bless {}, 'Local::TemplateInstallTable';
|
||||
my $autoula_mac;
|
||||
|
||||
no warnings qw(redefine once);
|
||||
local *xCAT::Table::new = sub {
|
||||
my ( undef, $table ) = @_;
|
||||
return $mactab if $table eq 'mac';
|
||||
return $nrtab if $table eq 'noderes';
|
||||
return $hoststab if $table eq 'hosts';
|
||||
die "Unexpected table $table";
|
||||
};
|
||||
local *xCAT::Template::autoulaaddress = sub {
|
||||
($autoula_mac) = @_;
|
||||
return 'fd00::1';
|
||||
};
|
||||
local $::XCATSITEVALS{managedaddressmode} = $mode || 'dhcp';
|
||||
|
||||
my $line = xCAT::Template::kickstartnetwork();
|
||||
return ( $line, $autoula_mac, $hoststab->{written} );
|
||||
}
|
||||
|
||||
sub ks_device {
|
||||
my ($line) = kickstart_network(@_);
|
||||
return $line =~ /--device=(\S+)/ ? $1 : undef;
|
||||
}
|
||||
|
||||
is( ks_device( '', '', $MAC1 ), lc($MAC1),
|
||||
'a node setting neither attribute keeps the address it has today' );
|
||||
is( ks_device( 'eth1', '', $MAC1 ), 'eth1',
|
||||
'a node setting installnic names that interface' );
|
||||
is( ks_device( $MAC2, '', $MAC1 ), lc($MAC2),
|
||||
'a node whose installnic carries an address names that address' );
|
||||
|
||||
# The defect this closes: a bare multi address entry resolves to the LAST
|
||||
# address, which need not be the adapter that deploys the node. Setting
|
||||
# installnic must override that.
|
||||
my $BARE = "$MAC1|$MAC2";
|
||||
is( ks_device( '', '', $BARE ), lc($MAC2),
|
||||
'a bare multi address entry alone still resolves to the last address' );
|
||||
is( ks_device( 'eth0', '', $BARE ), 'eth0',
|
||||
'installnic overrides a bare multi address entry' );
|
||||
|
||||
# An interface name is case sensitive. A node on POWER carries names such as
|
||||
# enP1p12s0f0, which no longer name a device once they are lower cased. Only
|
||||
# an address may be lower cased.
|
||||
my $MIXED = 'enP1p12s0f0';
|
||||
is( ks_device( $MIXED, '', $MAC1 ), $MIXED,
|
||||
'the kickstart keeps the case of the interface name' );
|
||||
is( ks_device( '', $MIXED, $MAC1 ), $MIXED,
|
||||
'the kickstart keeps the case of a primarynic interface name' );
|
||||
my ($mixedset) = xCAT::Template::subiquity_install_netcfg( $MIXED, '', $MAC1, $NODE );
|
||||
is( $mixedset, $MIXED, 'Ubuntu keeps the case of the interface name too' );
|
||||
is( ks_device( '', '', uc($MAC1) ), lc($MAC1),
|
||||
'an address is still lower cased' );
|
||||
|
||||
# autoula must derive the address from the hardware address even when the
|
||||
# kickstart selects an interface by name.
|
||||
my ( $autoula_line, $autoula_mac, $hostattrs ) =
|
||||
kickstart_network( $MIXED, '', $MAC1, 'autoula' );
|
||||
is( $autoula_line,
|
||||
"network --onboot=yes --bootproto=static --device=$MIXED --noipv4 --ipv6=fd00::1",
|
||||
'autoula keeps the selected interface in the kickstart line' );
|
||||
is( $autoula_mac, lc($MAC1),
|
||||
'autoula derives the address from the MAC, not the interface name' );
|
||||
is( $hostattrs->{ip}, 'fd00::1', 'the generated ULA is saved in the hosts table' );
|
||||
|
||||
done_testing();
|
||||
Reference in New Issue
Block a user