# 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. $amount - The total hostname number to be generated. 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, $amount) = @_; my ($prefix, $appendix, $len) = xCAT::ProfiledNodeUtils->split_hostname($format, 'N'); return xCAT::ProfiledNodeUtils->gen_numric_hostnames($prefix, $appendix, $len, $rank, $amount); } #------------------------------------------------------------------------------- =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. $rank - the start number for numric part $amount - the amount of hostnames to be generated. 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, $amount) = @_; 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); if ($amount && (@hostnames == $amount)){ last; } $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 ($prefix, $appendix, $rlen, $nlen); my $ridx = index $format, "#R"; my $nidx = index $format, "#N"; if ($ridx >= 0){ ($prefix, $appendix, $rlen) = xCAT::ProfiledNodeUtils->split_hostname($format, 'R'); ($prefix, $appendix, $nlen) = xCAT::ProfiledNodeUtils->split_hostname($format, 'N'); if ($rlen >= 10 || $nlen >= 10){ $type = "unknown"; } else{ $type = "rack"; } } elsif ($nidx >= 0){ ($prefix, $appendix, $nlen) = xCAT::ProfiledNodeUtils->split_hostname($format, 'N'); if ($nlen >= 10){ $type = "unknown"; } else{ $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_ # 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'}; }