2013-04-06 09:40:39 +00:00
#!/usr/bin/env perl
## IBM(c) 20013 EPL license http://www.eclipse.org/legal/epl-v10.html
#
# This plugin is used to handle the sequencial discovery. During the discovery,
# the nodes should be powered on one by one, sequencial discovery plugin will
# discover the nodes one by one and define them to xCAT DB.
# For the new discovered node but NOT handled by xCAT plugin,
# it will be recorded to discoverydata table.
#
package xCAT_plugin::seqdiscovery ;
BEGIN
{
$ ::XCATROOT = $ ENV { 'XCATROOT' } ? $ ENV { 'XCATROOT' } : '/opt/xcat' ;
}
use strict ;
use Getopt::Long ;
2013-05-16 08:19:53 +00:00
use XML::Simple ;
$ XML:: Simple:: PREFERRED_PARSER = 'XML::Parser' ;
2013-04-06 09:40:39 +00:00
use lib "$::XCATROOT/lib/perl" ;
use xCAT::NodeRange ;
use xCAT::Table ;
use xCAT::NetworkUtils ;
use xCAT::MsgUtils ;
use xCAT::DiscoveryUtils ;
2013-05-16 08:19:53 +00:00
use xCAT::NodeRange qw/noderange/ ;
2013-08-16 03:10:50 +00:00
require xCAT::data::ibmhwtypes ;
2013-04-06 09:40:39 +00:00
use Time::HiRes qw( gettimeofday sleep ) ;
sub handled_commands {
return {
findme = > 'seqdiscovery' ,
nodediscoverstart = > 'seqdiscovery' ,
nodediscoverstop = > 'seqdiscovery' ,
nodediscoverls = > 'seqdiscovery' ,
nodediscoverstatus = > 'seqdiscovery' ,
2013-05-16 08:19:53 +00:00
nodediscoverdef = > 'seqdiscovery' ,
2013-04-06 09:40:39 +00:00
}
}
2013-05-22 14:58:46 +00:00
= head3 findme
Handle the request form node to map and define the request to a node
= cut
2013-04-06 09:40:39 +00:00
sub findme {
my $ request = shift ;
my $ callback = shift ;
my $ subreq = shift ;
my @ SEQdiscover = xCAT::TableUtils - > get_site_attribute ( "__SEQDiscover" ) ;
my @ PCMdiscover = xCAT::TableUtils - > get_site_attribute ( "__PCMDiscover" ) ;
unless ( $ SEQdiscover [ 0 ] ) {
if ( $ PCMdiscover [ 0 ] ) {
#profile disocvery is running, then just return to make profile discovery to handle it
return ;
}
# update the discoverydata table to have an undefined node
$ request - > { discoverymethod } - > [ 0 ] = 'undef' ;
xCAT::DiscoveryUtils - > update_discovery_data ( $ request ) ;
return ;
}
# do the sequential discovery
xCAT::MsgUtils - > message ( "S" , "Sequential Discovery: Processing" ) ;
# Get the parameters for the sequential discovery
my % param ;
my @ params = split ( ',' , $ SEQdiscover [ 0 ] ) ;
foreach ( @ params ) {
my ( $ name , $ value ) = split ( '=' , $ _ ) ;
$ param { $ name } = $ value ;
}
my $ mac ;
my $ ip = $ request - > { '_xcat_clientip' } ;
if ( defined $ request - > { nodetype } and $ request - > { nodetype } - > [ 0 ] eq 'virtual' ) {
return ;
}
2013-05-13 08:11:11 +00:00
my $ arptable ;
if ( - x "/usr/sbin/arp" ) {
$ arptable = `/usr/sbin/arp -n` ;
}
2013-05-16 08:19:53 +00:00
else {
2013-05-13 08:11:11 +00:00
$ arptable = `/sbin/arp -n` ;
}
2013-05-22 14:58:46 +00:00
2013-04-06 09:40:39 +00:00
my @ arpents = split /\n/ , $ arptable ;
foreach ( @ arpents ) {
if ( m/^($ip)\s+\S+\s+(\S+)\s/ ) {
$ mac = $ 2 ;
last ;
}
}
2013-04-12 08:12:12 +00:00
2013-04-06 09:40:39 +00:00
unless ( $ mac ) {
xCAT::MsgUtils - > message ( "S" , "Discovery Error: Could not find the mac of the $ip." ) ;
return ;
}
# check whether the mac could map to a node
my $ mactab = xCAT::Table - > new ( 'mac' ) ;
unless ( $ mactab ) {
xCAT::MsgUtils - > message ( "S" , "Discovery Error: Could not open table: mac." ) ;
}
my $ node ;
my @ macs = $ mactab - > getAllAttribs ( 'node' , 'mac' ) ;
# for each entry: 34:40:b5:be:db:b0!*NOIP*|34:40:b5:be:db:b0!*NOIP*
foreach my $ macnode ( @ macs ) {
my @ macents = split ( '\|' , $ macnode - > { 'mac' } ) ;
foreach my $ macent ( @ macents ) {
my ( $ usedmac ) = split ( '!' , $ macent ) ;
if ( $ usedmac =~ /$mac/i ) {
$ node = $ macnode - > { 'node' } ;
last ;
}
}
}
my @ allnodes ;
unless ( $ node ) {
# get a free node
@ allnodes = getfreenodes ( $ param { 'noderange' } , "all" ) ;
if ( @ allnodes ) {
$ node = $ allnodes [ 0 ] ;
}
}
if ( $ node ) {
my $ skiphostip ;
my $ skipbmcip ;
2013-06-08 23:32:38 +00:00
my $ bmcname ;
2013-04-06 09:40:39 +00:00
# check the host ip and bmc
my $ hosttab = xCAT::Table - > new ( 'hosts' ) ;
unless ( $ hosttab ) {
xCAT::MsgUtils - > message ( "S" , "Discovery Error: Could not open table: hosts." ) ;
}
2013-05-22 14:58:46 +00:00
my $ hostip = getpredefips ( [ $ node ] , "host" ) ;
foreach ( keys %$ hostip ) {
if ( $ hostip - > { $ _ } eq "$node" ) {
$ skiphostip = 1 ;
}
2013-04-06 09:40:39 +00:00
}
2013-04-12 08:12:12 +00:00
2013-04-06 09:40:39 +00:00
my $ ipmitab = xCAT::Table - > new ( 'ipmi' ) ;
unless ( $ ipmitab ) {
xCAT::MsgUtils - > message ( "S" , "Discovery Error: Could not open table: ipmi." ) ;
}
2013-06-08 23:32:38 +00:00
# check the bmc definition in the ipmi table
my $ ipmient = $ ipmitab - > getNodeAttribs ( $ node , [ 'bmc' ] ) ;
if ( defined ( $ ipmient - > { 'bmc' } ) ) {
$ bmcname = $ ipmient - > { 'bmc' } ;
if ( $ bmcname =~ /\d+\.\d+\.\d+\.\d+/ ) {
$ skipbmcip = 1 ;
} else {
my $ bmcip = getpredefips ( [ $ node ] , "bmc" ) ;
foreach ( keys %$ bmcip ) {
if ( $ bmcip - > { $ _ } eq $ bmcname ) {
$ skipbmcip = 1 ;
}
}
}
}
2013-05-22 14:58:46 +00:00
# set the host ip if the node does not have
2013-04-06 09:40:39 +00:00
unless ( $ skiphostip ) {
my $ hostip = getfreeips ( $ param { 'hostiprange' } , \ @ allnodes , "host" ) ;
unless ( $ hostip ) {
nodediscoverstop ( $ callback , undef , "host ips" ) ;
return ;
}
$ hosttab - > setNodeAttribs ( $ node , { ip = > $ hostip } ) ;
$ hosttab - > commit ( ) ;
}
2013-05-22 14:58:46 +00:00
# set the bmc ip if the node does not have
2013-04-06 09:40:39 +00:00
unless ( $ skipbmcip ) {
2013-06-08 23:32:38 +00:00
unless ( $ bmcname ) {
# set the default bmc name
$ bmcname = $ node . "-bmc" ;
}
2013-04-06 09:40:39 +00:00
my $ bmcip = getfreeips ( $ param { 'bmciprange' } , \ @ allnodes , "bmc" ) ;
unless ( $ bmcip ) {
nodediscoverstop ( $ callback , undef , "bmc ips" ) ;
return ;
}
2013-06-12 02:57:33 +00:00
# for auto created bmc, just add it to hosts.otherinterfaces instead of adding a new bmc node
my $ otherif = $ hosttab - > getNodeAttribs ( $ node , [ 'otherinterfaces' ] ) ;
my $ updateotherif ;
if ( $ otherif && defined ( $ otherif - > { 'otherinterfaces' } ) ) {
$ updateotherif . = ",$bmcname:$bmcip" ;
} else {
$ updateotherif = "$bmcname:$bmcip" ;
}
$ hosttab - > setNodeAttribs ( $ node , { otherinterfaces = > $ updateotherif } ) ;
2013-04-06 09:40:39 +00:00
$ hosttab - > commit ( ) ;
2013-05-22 14:58:46 +00:00
# set the bmc to the ipmi table
$ ipmitab - > setNodeAttribs ( $ node , { bmc = > $ bmcname } ) ;
2013-06-12 02:57:33 +00:00
$ ipmitab - > commit ( ) ;
2013-04-06 09:40:39 +00:00
}
# update the host ip pair to /etc/hosts, it's necessary for discovered and makedhcp commands
2013-06-08 23:32:38 +00:00
my @ newhosts = ( $ node , $ bmcname ) ;
2013-04-06 09:40:39 +00:00
if ( @ newhosts ) {
my $ req ;
$ req - > { command } = [ 'makehosts' ] ;
$ req - > { node } = \ @ newhosts ;
$ subreq - > ( $ req ) ;
}
# set the specific attributes from parameters
my $ updateparams ;
my % setpos ;
if ( defined ( $ param { 'rack' } ) ) {
$ setpos { 'rack' } = $ param { 'rack' } ;
}
if ( defined ( $ param { 'chassis' } ) ) {
$ setpos { 'chassis' } = $ param { 'chassis' } ;
}
if ( defined ( $ param { 'height' } ) ) {
$ setpos { 'height' } = $ param { 'height' } ;
}
if ( defined ( $ param { 'unit' } ) ) {
$ setpos { 'u' } = $ param { 'unit' } ;
if ( defined ( $ param { 'height' } ) ) {
$ param { 'unit' } += $ param { 'height' } ;
} else {
$ param { 'unit' } += 1 ;
}
$ updateparams = 1 ;
}
if ( keys % setpos ) {
my $ postab = xCAT::Table - > new ( 'nodepos' ) ;
unless ( $ postab ) {
xCAT::MsgUtils - > message ( "S" , "Discovery Error: Could not open table: nodepos." ) ;
}
$ postab - > setNodeAttribs ( $ node , \ % setpos ) ;
$ postab - > close ( ) ;
}
if ( $ updateparams ) {
my $ textparam ;
foreach my $ name ( keys % param ) {
$ textparam . = "$name=$param{$name}," ;
}
$ textparam =~ s/,\z// ;
# Update the discovery parameters to the site.__SEQDiscover which will be used by nodediscoverls/status/stop and findme,
my $ sitetab = xCAT::Table - > new ( "site" ) ;
$ sitetab - > setAttribs ( { "key" = > "__SEQDiscover" } , { "value" = > "$textparam" } ) ;
$ sitetab - > close ( ) ;
}
#set the groups for the node
my $ nltab = xCAT::Table - > new ( 'nodelist' ) ;
unless ( $ nltab ) {
xCAT::MsgUtils - > message ( "S" , "Discovery Error: Could not open table: nodelist." ) ;
}
if ( defined ( $ param { 'groups' } ) ) {
$ nltab - > setNodeAttribs ( $ node , { groups = > $ param { 'groups' } } ) ;
} else {
2013-05-22 14:58:46 +00:00
# just set the groups attribute when there was no groups value was set
2013-05-07 04:22:48 +00:00
my $ nlent = $ nltab - > getNodeAttribs ( $ node , [ 'groups' ] ) ;
if ( ! $ nlent || ! $ nlent - > { 'groups' } ) {
$ nltab - > setNodeAttribs ( $ node , { groups = > "all" } ) ;
}
2013-04-06 09:40:39 +00:00
}
2013-08-16 03:10:50 +00:00
# update node groups with pre-defined groups
if ( defined ( $ param { 'mtm' } ) ) {
my @ list = ( ) ;
my $ tmp_group = xCAT::data::ibmhwtypes:: parse_group ( $ param { 'mtm' } ) ;
if ( defined ( $ tmp_group ) ) {
xCAT::TableUtils - > updatenodegroups ( $ node , $ nltab , $ tmp_group ) ;
}
}
2013-05-22 14:58:46 +00:00
# set the mgt for the node
my $ hmtab = xCAT::Table - > new ( 'nodehm' ) ;
unless ( $ hmtab ) {
xCAT::MsgUtils - > message ( "S" , "Discovery Error: Could not open table: nodehm." ) ;
}
my $ hment = $ hmtab - > getNodeAttribs ( $ node , [ 'mgt' ] ) ;
if ( ! $ hment || ! $ hment - > { 'mgt' } ) {
$ hmtab - > setNodeAttribs ( $ node , { mgt = > "ipmi" } ) ;
}
# call the discovered command to update the discovery request to a node
2013-04-06 09:40:39 +00:00
$ request - > { command } = [ 'discovered' ] ;
$ request - > { noderange } = [ $ node ] ;
$ request - > { discoverymethod } = [ 'sequential' ] ;
$ request - > { updateswitch } = [ 'yes' ] ;
$ subreq - > ( $ request ) ;
% { $ request } = ( ) ; #Clear req structure, it's done..
undef $ mactab ;
} else {
nodediscoverstop ( $ callback , undef , "node names" ) ;
return ;
}
xCAT::MsgUtils - > message ( "S" , "Sequential Discovery: Done" ) ;
}
= head3 displayver
Display the version information
= cut
sub displayver {
my $ callback = shift ;
my $ version = xCAT::Utils - > Version ( ) ;
my $ rsp ;
push @ { $ rsp - > { data } } , $ version ;
xCAT::MsgUtils - > message ( "I" , $ rsp , $ callback ) ;
}
= head3 nodediscoverstart
Initiate the sequencial discovery process
= cut
sub nodediscoverstart {
my $ callback = shift ;
my $ args = shift ;
my $ usage = sub {
my $ cb = shift ;
my $ msg = shift ;
my $ rsp ;
if ( $ msg ) {
push @ { $ rsp - > { data } } , $ msg ;
xCAT::MsgUtils - > message ( "E" , $ rsp , $ cb , 1 ) ;
}
my $ usageinfo = " nodediscoverstart: Start a discovery process: Sequential or Profile .
Usage:
Common:
nodediscoverstart [ - h | - - help | - v | - - version | - V | - - verbose ]
Sequential Discovery:
nodediscoverstart noderange = <noderange> [ hostiprange = <imageprofile> ] [ bmciprange = <bmciprange> ] [ groups = <groups> ] [ rack = <rack> ] [ chassis = <chassis> ] [ height = <height> ] [ unit = <unit> ]
Profile Discovery:
2013-04-12 08:12:12 +00:00
nodediscoverstart networkprofile = <networkprofile> imageprofile = <imageprofile> hostnameformat = <hostnameformat> [ hardwareprofile = <hardwareprofile> ] [ groups = <groups> ] [ rack = <rack> ] [ chassis = <chassis> ] [ height = <height> ] [ unit = <unit> ] [ rank = rank - num ] " ;
2013-04-06 09:40:39 +00:00
$ rsp = ( ) ;
push @ { $ rsp - > { data } } , $ usageinfo ;
xCAT::MsgUtils - > message ( "I" , $ rsp , $ cb ) ;
} ;
# valid attributes for deqdiscovery
my % validargs = (
'noderange' = > 1 ,
'hostiprange' = > 1 ,
'bmciprange' = > 1 ,
'groups' = > 1 ,
'rack' = > 1 ,
'chassis' = > 1 ,
'height' = > 1 ,
'unit' = > 1 ,
) ;
if ( $ args ) {
@ ARGV = @$ args ;
}
my ( $ help , $ ver ) ;
if ( ! GetOptions (
'h|help' = > \ $ help ,
'V|verbose' = > \ $ ::VERBOSE ,
'v|version' = > \ $ ver ) ) {
$ usage - > ( $ callback ) ;
return ;
}
if ( $ help ) {
$ usage - > ( $ callback ) ;
return ;
}
if ( $ ver ) {
& displayver ( $ callback ) ;
return ;
}
my % orgargs ;
foreach ( @ ARGV ) {
my ( $ name , $ value ) = split ( '=' , $ _ ) ;
$ orgargs { $ name } = $ value ;
}
# Check the noderage=has been specified which is the flag that this is for sequential discovery
# Otherwise try to check the whether the networkprofile || hardwareprofile || imageprofile
# has been passed, if yes, return to profile discovery
unless ( defined ( $ orgargs { noderange } ) ) {
if ( defined ( $ orgargs { networkprofile } ) || defined ( $ orgargs { hostnameformat } ) || defined ( $ orgargs { imageprofile } ) ) {
# just return that make profile-based discovery to handle it
return ;
} else {
$ usage - > ( $ callback , "For sequential discovery, the \'noderange\' option must be specified." ) ;
return ;
}
}
my % param ; # The valid parameters
my $ textparam ; # The valid parameters in 'name=value,name=value...' format
# Check the validate of parameters
foreach my $ name ( keys % orgargs ) {
unless ( defined ( $ validargs { $ name } ) ) {
$ usage - > ( $ callback , "Invalid arguement \"$name\"." ) ;
return ;
}
unless ( defined ( $ orgargs { $ name } ) ) {
$ usage - > ( $ callback , "The parameter \"$name\" need a value." ) ;
return ;
}
# keep the valid parameters
$ param { $ name } = $ orgargs { $ name } ;
$ textparam . = $ name . '=' . $ param { $ name } . ',' ;
}
$ textparam =~ s/,\z// ;
# Check the running of profile-based discovery
my @ PCMdiscover = xCAT::TableUtils - > get_site_attribute ( "__PCMDiscover" ) ;
if ( $ PCMdiscover [ 0 ] ) {
my $ rsp ;
2013-04-12 08:12:12 +00:00
push @ { $ rsp - > { data } } , "Sequentail Discovery cannot be run together with Profile-based discovery" ;
2013-04-06 09:40:39 +00:00
xCAT::MsgUtils - > message ( "E" , $ rsp , $ callback , 1 ) ;
return ;
}
# Check the running of sequential discovery
my @ SEQdiscover = xCAT::TableUtils - > get_site_attribute ( "__SEQDiscover" ) ;
if ( $ SEQdiscover [ 0 ] ) {
my $ rsp ;
push @ { $ rsp - > { data } } , "Sequentail Discovery is running. If you want to rerun the discovery, stop the running discovery first." ;
xCAT::MsgUtils - > message ( "E" , $ rsp , $ callback , 1 ) ;
return ;
}
# Check that the dynamic range in the dhcpd.conf has been set correctly
# search all the network in the networks table that make sure the dynamic range for the deployment network has been set
# Set the discovery parameters to the site.__SEQDiscover which will be used by nodediscoverls/status/stop and findme,
my $ sitetab = xCAT::Table - > new ( "site" ) ;
$ sitetab - > setAttribs ( { "key" = > "__SEQDiscover" } , { "value" = > "$textparam" } ) ;
$ sitetab - > close ( ) ;
# Clean the entries which discovery method is 'sequential' from the discoverdata table
my $ distab = xCAT::Table - > new ( "discoverydata" ) ;
$ distab - > delEntries ( { method = > 'sequential' } ) ;
$ distab - > commit ( ) ;
# Calculate the available node name and IPs
my @ freenodes = getfreenodes ( $ param { 'noderange' } , "all" ) ;
my @ freehostips = getfreeips ( $ param { 'hostiprange' } , \ @ freenodes , "host" , "all" ) ;
my @ freebmcips = getfreeips ( $ param { 'bmciprange' } , \ @ freenodes , "bmc" , "all" ) ;
#xCAT::MsgUtils->message("S", "Sequential Discovery: Start");
my $ rsp ;
push @ { $ rsp - > { data } } , "Sequential Discovery: Started:" ;
push @ { $ rsp - > { data } } , " Number of free node names: " . ( $# freenodes + 1 ) ;
if ( $ param { 'hostiprange' } ) {
if ( @ freehostips ) {
push @ { $ rsp - > { data } } , " Number of free host ips: " . ( $# freehostips + 1 ) ;
} else {
push @ { $ rsp - > { data } } , " No free host ips." ;
}
}
if ( $ param { 'bmciprange' } ) {
if ( @ freebmcips ) {
push @ { $ rsp - > { data } } , " Number of free bmc ips: " . ( $# freebmcips + 1 ) ;
} else {
push @ { $ rsp - > { data } } , " No free bmc ips." ;
}
}
xCAT::MsgUtils - > message ( "I" , $ rsp , $ callback ) ;
if ( $ ::VERBOSE ) {
# dispaly the free nodes
2013-05-22 14:58:46 +00:00
# get predefined host ip
my % prehostips ;
my $ prehosts = getpredefips ( \ @ freenodes , "host" ) ; #pre{ip} = nodename
foreach ( keys %$ prehosts ) {
$ prehostips { $ prehosts - > { $ _ } } = $ _ ; #pre{nodename} = ip
}
# get predefined bmc ip
my % prebmcips ;
my $ prebmcs = getpredefips ( \ @ freenodes , "bmc" ) ; #pre{ip} = bmcname
foreach ( keys %$ prebmcs ) {
$ prebmcips { $ prebmcs - > { $ _ } } = $ _ ; #pre{bmcname} = ip
}
2013-06-08 23:32:38 +00:00
# get the bmc of nodes
my $ ipmitab = xCAT::Table - > new ( 'ipmi' ) ;
my $ ipmient ;
if ( $ ipmitab ) {
$ ipmient = $ ipmitab - > getNodesAttribs ( \ @ freenodes , [ 'bmc' ] ) ;
}
2013-05-22 14:58:46 +00:00
my $ vrsp ;
push @ { $ vrsp - > { data } } , "\n====================Free Nodes===================" ;
push @ { $ vrsp - > { data } } , sprintf ( "%-20s%-20s%-20s" , "NODE" , "HOST IP" , "BMC IP" ) ;
my $ index = 0 ;
foreach ( @ freenodes ) {
my $ hostip ;
my $ bmcip ;
# if predefined, use it; otherwise pop out one from the free ip list
if ( defined ( $ prehostips { $ _ } ) ) {
$ hostip = $ prehostips { $ _ } ;
} else {
while ( ( $ hostip = shift @ freehostips ) ) {
if ( ! defined ( $ prehosts - > { $ hostip } ) ) { last ; }
2013-04-06 09:40:39 +00:00
}
2013-05-22 14:58:46 +00:00
unless ( $ hostip ) {
$ hostip = "--no free--" ;
2013-04-06 09:40:39 +00:00
}
}
2013-05-22 14:58:46 +00:00
# if predefined, use it; otherwise pop out one from the free ip list
2013-06-08 23:32:38 +00:00
my $ bmcname ;
if ( defined ( $ ipmient - > { $ _ } - > [ 0 ] - > { 'bmc' } ) ) {
$ bmcname = $ ipmient - > { $ _ } - > [ 0 ] - > { 'bmc' } ;
if ( $ bmcname =~ /\d+\.\d+\.\d+\.\d+/ ) {
$ bmcip = $ bmcname ;
} elsif ( defined ( $ prebmcips { $ bmcname } ) ) {
$ bmcip = $ prebmcips { $ bmcname } ;
}
}
unless ( $ bmcip ) {
2013-05-22 14:58:46 +00:00
while ( ( $ bmcip = shift @ freebmcips ) ) {
if ( ! defined ( $ prebmcs - > { $ bmcip } ) ) { last ; }
2013-04-06 09:40:39 +00:00
}
2013-05-22 14:58:46 +00:00
unless ( $ bmcip ) {
$ bmcip = "--no free--" ;
2013-04-06 09:40:39 +00:00
}
}
2013-05-22 14:58:46 +00:00
push @ { $ vrsp - > { data } } , sprintf ( "%-20s%-20s%-20s" , $ _ , $ hostip , $ bmcip ) ;
$ index + + ;
2013-04-06 09:40:39 +00:00
}
2013-05-22 14:58:46 +00:00
xCAT::MsgUtils - > message ( "I" , $ vrsp , $ callback ) ;
2013-04-06 09:40:39 +00:00
}
}
= head3 nodediscoverstop
Stop the sequencial discovery process
= cut
sub nodediscoverstop {
my $ callback = shift ;
my $ args = shift ;
my $ auto = shift ;
my $ usage = sub {
my $ cb = shift ;
my $ msg = shift ;
my $ rsp ;
if ( $ msg ) {
push @ { $ rsp - > { data } } , $ msg ;
xCAT::MsgUtils - > message ( "E" , $ rsp , $ cb , 1 ) ;
}
my $ usageinfo = " nodediscoverstop: Stop the running discovery: Sequential and Profile .
Usage:
nodediscoverstop [ - h | - - help | - v | - - version ] " ;
$ rsp = ( ) ;
push @ { $ rsp - > { data } } , $ usageinfo ;
xCAT::MsgUtils - > message ( "I" , $ rsp , $ cb ) ;
} ;
if ( $ args ) {
@ ARGV = @$ args ;
}
my ( $ help , $ ver ) ;
if ( ! GetOptions (
'h|help' = > \ $ help ,
'V|verbose' = > \ $ ::VERBOSE ,
'v|version' = > \ $ ver ) ) {
$ usage - > ( $ callback ) ;
return ;
}
if ( $ help ) {
$ usage - > ( $ callback ) ;
return ;
}
if ( $ ver ) {
& displayver ( $ callback ) ;
return ;
}
# Check the running of sequential discovery
my @ SEQDiscover = xCAT::TableUtils - > get_site_attribute ( "__SEQDiscover" ) ;
my @ PCMDiscover = xCAT::TableUtils - > get_site_attribute ( "__PCMDiscover" ) ;
if ( $ PCMDiscover [ 0 ] ) {
# return directly that profile discover will cover it
2013-04-12 08:12:12 +00:00
return ;
2013-04-06 09:40:39 +00:00
} elsif ( ! $ SEQDiscover [ 0 ] ) {
# Neither of profile nor sequential was running
my $ rsp ;
push @ { $ rsp - > { data } } , "Sequential Discovery is stopped." ;
push @ { $ rsp - > { data } } , "Profile Discovery is stopped." ;
xCAT::MsgUtils - > message ( "E" , $ rsp , $ callback , 1 ) ;
return ;
}
# Go thought discoverydata table and display the sequential disocvery entries
my $ distab = xCAT::Table - > new ( 'discoverydata' ) ;
unless ( $ distab ) {
my $ rsp ;
push @ { $ rsp - > { data } } , "Discovery Error: Could not open table: discoverydata." ;
xCAT::MsgUtils - > message ( "E" , $ rsp , $ callback ) ;
return ;
}
my @ disdata = $ distab - > getAllAttribsWhere ( "method='sequential'" , 'node' , 'mtm' , 'serial' ) ;
my @ discoverednodes ;
foreach ( @ disdata ) {
push @ discoverednodes , sprintf ( " %-20s%-10s%-10s" , $ _ - > { 'node' } , $ _ - > { 'mtm' } , substr ( $ _ - > { 'serial' } , 0 , 8 ) , ) ;
}
my $ rsp ;
push @ { $ rsp - > { data } } , "Discovered " . ( $# discoverednodes + 1 ) . " nodes." ;
if ( @ discoverednodes ) {
push @ { $ rsp - > { data } } , sprintf ( " %-20s%-10s%-10s" , 'NODE' , 'MTM' , 'SERIAL' ) ;
foreach ( @ discoverednodes ) {
push @ { $ rsp - > { data } } , "$_" ;
}
}
xCAT::MsgUtils - > message ( "I" , $ rsp , $ callback ) ;
if ( $ auto ) {
xCAT::MsgUtils - > message ( "S" , "Sequential Discovery: Auto Stopped because all $auto in the specified range have been assigned to discovered nodes. Run \'nodediscoverls -t seq\' to display the discovery result." ) ;
} else {
xCAT::MsgUtils - > message ( "S" , "Sequential Discovery: Stoped." ) ;
}
# Remove the site.__SEQDiscover
my $ sitetab = xCAT::Table - > new ( "site" ) ;
$ sitetab - > delEntries ( { key = > '__SEQDiscover' } ) ;
$ sitetab - > commit ( ) ;
}
= head3 nodediscoverls
Display the discovered nodes
= cut
sub nodediscoverls {
my $ callback = shift ;
my $ args = shift ;
my $ usage = sub {
my $ cb = shift ;
my $ msg = shift ;
my $ rsp ;
if ( $ msg ) {
push @ { $ rsp - > { data } } , $ msg ;
xCAT::MsgUtils - > message ( "E" , $ rsp , $ cb , 1 ) ;
}
my $ usageinfo = " nodediscoverls: list the discovered nodes .
Usage:
nodediscoverls
nodediscoverls [ - h | - - help | - v | - - version ]
2013-05-16 08:19:53 +00:00
nodediscoverls [ - t seq | profile | switch | blade | manual | undef | all ] [ - l ]
2013-04-06 09:40:39 +00:00
nodediscoverls [ - u uuid ] [ - l ]
" ;
$ rsp = ( ) ;
push @ { $ rsp - > { data } } , $ usageinfo ;
xCAT::MsgUtils - > message ( "I" , $ rsp , $ cb ) ;
} ;
if ( $ args ) {
@ ARGV = @$ args ;
}
my ( $ type , $ uuid , $ long , $ help , $ ver ) ;
if ( ! GetOptions (
't=s' = > \ $ type ,
'u=s' = > \ $ uuid ,
'l' = > \ $ long ,
'h|help' = > \ $ help ,
'V|verbose' = > \ $ ::VERBOSE ,
'v|version' = > \ $ ver ) ) {
$ usage - > ( $ callback ) ;
return ;
}
if ( $ help ) {
$ usage - > ( $ callback ) ;
return ;
}
if ( $ ver ) {
& displayver ( $ callback ) ;
return ;
}
# If the type is specified, display the corresponding type of nodes
2013-05-16 08:19:53 +00:00
my @ SEQDiscover ;
2013-04-06 09:40:39 +00:00
if ( $ type ) {
2013-05-16 08:19:53 +00:00
if ( $ type !~ /^(seq|profile|switch|blade|manual|undef|all)$/ ) {
2013-04-06 09:40:39 +00:00
$ usage - > ( $ callback , "The discovery type \'$type\' is not supported." ) ;
return ;
}
} elsif ( $ uuid ) {
} else {
# Check the running of sequential discovery
2013-05-16 08:19:53 +00:00
@ SEQDiscover = xCAT::TableUtils - > get_site_attribute ( "__SEQDiscover" ) ;
2013-04-06 09:40:39 +00:00
if ( $ SEQDiscover [ 0 ] ) {
$ type = "seq" ;
} else {
my @ PCMDiscover = xCAT::TableUtils - > get_site_attribute ( "__PCMDiscover" ) ;
if ( $ PCMDiscover [ 0 ] ) {
#return directly if my type of discover is not running.
return ;
} else {
# no type, no seq and no profile, then just diaplay all
$ type = "all" ;
}
}
}
# Go thought discoverydata table and display the disocvery entries
my $ distab = xCAT::Table - > new ( 'discoverydata' ) ;
unless ( $ distab ) {
my $ rsp ;
push @ { $ rsp - > { data } } , "Discovery Error: Could not open table: discoverydata." ;
xCAT::MsgUtils - > message ( "E" , $ rsp , $ callback ) ;
return ;
}
my @ disdata ;
my @ disattrs ;
if ( $ long ) {
@ disattrs = ( 'uuid' , 'node' , 'method' , 'discoverytime' , 'arch' , 'cpucount' , 'cputype' , 'memory' , 'mtm' , 'serial' , 'nicdriver' , 'nicipv4' , 'nichwaddr' , 'nicpci' , 'nicloc' , 'niconboard' , 'nicfirm' , 'switchname' , 'switchaddr' , 'switchdesc' , 'switchport' ) ;
} else {
@ disattrs = ( 'uuid' , 'node' , 'method' , 'mtm' , 'serial' ) ;
}
if ( $ type ) {
if ( $ type eq "all" ) {
@ disdata = $ distab - > getAllAttribs ( @ disattrs ) ;
} else {
$ type = "sequential" if ( $ type =~ /^seq/ ) ;
@ disdata = $ distab - > getAllAttribsWhere ( "method='$type'" , @ disattrs ) ;
}
} elsif ( $ uuid ) {
@ disdata = $ distab - > getAllAttribsWhere ( "uuid='$uuid'" , @ disattrs ) ;
}
my $ discoverednum = $# disdata + 1 ;
my @ discoverednodes ;
foreach my $ ent ( @ disdata ) {
if ( $ long ) {
foreach my $ attr ( @ disattrs ) {
if ( $ attr eq "uuid" ) {
push @ discoverednodes , "Object uuid: $ent->{$attr}" ;
} elsif ( defined ( $ ent - > { $ attr } ) ) {
push @ discoverednodes , " $attr=$ent->{$attr}" ;
}
}
} else {
$ ent - > { 'node' } = 'undef' unless ( $ ent - > { 'node' } ) ;
$ ent - > { 'method' } = 'undef' unless ( $ ent - > { 'method' } ) ;
push @ discoverednodes , sprintf ( " %-40s%-20s%-15s%-10s%-10s" , $ ent - > { 'uuid' } , $ ent - > { 'node' } , $ ent - > { 'method' } , $ ent - > { 'mtm' } , substr ( $ ent - > { 'serial' } , 0 , 8 ) ) ;
}
}
my $ rsp ;
2013-05-16 08:19:53 +00:00
if ( $ SEQDiscover [ 0 ] && $ type eq "sequential" ) {
2013-04-06 09:40:39 +00:00
push @ { $ rsp - > { data } } , "Discovered $discoverednum node." ;
}
if ( @ discoverednodes ) {
unless ( $ long ) {
push @ { $ rsp - > { data } } , sprintf ( " %-40s%-20s%-15s%-10s%-10s" , 'UUID' , 'NODE' , , 'METHOD' , 'MTM' , 'SERIAL' ) ;
}
foreach ( @ discoverednodes ) {
push @ { $ rsp - > { data } } , "$_" ;
}
}
xCAT::MsgUtils - > message ( "I" , $ rsp , $ callback ) ;
}
= head3 nodediscoverstatus
Display the discovery status
= cut
sub nodediscoverstatus {
my $ callback = shift ;
my $ args = shift ;
my $ usage = sub {
my $ cb = shift ;
my $ msg = shift ;
my $ rsp ;
if ( $ msg ) {
push @ { $ rsp - > { data } } , $ msg ;
xCAT::MsgUtils - > message ( "E" , $ rsp , $ cb , 1 ) ;
}
my $ usageinfo = " nodediscoverstatus: Display the discovery process status .
Usage:
nodediscoverstatus [ - h | - - help | - v | - - version ] " ;
$ rsp = ( ) ;
push @ { $ rsp - > { data } } , $ usageinfo ;
xCAT::MsgUtils - > message ( "I" , $ rsp , $ cb ) ;
} ;
if ( $ args ) {
@ ARGV = @$ args ;
}
my ( $ type , $ uuid , $ long , $ help , $ ver ) ;
if ( ! GetOptions (
'h|help' = > \ $ help ,
'V|verbose' = > \ $ ::VERBOSE ,
'v|version' = > \ $ ver ) ) {
$ usage - > ( $ callback ) ;
return ;
}
if ( $ help ) {
$ usage - > ( $ callback ) ;
return ;
}
if ( $ ver ) {
& displayver ( $ callback ) ;
return ;
}
# Check the running of sequential discovery
my @ SEQDiscover = xCAT::TableUtils - > get_site_attribute ( "__SEQDiscover" ) ;
my @ PCMDiscover = xCAT::TableUtils - > get_site_attribute ( "__PCMDiscover" ) ;
if ( $ SEQDiscover [ 0 ] ) {
my $ rsp ;
push @ { $ rsp - > { data } } , "Sequential discovery is running." ;
push @ { $ rsp - > { data } } , " The parameters used for discovery: " . $ SEQDiscover [ 0 ] ;
xCAT::MsgUtils - > message ( "I" , $ rsp , $ callback ) ;
} elsif ( $ PCMDiscover [ 0 ] ) {
2013-04-12 08:12:12 +00:00
my $ rsp ;
push @ { $ rsp - > { data } } , "Node discovery for all nodes using profiles is running" ;
xCAT::MsgUtils - > message ( "I" , $ rsp , $ callback ) ;
2013-04-06 09:40:39 +00:00
} else {
my $ rsp ;
push @ { $ rsp - > { data } } , "Sequential Discovery is stopped." ;
push @ { $ rsp - > { data } } , "Profile Discovery is stopped." ;
xCAT::MsgUtils - > message ( "I" , $ rsp , $ callback ) ;
}
}
2013-05-16 08:19:53 +00:00
= head3 nodediscoverdef
Define the undefined entry from the discoverydata table to a specific node
Or clean the discoverydata table
= cut
sub nodediscoverdef {
my $ callback = shift ;
my $ subreq = shift ;
my $ args = shift ;
# The subroutine used to display the usage message
my $ usage = sub {
my $ cb = shift ;
my $ msg = shift ;
my $ rsp ;
if ( $ msg ) {
push @ { $ rsp - > { data } } , $ msg ;
xCAT::MsgUtils - > message ( "E" , $ rsp , $ cb , 1 ) ;
}
my $ usageinfo = " nodediscoverdef: Define the undefined discovery request , or clean the discovery entries in the discoverydata table ( Which can be displayed by nodediscoverls command ) .
Usage:
nodediscoverdef - u uuid - n node
nodediscoverdef - r - u uuid
nodediscoverdef - r - t { seq | profile | switch | blade | manual | undef | all }
nodediscoverdef [ - h | - - help | - v | - - version ] " ;
$ rsp = ( ) ;
push @ { $ rsp - > { data } } , $ usageinfo ;
xCAT::MsgUtils - > message ( "I" , $ rsp , $ cb ) ;
} ;
# Parse arguments
if ( $ args ) {
@ ARGV = @$ args ;
}
my ( $ type , $ uuid , $ node , $ remove , $ help , $ ver ) ;
if ( ! GetOptions (
'u=s' = > \ $ uuid ,
'n=s' = > \ $ node ,
't=s' = > \ $ type ,
'r' = > \ $ remove ,
'h|help' = > \ $ help ,
'V|verbose' = > \ $ ::VERBOSE ,
'v|version' = > \ $ ver ) ) {
$ usage - > ( $ callback ) ;
return ;
}
if ( $ help ) {
$ usage - > ( $ callback ) ;
return ;
}
if ( $ ver ) {
& displayver ( $ callback ) ;
return ;
}
# open the discoverydata table for the subsequent using
my $ distab = xCAT::Table - > new ( "discoverydata" ) ;
unless ( $ distab ) {
xCAT::MsgUtils - > message ( "S" , "Discovery Error: Could not open table: discoverydata." ) ;
return ;
}
if ( $ remove ) {
# handle the -r to remove the entries from discoverydata table
if ( ! ( $ uuid || $ type ) || $ node ) {
$ usage - > ( $ callback ) ;
return ;
}
if ( $ uuid && $ type ) {
$ usage - > ( $ callback ) ;
return ;
}
if ( $ uuid ) {
# handle the -r -u <uuid>
my @ disdata = $ distab - > getAllAttribsWhere ( "uuid='$uuid'" , 'method' ) ;
unless ( @ disdata ) {
xCAT::MsgUtils - > message ( "E" , { data = > [ "Cannot find discovery entry with uuid equals [$uuid]." ] } , $ callback ) ;
return ;
}
$ distab - > delEntries ( { uuid = > $ uuid } ) ;
$ distab - > commit ( ) ;
} elsif ( $ type ) {
# handle the -r -t <...>
if ( $ type !~ /^(seq|profile|switch|blade|manual|undef|all)$/ ) {
$ usage - > ( $ callback , "The discovery type \'$type\' is not supported." ) ;
return ;
}
if ( $ type eq "all" ) {
# remove all the entries from discoverydata table
# there's no subroutine to remove all the entries from a table, so just make code to work around
# get all the entries first
my @ disdata = $ distab - > getAllAttribs ( 'uuid' , 'method' ) ;
my % methodlist ;
foreach my $ ent ( @ disdata ) {
if ( $ ent - > { 'method' } ) {
# if the entry has 'method' att set, classify them and remove at once
$ methodlist { $ ent - > { 'method' } } = 1 ;
} else {
# if 'method' is not set, remove the entry directly
$ distab - > delEntries ( { uuid = > $ ent - > { 'uuid' } } ) ;
}
}
# remove entries which have method att been set
2013-07-11 08:31:44 +00:00
foreach ( keys % methodlist ) {
2013-05-16 08:19:53 +00:00
$ distab - > delEntries ( { method = > $ _ } ) ;
}
$ distab - > commit ( ) ;
} else {
# remove the specific type of discovery entries
if ( $ type =~ /^seq/ ) {
$ type = "sequential" ;
}
$ distab - > delEntries ( { method = > $ type } ) ;
$ distab - > commit ( ) ;
}
}
xCAT::MsgUtils - > message ( "I" , { data = > [ "Removing discovery entries finished." ] } , $ callback ) ;
} elsif ( $ uuid ) {
# define the undefined entry to a node
if ( ! $ node ) {
$ usage - > ( $ callback ) ;
return ;
}
# make sure the node is valid.
my @ validnode = noderange ( $ node ) ;
if ( $# validnode != 0 ) {
xCAT::MsgUtils - > message ( "E" , { data = > [ "The node [$node] should be a valid xCAT node." ] } , $ callback ) ;
return ;
}
$ node = $ validnode [ 0 ] ;
# to define the a request to a node, reuse the 'discovered' command to update the node
# so the procedure will be that regenerate the request base on the attributes which stored in the discoverydata table
# get all the attributes for the entry from the discoverydata table
my @ disattrs = ( 'uuid' , 'node' , 'method' , 'discoverytime' , 'arch' , 'cpucount' , 'cputype' , 'memory' , 'mtm' , 'serial' , 'nicdriver' , 'nicipv4' , 'nichwaddr' , 'nicpci' , 'nicloc' , 'niconboard' , 'nicfirm' , 'switchname' , 'switchaddr' , 'switchdesc' , 'switchport' , 'otherdata' ) ;
my @ disdata = $ distab - > getAllAttribsWhere ( "uuid='$uuid'" , @ disattrs ) ;
unless ( @ disdata ) {
xCAT::MsgUtils - > message ( "E" , { data = > [ "Cannot find discovery entry with uuid equals $uuid" ] } , $ callback ) ;
return ;
}
# generate the request which is used to define the node
my $ request ;
my $ ent = @ disdata [ 0 ] ;
my $ interfaces ;
my $ otherdata ;
foreach my $ key ( keys %$ ent ) {
if ( $ key =~ /(nicdriver|nicfirm|nicipv4|nichwaddr|nicpci|nicloc|niconboard|switchaddr|switchname|switchport)/ ) {
# these entries are formatted as: eth0!xxx,eth1!xxx. split it and generate the request as eth0 {...}, eth1 {...}
my @ ifs = split ( /,/ , $ ent - > { $ key } ) ;
foreach ( @ ifs ) {
my ( $ if , $ value ) = split ( '!' , $ _ ) ;
my $ origname = $ key ;
if ( $ key eq "nicdriver" ) {
$ origname = "driver" ;
} elsif ( $ key eq "nicfirm" ) {
$ origname = "firmdesc" ;
} elsif ( $ key eq "nicipv4" ) {
$ origname = "ip4address" ;
} elsif ( $ key eq "nichwaddr" ) {
$ origname = "hwaddr" ;
} elsif ( $ key eq "nicpci" ) {
$ origname = "pcidev" ;
} elsif ( $ key eq "nicloc" ) {
$ origname = "location" ;
} elsif ( $ key eq "niconboard" ) {
$ origname = "onboardeth" ;
}
push @ { $ interfaces - > { $ if } - > { $ origname } } , $ value ;
}
} elsif ( $ key eq "otherdata" ) {
# this entry is just keep as is, so translate to hash is enough
$ otherdata = eval { XMLin ( $ ent - > { $ key } , SuppressEmpty = > undef , ForceArray = > 1 ) } ;
} elsif ( $ key eq "switchdesc" ) {
# just ingore the switchdesc, since it include ','
} else {
# for general attrs which just have one first level
$ request - > { $ key } = [ $ ent - > { $ key } ] ;
}
}
# add the interface part to the request hash
if ( $ interfaces ) {
foreach ( keys %$ interfaces ) {
$ interfaces - > { $ _ } - > { 'devname' } = [ $ _ ] ;
push @ { $ request - > { nic } } , $ interfaces - > { $ _ } ;
}
}
# add the untouched part to the request hash
if ( $ otherdata ) {
foreach ( keys %$ otherdata ) {
$ request - > { $ _ } = $ otherdata - > { $ _ } ;
}
}
# call the 'discovered' command to update the request to a node
$ request - > { command } = [ 'discovered' ] ;
$ request - > { node } = [ $ node ] ;
$ request - > { discoverymethod } = [ 'manual' ] ;
$ request - > { updateswitch } = [ 'yes' ] ;
2013-07-01 09:10:18 +00:00
my $ rsp = $ subreq - > ( $ request ) ;
if ( defined ( $ rsp - > { errorcode } - > [ 0 ] ) ) {
xCAT::MsgUtils - > message ( "E" , $ rsp , $ callback ) ;
} else {
xCAT::MsgUtils - > message ( "I" , { data = > [ "Defined [$uuid] to node $node." ] } , $ callback ) ;
}
2013-05-16 08:19:53 +00:00
} else {
$ usage - > ( $ callback ) ;
return ;
}
}
2013-04-06 09:40:39 +00:00
sub process_request {
my $ request = shift ;
my $ callback = shift ;
my $ subreq = shift ;
my $ command = $ request - > { command } - > [ 0 ] ;
my $ args = $ request - > { arg } ;
if ( $ command eq "findme" ) {
findme ( $ request , $ callback , $ subreq ) ;
} elsif ( $ command eq "nodediscoverstart" ) {
nodediscoverstart ( $ callback , $ args ) ;
} elsif ( $ command eq "nodediscoverstop" ) {
nodediscoverstop ( $ callback , $ args ) ;
} elsif ( $ command eq "nodediscoverls" ) {
nodediscoverls ( $ callback , $ args ) ;
} elsif ( $ command eq "nodediscoverstatus" ) {
nodediscoverstatus ( $ callback , $ args ) ;
2013-05-16 08:19:53 +00:00
} elsif ( $ command eq "nodediscoverdef" ) {
nodediscoverdef ( $ callback , $ subreq , $ args ) ;
2013-04-06 09:40:39 +00:00
}
}
= head3 getfreenodes
Get the free nodes base on the user specified noderange and defined nodes
arg1 - the noderange
arg2 - " all ' : return all the free nodes ; otherwise just return one .
= cut
sub getfreenodes () {
my $ noderange = shift ;
my $ all = shift ;
my @ freenodes ;
# get all the nodes from noderange
my @ nodes = noderange ( $ noderange , 0 ) ;
# get all nodes from nodelist and mac table
my $ nltb = xCAT::Table - > new ( 'nodelist' ) ;
unless ( $ nltb ) {
xCAT::MsgUtils - > message ( "S" , "Discovery Error: Could not open table: nodelist." ) ;
return ;
}
my $ mactb = xCAT::Table - > new ( 'mac' ) ;
unless ( $ mactb ) {
xCAT::MsgUtils - > message ( "S" , "Discovery Error: Could not open table: mac." ) ;
return ;
}
2013-05-22 14:58:46 +00:00
# if mac address has been set, the node is not free
2013-04-06 09:40:39 +00:00
my $ nlent = $ nltb - > getNodesAttribs ( \ @ nodes , [ 'groups' ] ) ;
my $ macent = $ mactb - > getNodesAttribs ( \ @ nodes , [ 'mac' ] ) ;
foreach my $ node ( @ nodes ) {
if ( $ nlent - > { $ node } - > [ 0 ] ) {
unless ( $ macent - > { $ node } - > [ 0 ] && $ macent - > { $ node } - > [ 0 ] - > { 'mac' } ) {
push @ freenodes , $ node ;
unless ( $ all ) { last ; }
}
} else {
push @ freenodes , $ node ;
unless ( $ all ) { last ; }
}
}
unless ( @ freenodes ) {
return ;
}
if ( $ all ) {
return @ freenodes ;
} else {
return $ freenodes [ 0 ] ;
}
}
2013-05-22 14:58:46 +00:00
= head3 getpredefips
2013-06-08 23:32:38 +00:00
Get the ips which have been predefined to host or bmc
2013-05-22 14:58:46 +00:00
arg1 - a refenrece to the array of nodes
arg2 - type: host , bmc
2013-04-06 09:40:39 +00:00
2013-05-22 14:58:46 +00:00
return : hash { ip } = node
2013-04-06 09:40:39 +00:00
= cut
2013-05-22 14:58:46 +00:00
sub getpredefips {
2013-04-06 09:40:39 +00:00
my $ freenode = shift ;
my $ type = shift ; # type: host, bmc
my $ hoststb = xCAT::Table - > new ( 'hosts' ) ;
unless ( $ hoststb ) {
xCAT::MsgUtils - > message ( "S" , "Discovery Error: Could not open table: hosts." ) ;
}
2013-05-22 14:58:46 +00:00
my % predefips ; # to have the ip which prefined to the nodes
2013-04-06 09:40:39 +00:00
if ( $ type eq "bmc" ) {
2013-06-08 23:32:38 +00:00
# Find the bmc name from the ipmi table.
# if ipmi.bmc is an IP address, that means this is the IP of bmc
my @ freebmc ;
my % node2bmc ; # $node2bmc{$node} = $bmc;
2013-05-22 14:58:46 +00:00
my $ ipmitab = xCAT::Table - > new ( 'ipmi' ) ;
if ( $ ipmitab ) {
my $ ipmient = $ ipmitab - > getNodesAttribs ( $ freenode , [ 'bmc' ] ) ;
foreach ( @$ freenode ) {
2013-06-08 23:32:38 +00:00
if ( defined ( $ ipmient - > { $ _ } - > [ 0 ] - > { 'bmc' } ) ) {
if ( $ ipmient - > { $ _ } - > [ 0 ] - > { 'bmc' } =~ /\d+\.\d+\.\d+\.\d+/ ) {
$ predefips { $ ipmient - > { $ _ } - > [ 0 ] - > { 'bmc' } } = $ _ . "-bmc" ;
} else {
push @ freebmc , $ ipmient - > { $ _ } - > [ 0 ] - > { 'bmc' } ;
$ node2bmc { $ _ } = $ ipmient - > { $ _ } - > [ 0 ] - > { 'bmc' } ;
}
2013-05-22 14:58:46 +00:00
}
}
}
2013-04-06 09:40:39 +00:00
2013-06-08 23:32:38 +00:00
# check the system resolution first, then host.ip, then host.otherinterfaces
2013-05-22 14:58:46 +00:00
my $ freenodeent = $ hoststb - > getNodesAttribs ( \ @ freebmc , [ 'ip' ] ) ;
foreach ( @ freebmc ) {
my $ nodeip = xCAT::NetworkUtils - > getipaddr ( $ _ ) ;
if ( $ nodeip ) {
2013-06-08 23:32:38 +00:00
# handle the bmc which could be resolved to an IP by system
2013-05-22 14:58:46 +00:00
$ predefips { $ nodeip } = $ _ ;
} else {
2013-06-08 23:32:38 +00:00
# handle the bmc which IP was defined in the hosts.ip
2013-05-22 14:58:46 +00:00
if ( defined ( $ freenodeent - > { $ _ } - > [ 0 ] ) && $ freenodeent - > { $ _ } - > [ 0 ] - > { 'ip' } ) {
$ predefips { $ freenodeent - > { $ _ } - > [ 0 ] - > { 'ip' } } = $ _ ;
}
}
}
2013-04-06 09:40:39 +00:00
2013-06-08 23:32:38 +00:00
# handle the bmcs which bmc has been set in the hosts.otherinterfaces
2013-05-22 14:58:46 +00:00
$ freenodeent = $ hoststb - > getNodesAttribs ( $ freenode , [ 'otherinterfaces' ] ) ;
foreach ( @$ freenode ) {
2013-06-08 23:32:38 +00:00
if ( defined ( $ node2bmc { $ _ } ) ) {
# for bmc node, search the hosts.otherinterface to see whether there's perdefined ip for bmc
my $ bmcip = getbmcip_otherinterfaces ( $ _ , $ node2bmc { $ _ } , $ freenodeent - > { $ _ } - > [ 0 ] - > { 'otherinterfaces' } ) ;
if ( $ bmcip ) {
$ predefips { $ bmcip } = $ node2bmc { $ _ } ;
}
2013-05-22 14:58:46 +00:00
}
}
} elsif ( $ type eq "host" ) {
# get the predefined node which ip has been set in the hosts.ip
my $ freenodeent = $ hoststb - > getNodesAttribs ( $ freenode , [ 'ip' ] ) ;
foreach ( @$ freenode ) {
my $ nodeip = xCAT::NetworkUtils - > getipaddr ( $ _ ) ;
if ( $ nodeip ) {
$ predefips { $ nodeip } = $ _ ;
} else {
if ( defined ( $ freenodeent - > { $ _ } - > [ 0 ] ) && $ freenodeent - > { $ _ } - > [ 0 ] - > { 'ip' } ) {
$ predefips { $ freenodeent - > { $ _ } - > [ 0 ] - > { 'ip' } } = $ _ ;
}
}
2013-04-06 09:40:39 +00:00
}
}
2013-05-22 14:58:46 +00:00
return \ % predefips ;
}
= head3 getfreeips
Get the free ips base on the user specified ip range
arg1 - the ip range . Two format are suported: 192.168 .1 .1 - 192.168 .2 .50 ; 192.168 . [ 1 - 2 ] . [ 10 - 100 ]
arg2 - all the free nodes
arg3 - type: host , bmc
arg4 - " all ' : return free ips for all the free nodes ; otherwise just return the first one .
return : array of all free ips or one ip base on the arg4
= cut
sub getfreeips {
my $ iprange = shift ;
my $ freenode = shift ;
my $ type = shift ; # type: host, bmc
my $ all = shift ;
my @ freeips ;
my % predefips ; # to have the ip which prefined to the nodes
my $ hoststb = xCAT::Table - > new ( 'hosts' ) ;
unless ( $ hoststb ) {
xCAT::MsgUtils - > message ( "S" , "Discovery Error: Could not open table: hosts." ) ;
}
my @ freebmc ;
2013-04-06 09:40:39 +00:00
my % usedips = ( ) ;
2013-05-22 14:58:46 +00:00
if ( $ type eq "bmc" ) {
# get the host ip for all predefind nodes from $freenode
% predefips = % { getpredefips ( $ freenode , "bmc" ) } ;
# get all the used ips, the predefined ip should be ignored
my @ hostsent = $ hoststb - > getAllNodeAttribs ( [ 'node' , 'ip' , 'otherinterfaces' ] ) ;
2013-06-08 23:32:38 +00:00
# Find the bmc name from the ipmi table.
# if ipmi.bmc is an IP address, that means this is the IP of bmc
my % node2bmc ; # $node2bmc{$node} = $bmc;
my $ ipmitab = xCAT::Table - > new ( 'ipmi' ) ;
if ( $ ipmitab ) {
my @ ipmients = $ ipmitab - > getAllNodeAttribs ( [ 'node' , 'bmc' ] ) ;
foreach my $ ipmient ( @ ipmients ) {
if ( defined ( $ ipmient - > { 'bmc' } ) ) {
if ( $ ipmient - > { 'bmc' } =~ /\d+\.\d+\.\d+\.\d+/ ) {
unless ( $ predefips { $ ipmient - > { 'bmc' } } ) {
$ usedips { $ ipmient - > { 'bmc' } } = 1 ;
}
} else {
$ node2bmc { $ ipmient - > { 'node' } } = $ ipmient - > { 'bmc' } ;
}
}
}
}
2013-05-22 14:58:46 +00:00
foreach my $ host ( @ hostsent ) {
2013-06-08 23:32:38 +00:00
# handle the case that bmc has an entry in the hosts table
my $ nodeip = xCAT::NetworkUtils - > getipaddr ( $ host - > { 'node' } ) ;
2013-05-22 14:58:46 +00:00
if ( $ nodeip ) {
unless ( $ predefips { $ nodeip } ) {
$ usedips { $ nodeip } = 1 ;
}
} else {
if ( defined ( $ host - > { 'ip' } ) && ! $ predefips { $ host - > { 'ip' } } ) {
$ usedips { $ host - > { 'ip' } } = 1 ;
}
}
# handle the case that the bmc<->ip mapping is specified in hosts.otherinterfaces
2013-06-08 23:32:38 +00:00
if ( defined ( $ node2bmc { $ host - > { 'node' } } ) ) {
my $ bmcip = xCAT::NetworkUtils - > getipaddr ( $ node2bmc { $ host - > { 'node' } } ) ;
if ( $ bmcip ) {
unless ( $ predefips { $ bmcip } ) {
$ usedips { $ bmcip } = 1 ;
}
} else {
if ( defined ( $ host - > { 'otherinterfaces' } ) ) {
my $ bmcip = getbmcip_otherinterfaces ( $ host - > { 'node' } , $ node2bmc { $ host - > { 'node' } } , $ host - > { 'otherinterfaces' } ) ;
unless ( $ predefips { $ bmcip } ) {
$ usedips { $ bmcip } = 1 ;
}
}
2013-05-22 14:58:46 +00:00
}
}
}
} elsif ( $ type eq "host" ) {
# get the bmc ip for all predefind nodes from $freenode
% predefips = % { getpredefips ( $ freenode , "host" ) } ;
# get all the used ips, the predefined ip should be ignored
my @ hostsent = $ hoststb - > getAllNodeAttribs ( [ 'node' , 'ip' ] ) ;
foreach my $ host ( @ hostsent ) {
2013-06-08 23:32:38 +00:00
my $ nodeip = xCAT::NetworkUtils - > getipaddr ( $ host - > { 'node' } ) ;
2013-05-22 14:58:46 +00:00
if ( $ nodeip ) {
unless ( $ predefips { $ nodeip } ) {
$ usedips { $ nodeip } = 1 ;
}
} else {
if ( defined ( $ host - > { 'ip' } ) && ! $ predefips { $ host - > { 'ip' } } ) {
$ usedips { $ host - > { 'ip' } } = 1 ;
}
}
2013-04-06 09:40:39 +00:00
}
}
2013-05-22 14:58:46 +00:00
# to calculate the free IP. free ip = 'ip in the range' - 'used ip'
2013-04-06 09:40:39 +00:00
if ( $ iprange =~ /(\d+\.\d+\.\d+\.\d+)-(\d+\.\d+\.\d+\.\d+)/ ) {
2013-05-22 14:58:46 +00:00
# if ip range format is 192.168.1.0-192.168.1.200
2013-04-06 09:40:39 +00:00
my ( $ startip , $ endip ) = ( $ 1 , $ 2 ) ;
my $ startnum = xCAT::NetworkUtils - > ip_to_int ( $ startip ) ;
my $ endnum = xCAT::NetworkUtils - > ip_to_int ( $ endip ) ;
while ( $ startnum <= $ endnum ) {
my $ ip = xCAT::NetworkUtils - > int_to_ip ( $ startnum ) ;
unless ( $ usedips { $ ip } ) {
push @ freeips , $ ip ;
unless ( $ all ) { last ; }
}
$ startnum + + ;
}
} elsif ( $ iprange ) {
# use the noderange to expand the range
my @ ips = noderange ( $ iprange , 0 ) ;
foreach my $ ip ( @ ips ) {
unless ( $ usedips { $ ip } ) {
push @ freeips , $ ip ;
unless ( $ all ) { last ; }
}
}
} else {
# only find the ip which mapping to the node
}
unless ( @ freeips ) {
return ;
}
if ( $ all ) {
return @ freeips ;
} else {
return $ freeips [ 0 ] ;
}
}
2013-05-22 14:58:46 +00:00
= head3 getbmcip_otherinterfaces
Parse the value in the hosts . otherinterfaces
arg1 - node
2013-06-08 23:32:38 +00:00
arg2 - bmc name
arg3 - value in the hosts . otherinterfaces
2013-05-22 14:58:46 +00:00
return : the ip of the node <node> - bmc
= cut
sub getbmcip_otherinterfaces
{
2013-06-08 23:32:38 +00:00
my $ node = shift ;
my $ bmc = shift ;
2013-05-22 14:58:46 +00:00
my $ otherinterfaces = shift ;
my @ itf_pairs = split ( /,/ , $ otherinterfaces ) ;
foreach ( @ itf_pairs )
{
my ( $ itf , $ ip ) ;
if ( $ _ =~ /!/ ) {
( $ itf , $ ip ) = split ( /!/ , $ _ ) ;
} else {
( $ itf , $ ip ) = split ( /:/ , $ _ ) ;
}
if ( $ itf =~ /^-/ )
{
$ itf = $ node . $ itf ;
}
2013-06-08 23:32:38 +00:00
if ( $ itf eq $ bmc ) {
2013-05-22 14:58:46 +00:00
return xCAT::NetworkUtils - > getipaddr ( $ ip ) ;
}
}
return ;
}
2013-04-06 09:40:39 +00:00
1 ;