c8b1b3219c
2. import hostinfo file format should support windows txt file 3. If no dynamic range set, display an error message while start auto discover. 4. distinguish error codes for arguments validation and hostinfo file validation errors: 1 for arguments validation failure, 2 for hostinfo file parse. 5. support hostname format validation. git-svn-id: https://svn.code.sf.net/p/xcat/code/xcat-core/trunk@14144 8638fb3e-16cb-4fca-ae20-7b5d299a9bcd
548 lines
19 KiB
Perl
548 lines
19 KiB
Perl
# IBM(c) 2012 EPL license http://www.eclipse.org/legal/epl-v10.html
|
|
package xCAT::ProfiledNodeUtils;
|
|
|
|
use strict;
|
|
use warnings;
|
|
use Socket;
|
|
use File::Path qw/mkpath/;
|
|
use File::Temp qw/tempfile/;
|
|
use Fcntl qw(:flock);
|
|
require xCAT::Table;
|
|
require xCAT::TableUtils;
|
|
require xCAT::NodeRange;
|
|
require xCAT::NetworkUtils;
|
|
require xCAT::DBobjUtils;
|
|
|
|
|
|
#--------------------------------------------------------------------------------
|
|
|
|
=head1 xCAT::ProfiledNodeUtils
|
|
|
|
=head2 Package Description
|
|
|
|
This program module file, is a set of node management utilities for Profile based nodes.
|
|
|
|
=cut
|
|
|
|
#-------------------------------------------------------------------------------
|
|
|
|
#-------------------------------------------------------------------------------
|
|
|
|
=head3 get_allocable_staticips_innet
|
|
Description : Get allocable IPs from a network.
|
|
Arguments : $netname - network name
|
|
$exclude_ips_ref - excluded IPs list reference.
|
|
Returns : Reference of allocable IPs list
|
|
=cut
|
|
|
|
#-------------------------------------------------------------------------------
|
|
sub get_allocable_staticips_innet
|
|
{
|
|
my $class = shift;
|
|
my $netname = shift;
|
|
my $exclude_ips_ref = shift;
|
|
my %iphash;
|
|
my @allocableips;
|
|
|
|
foreach (@$exclude_ips_ref){
|
|
$iphash{$_} = 0;
|
|
}
|
|
|
|
my $networkstab = xCAT::Table->new('networks');
|
|
my $netentry = ($networkstab->getAllAttribsWhere("netname = '$netname'", 'ALL'))[0];
|
|
my ($startip, $endip) = split('-', $netentry->{'staticrange'});
|
|
my $incremental = $netentry->{'staticrangeincrement'};
|
|
my $validipsref;
|
|
if ($incremental and $startip and $endip){
|
|
$validipsref = xCAT::NetworkUtils->get_allips_in_range($startip, $endip, $incremental);
|
|
}
|
|
foreach (@$validipsref){
|
|
if (! exists($iphash{$_})){
|
|
push @allocableips, $_;
|
|
}
|
|
}
|
|
return \@allocableips;
|
|
}
|
|
|
|
#-------------------------------------------------------------------------------
|
|
|
|
=head3 genhosts_with_numric_tmpl
|
|
Description : Generate numric hostnames using numric template name.
|
|
Arguments : $format - The hostname format string..
|
|
$rank - The start number.
|
|
Returns : numric hostname list
|
|
Example :
|
|
calling genhosts_with_numric_tmpl("compute#NNnode") will return a list like:
|
|
("compute00node", "compute01node", ..."compute98node", "compute99node")
|
|
=cut
|
|
|
|
#-------------------------------------------------------------------------------
|
|
sub genhosts_with_numric_tmpl
|
|
{
|
|
my ($class, $format, $rank) = @_;
|
|
|
|
my ($prefix, $appendix, $len) = xCAT::ProfiledNodeUtils->split_hostname($format, 'N');
|
|
return xCAT::ProfiledNodeUtils->gen_numric_hostnames($prefix, $appendix, $len, $rank);
|
|
}
|
|
|
|
#-------------------------------------------------------------------------------
|
|
|
|
=head3 split_hostname
|
|
Description : Split hostname format as prefix, appendix and number length.
|
|
Arguments : $format - hostname format
|
|
$patt_char - pattern char, we always use "N" to indicate numric pattern
|
|
Returns : ($prefix, $appendix, $numlen)
|
|
$prefix - the prefix string of hostname format.
|
|
$appendix - the appendix string of hostname format
|
|
$numlen - The number length in hostname format.
|
|
Example :
|
|
calling split_hostname("compute#NNnode") will return a list like:
|
|
("compute", "node", 2)
|
|
=cut
|
|
|
|
#-------------------------------------------------------------------------------
|
|
sub split_hostname
|
|
{
|
|
my ($class, $format, $patt_char) = @_;
|
|
|
|
my $idx = index $format, "#$patt_char";
|
|
my @array_format = split(//, $format);
|
|
my $pos = $idx+2;
|
|
while ( $pos <= (scalar(@array_format) - 1)){
|
|
if ($array_format[$pos] eq "$patt_char"){
|
|
$pos++;
|
|
}else{
|
|
last;
|
|
}
|
|
}
|
|
my $ridx = $pos - 1;
|
|
|
|
my $prefix = "";
|
|
$prefix = substr $format, 0, $idx;
|
|
my $appendix = "";
|
|
if (($ridx + 1) != scalar(@array_format)){
|
|
$appendix = substr $format, $ridx + 1;
|
|
}
|
|
return $prefix, $appendix, ($ridx - $idx);
|
|
}
|
|
|
|
#-------------------------------------------------------------------------------
|
|
|
|
=head3 gen_numric_hostnames
|
|
Description : Generate numric hostnames.
|
|
Arguments : $prefix - The prefix string of the hostname.
|
|
$appendix - The appendix string of the hostname.
|
|
$len - the numric number length in hostname.
|
|
Returns : numric hostname list
|
|
Example :
|
|
calling gen_numric_hostnames("compute", "node",2) will return a list like:
|
|
("compute00node", "compute01node", ..."compute98node", "compute99node")
|
|
=cut
|
|
|
|
#-------------------------------------------------------------------------------
|
|
sub gen_numric_hostnames
|
|
{
|
|
my ($class, $prefix, $appendix, $len, $rank) = @_;
|
|
my @hostnames;
|
|
my $cnt = 0;
|
|
|
|
if ($rank){
|
|
$cnt = $rank;
|
|
}
|
|
my $maxnum = 10 ** $len;
|
|
while($cnt < $maxnum)
|
|
{
|
|
my $fullnum = $maxnum + $cnt;
|
|
my $hostname = $prefix.(substr $fullnum, 1).$appendix;
|
|
push (@hostnames, $hostname);
|
|
$cnt++;
|
|
}
|
|
return \@hostnames;
|
|
}
|
|
|
|
#-------------------------------------------------------------------------------
|
|
|
|
=head3 get_hostname_format_type
|
|
Description : Get hostname format type.
|
|
Arguments : $format - hostname format
|
|
Returns : hostname format type value:
|
|
"numric" - numric hostname format.
|
|
"rack" - rack info hostname format.
|
|
Example :
|
|
calling get_hostname_format_type("compute#NNnode") will return "numric"
|
|
calling get_hostname_format_type("compute-#RR-#NN") will return "rack"
|
|
=cut
|
|
|
|
#-------------------------------------------------------------------------------
|
|
sub get_hostname_format_type{
|
|
my ($class, $format) = @_;
|
|
my $type;
|
|
|
|
my $ridx = index $format, "#R";
|
|
my $nidx = index $format, "#N";
|
|
if ($ridx >= 0){
|
|
$type = "rack";
|
|
} elsif ($nidx >= 0){
|
|
$type = "numric";
|
|
} else{
|
|
$type = "unknown";
|
|
}
|
|
|
|
return $type;
|
|
}
|
|
|
|
#-------------------------------------------------------------------------------
|
|
|
|
=head3 rackformat_to_numricformat
|
|
Description : convert rack hostname format into numric hostname format.
|
|
Arguments : $format - rack hostname format
|
|
$racknum - rack number.
|
|
Returns : numric hostname format.
|
|
Example :
|
|
calling rackformat_to_numricformat("compute-#RR-#NN", 1) will return "compute-01-#NN"
|
|
=cut
|
|
|
|
#-------------------------------------------------------------------------------
|
|
sub rackformat_to_numricformat{
|
|
my ($class, $format, $rackname) = @_;
|
|
my ($prefix, $appendix, $len) = xCAT::ProfiledNodeUtils->split_hostname($format, 'R');
|
|
|
|
my %objhash = xCAT::DBobjUtils->getobjdefs({$rackname, "rack"});
|
|
my $racknum = $objhash{$rackname}{"num"};
|
|
my $maxnum = 10 ** $len;
|
|
my $fullnum = $maxnum + $racknum;
|
|
return $prefix.(substr $fullnum, 1).$appendix;
|
|
}
|
|
|
|
#-------------------------------------------------------------------------------
|
|
|
|
=head3 get_nodes_nic_attrs
|
|
Description : Get nodes NIC attributes and return a dict.
|
|
Arguments : $nodelist - nodes list ref.
|
|
Returns : A hash ref of %nicsattrs for node's nics attributes.
|
|
keys of %nicsattrs are node names.
|
|
values of %nicsattrs are nics attrib ref.
|
|
For each nic attrib ref, the keys are nic names, like: ib0, eth0, bmc...
|
|
values are attributes of a specific nic, like:
|
|
type : nic type
|
|
hostnamesuffix: hostname suffix
|
|
customscript: custom script for this nic
|
|
network: network name for this nic
|
|
ip: ip address of this nic.
|
|
=cut
|
|
|
|
#-------------------------------------------------------------------------------
|
|
sub get_nodes_nic_attrs{
|
|
my $class = shift;
|
|
my $nodes = shift;
|
|
|
|
my $nicstab = xCAT::Table->new( 'nics');
|
|
my $entry = $nicstab->getNodesAttribs($nodes, ['nictypes', 'nichostnamesuffixes', 'niccustomscripts', 'nicnetworks']);
|
|
|
|
my %nicsattrs;
|
|
my @nicattrslist;
|
|
|
|
foreach my $node (@$nodes){
|
|
if ($entry->{$node}->[0]->{'nictypes'}){
|
|
@nicattrslist = split(",", $entry->{$node}->[0]->{'nictypes'});
|
|
foreach (@nicattrslist){
|
|
my @nicattrs = split(":", $_);
|
|
$nicsattrs{$node}{$nicattrs[0]}{'type'} = $nicattrs[1];
|
|
}
|
|
}
|
|
|
|
if($entry->{$node}->[0]->{'nichostnamesuffixes'}){
|
|
@nicattrslist = split(",", $entry->{$node}->[0]->{'nichostnamesuffixes'});
|
|
foreach (@nicattrslist){
|
|
my @nicattrs = split(":", $_);
|
|
$nicsattrs{$node}{$nicattrs[0]}{'hostnamesuffix'} = $nicattrs[1];
|
|
}
|
|
}
|
|
|
|
if($entry->{$node}->[0]->{'niccustomscripts'}){
|
|
@nicattrslist = split(",", $entry->{$node}->[0]->{'niccustomscripts'});
|
|
foreach (@nicattrslist){
|
|
my @nicattrs = split(":", $_);
|
|
$nicsattrs{$node}{$nicattrs[0]}{'customscript'} = $nicattrs[1];
|
|
}
|
|
}
|
|
|
|
if($entry->{$node}->[0]->{'nicnetworks'}){
|
|
@nicattrslist = split(",", $entry->{$node}->[0]->{'nicnetworks'});
|
|
foreach (@nicattrslist){
|
|
my @nicattrs = split(":", $_);
|
|
$nicsattrs{$node}{$nicattrs[0]}{'network'} = $nicattrs[1];
|
|
}
|
|
}
|
|
|
|
if($entry->{$node}->[0]->{'nicips'}){
|
|
@nicattrslist = split(",", $entry->{$node}->[0]->{'nicips'});
|
|
foreach (@nicattrslist){
|
|
my @nicattrs = split(":", $_);
|
|
$nicsattrs{$node}{$nicattrs[0]}{'ip'} = $nicattrs[1];
|
|
}
|
|
}
|
|
}
|
|
|
|
return \%nicsattrs;
|
|
}
|
|
|
|
#-------------------------------------------------------------------------------
|
|
|
|
=head3 get_netprofile_bmcnet
|
|
Description : Get bmc network name of a network profile.
|
|
Arguments : $nettmpl - network profile name
|
|
Returns : bmc network name of this network profile.
|
|
=cut
|
|
|
|
#-------------------------------------------------------------------------------
|
|
sub get_netprofile_bmcnet{
|
|
my ($class, $netprofilename) = @_;
|
|
|
|
my $netprofile_nicshash_ref = xCAT::ProfiledNodeUtils->get_nodes_nic_attrs($netprofilename)->{$netprofilename};
|
|
my %netprofile_nicshash = %$netprofile_nicshash_ref;
|
|
if (exists $netprofile_nicshash{'bmc'}{"network"}){
|
|
return $netprofile_nicshash{'bmc'}{"network"}
|
|
}else{
|
|
return undef;
|
|
}
|
|
}
|
|
|
|
#-------------------------------------------------------------------------------
|
|
|
|
=head3 get_netprofile_provisionnet
|
|
Description : Get deployment network of a network profile.
|
|
Arguments : $nettmpl - network profile name
|
|
Returns : deployment network name of this network profile.
|
|
=cut
|
|
|
|
#-------------------------------------------------------------------------------
|
|
sub get_netprofile_provisionnet{
|
|
my ($class, $netprofilename) = @_;
|
|
|
|
my $netprofile_nicshash_ref = xCAT::ProfiledNodeUtils->get_nodes_nic_attrs([$netprofilename])->{$netprofilename};
|
|
my %netprofile_nicshash = %$netprofile_nicshash_ref;
|
|
my $restab = xCAT::Table->new('noderes');
|
|
my $installnicattr = $restab->getNodeAttribs($netprofilename, ['installnic']);
|
|
my $installnic = $installnicattr->{'installnic'};
|
|
|
|
if ($installnic){
|
|
if (exists $netprofile_nicshash{$installnic}{"network"}){
|
|
return $netprofile_nicshash{$installnic}{"network"}
|
|
}
|
|
}
|
|
return undef;
|
|
}
|
|
|
|
#-------------------------------------------------------------------------------
|
|
|
|
=head3 get_output_filename
|
|
Description : Generate a temp file name for placing output details for profiled node management operations.
|
|
We make this file generated under /install/ so that clients can access it through http.
|
|
Arguments : N/A
|
|
Returns : A temp filename placed under /install/pcm/work/
|
|
=cut
|
|
|
|
#-------------------------------------------------------------------------------
|
|
sub get_output_filename
|
|
{
|
|
my $installdir = xCAT::TableUtils->getInstallDir();
|
|
my $pcmworkdir = $installdir."/pcm/work/";
|
|
if (! -d $pcmworkdir)
|
|
{
|
|
mkpath($pcmworkdir);
|
|
}
|
|
return tempfile("hostinfo_result_XXXXXXX", DIR=>$pcmworkdir);
|
|
}
|
|
|
|
#-------------------------------------------------------------------------------
|
|
|
|
=head3 get_all_chassis
|
|
Description : Get all chassis in system.
|
|
Arguments : hashref: if not set, return a array ref.
|
|
if set, return a hash ref.
|
|
Returns : ref for chassis list.
|
|
Example :
|
|
my $arrayref = xCAT::ProfiledNodeUtils->get_all_chassis();
|
|
my $hashref = xCAT::ProfiledNodeUtils->get_all_chassis(1);
|
|
=cut
|
|
|
|
#-------------------------------------------------------------------------------
|
|
sub get_all_chassis
|
|
{
|
|
my $class = shift;
|
|
my $hashref = shift;
|
|
my %chassishash;
|
|
|
|
my @chassis = xCAT::NodeRange::noderange('__Chassis');
|
|
if ($hashref){
|
|
foreach (@chassis){
|
|
$chassishash{$_} = 1;
|
|
}
|
|
return \%chassishash;
|
|
} else{
|
|
return \@chassis;
|
|
}
|
|
}
|
|
|
|
#-------------------------------------------------------------------------------
|
|
|
|
=head3 get_all_rack
|
|
Description : Get all rack in system.
|
|
Arguments : hashref: if not set, return a array ref.
|
|
if set, return a hash ref.
|
|
Returns : ref for rack list.
|
|
Example :
|
|
my $arrayref = xCAT::ProfiledNodeUtils->get_all_rack();
|
|
my $hashref = xCAT::ProfiledNodeUtils->get_all_rack(1);
|
|
=cut
|
|
|
|
#-------------------------------------------------------------------------------
|
|
sub get_all_rack
|
|
{
|
|
my $class = shift;
|
|
my $hashref = shift;
|
|
my %rackhash = ();
|
|
my @racklist = ();
|
|
|
|
my $racktab = xCAT::Table->new('rack');
|
|
my @racks = $racktab->getAllAttribs(('rackname'));
|
|
foreach (@racks){
|
|
if($_->{'rackname'}){
|
|
if ($hashref){
|
|
$rackhash{$_->{'rackname'}} = 1;
|
|
}else {
|
|
push @racklist, $_->{'rackname'};
|
|
}
|
|
}
|
|
}
|
|
|
|
if ($hashref){
|
|
return \%rackhash;
|
|
}else{
|
|
return \@racklist;
|
|
}
|
|
}
|
|
|
|
#-------------------------------------------------------------------------------
|
|
|
|
=head3 get_allnode_singleattrib_hash
|
|
Description : Get all records of a column from a table, then return a hash.
|
|
The return hash's keys are the records of this attribute
|
|
and values are all set as 1.
|
|
Arguments : $tabname - the table name.
|
|
$attr - the attribute name.
|
|
Returns : Reference of the records hash.
|
|
=cut
|
|
|
|
#-------------------------------------------------------------------------------
|
|
sub get_allnode_singleattrib_hash
|
|
{
|
|
my $class = shift;
|
|
my $tabname = shift;
|
|
my $attr = shift;
|
|
my $table = xCAT::Table->new($tabname);
|
|
my @entries = $table->getAllNodeAttribs([$attr]);
|
|
my %allrecords;
|
|
foreach (@entries) {
|
|
if ($_->{$attr}){
|
|
$allrecords{$_->{$attr}} = 0;
|
|
}
|
|
}
|
|
return \%allrecords;
|
|
}
|
|
|
|
#-------------------------------------------------------------------------------
|
|
|
|
=head3 is_discover_started
|
|
Description : Judge whether profiled nodes discovering is running or not.
|
|
Arguments : NA
|
|
Returns : 1 - Discover is running
|
|
0 - Discover is not started.
|
|
=cut
|
|
|
|
#-------------------------------------------------------------------------------
|
|
sub is_discover_started
|
|
{
|
|
my @sitevalues = xCAT::TableUtils->get_site_attribute("__PCMDiscover");
|
|
if (! $sitevalues[0]){
|
|
return 0;
|
|
}
|
|
return 1;
|
|
}
|
|
|
|
#-------------------------------------------------------------------------------
|
|
|
|
=head3 get_node_profiles
|
|
Description : Get nodelist's profile and return a hash ref.
|
|
Arguments : node list.
|
|
Returns : nodelist's profile hash.
|
|
keys are node names.
|
|
values are hash ref. This hash ref is placing the node's profile information:
|
|
keys can be followings: "NetworkProfile", "ImageProfile", "HardwareProfile"
|
|
values are the profile names.
|
|
=cut
|
|
|
|
#-------------------------------------------------------------------------------
|
|
|
|
sub get_nodes_profiles
|
|
{
|
|
my $class = shift;
|
|
my $nodelistref = shift;
|
|
my %profile_dict;
|
|
|
|
my $nodelisttab = xCAT::Table->new('nodelist');
|
|
my $groupshashref = $nodelisttab->getNodesAttribs($nodelistref, ['groups']);
|
|
my %groupshash = %$groupshashref;
|
|
|
|
foreach (keys %groupshash){
|
|
my $value = $groupshash{$_};
|
|
my $groups = $value->[0]->{'groups'};
|
|
# groups looks like "__Managed,__NetworkProfile_default_cn,__ImageProfile_rhels6.3-x86_64-install-compute"
|
|
my @grouplist = split(',', $groups);
|
|
my @profilelist = ("NetworkProfile", "ImageProfile", "HardwareProfile");
|
|
foreach my $group (@grouplist){
|
|
foreach my $profile (@profilelist){
|
|
my $idx = index ($group, $profile);
|
|
# The Group starts with __, so index will be 2.
|
|
if ( $idx == 2 ){
|
|
# The group string will like @NetworkProfile_<profile name>
|
|
# So, index should +3, 2 for '__', 1 for _.
|
|
my $append_index = length($profile) + 3;
|
|
$profile_dict{$_}{$profile} = substr $group, $append_index;
|
|
last;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return \%profile_dict;
|
|
}
|
|
|
|
#-------------------------------------------------------------------------------
|
|
|
|
=head3 get_imageprofile_prov_method
|
|
Description : Get A node's provisioning method from its imageprofile attribute.
|
|
Arguments : $imgprofilename - imageprofile name
|
|
Returns : node's provisioning method: install, netboot...etc
|
|
=cut
|
|
|
|
#-------------------------------------------------------------------------------
|
|
sub get_imageprofile_prov_method
|
|
{
|
|
|
|
# For imageprofile, we can get node's provisioning method through:
|
|
# nodetype table: node (imageprofile name), provmethod (osimage name)
|
|
# osimage table: imagename (osimage name), provmethod (node deploy method: install, netboot...)
|
|
my $class = shift;
|
|
my $imgprofilename = shift;
|
|
|
|
my $nodetypestab = xCAT::Table->new('nodetype');
|
|
my $entry = ($nodetypestab->getAllAttribsWhere("node = '$imgprofilename'", 'ALL' ))[0];
|
|
my $osimgname = $entry->{'provmethod'};
|
|
|
|
my $osimgtab = xCAT::Table->new('osimage');
|
|
my $osimgentry = ($osimgtab->getAllAttribsWhere("imagename = '$osimgname'", 'ALL' ))[0];
|
|
return $osimgentry->{'provmethod'};
|
|
}
|
|
|