2012-03-28 21:06:04 +00:00
package xCAT_plugin::slpdiscover ;
use strict ;
use xCAT::SvrUtils qw/sendmsg/ ;
use xCAT::SLP ;
2012-05-18 22:48:06 +00:00
use xCAT::NetworkUtils ;
use xCAT::SSHInteract ;
2012-03-28 21:06:04 +00:00
use xCAT::MacMap ;
2012-05-19 21:47:28 +00:00
use xCAT_plugin::bmcconfig ;
2012-04-04 14:35:13 +00:00
my $ defaultbladeuser ;
my $ defaultbladepass ;
2012-06-19 14:35:27 +00:00
my $ currentbladepass ;
my $ currentbladeuser ;
2012-04-04 14:35:13 +00:00
my $ mpahash ;
2012-03-28 21:06:04 +00:00
sub handled_commands {
return {
slpdiscover = > "slpdiscover" ,
} ;
} ;
my $ callback ;
my $ docmd ;
2012-05-19 21:13:55 +00:00
my % doneaddrs ;
2012-03-28 21:06:04 +00:00
my % ip4neigh ;
my % ip6neigh ;
2012-05-18 21:01:39 +00:00
my % flexchassismap ;
my % flexchassisuuid ;
my % nodebymp ;
my % passwordmap ;
my % chassisbyuuid ;
2012-03-28 21:06:04 +00:00
my % searchmacs ;
my % researchmacs ;
my $ macmap ;
sub get_mac_for_addr {
my $ neigh ;
my $ addr = shift ;
if ( $ addr =~ /:/ ) {
get_ipv6_neighbors ( ) ;
return $ ip6neigh { $ addr } ;
} else {
get_ipv4_neighbors ( ) ;
return $ ip4neigh { $ addr } ;
}
}
sub get_ipv4_neighbors {
#TODO: something less 'hacky'
my @ ipdata = `ip -4 neigh` ;
% ip6neigh = ( ) ;
foreach ( @ ipdata ) {
if ( /^(\S*)\s.*lladdr\s*(\S*)\s/ ) {
$ ip4neigh { $ 1 } = $ 2 ;
}
}
}
sub get_ipv6_neighbors {
#TODO: something less 'hacky'
my @ ipdata = `ip -6 neigh` ;
% ip6neigh = ( ) ;
foreach ( @ ipdata ) {
if ( /^(\S*)\s.*lladdr\s*(\S*)\s/ ) {
$ ip6neigh { $ 1 } = $ 2 ;
}
}
}
sub handle_new_slp_entity {
my $ data = shift ;
delete $ data - > { sockaddr } ; #won't need it
2012-05-19 13:46:05 +00:00
my $ mac = get_mac_for_addr ( $ data - > { peername } ) ;
2012-05-18 22:48:06 +00:00
if ( $ data - > { SrvType } eq "service:management-hardware.IBM:integrated-management-module2" and $ data - > { attributes } - > { "enclosure-form-factor" } - > [ 0 ] eq "BC2" ) {
2012-05-19 13:46:05 +00:00
$ data - > { macaddress } = $ mac ;
2012-05-18 21:01:39 +00:00
#this is a Flex ITE, don't go mac searching for it, but remember the chassis UUID for later
2012-05-24 13:50:37 +00:00
if ( $ flexchassismap { $ data - > { attributes } - > { "chassis-uuid" } - > [ 0 ] } - > { $ mac } and $ data - > { peername } !~ /fe80/ ) {
return ;
}
$ flexchassismap { $ data - > { attributes } - > { "chassis-uuid" } - > [ 0 ] } - > { $ mac } = $ data ;
2012-05-18 21:01:39 +00:00
return ;
}
2012-03-28 21:06:04 +00:00
unless ( $ mac ) { return ; }
$ searchmacs { $ mac } = $ data ;
}
sub process_request {
my $ request = shift ;
$ callback = shift ;
$ docmd = shift ;
% searchmacs = ( ) ;
2012-05-18 21:01:39 +00:00
my $ srvtypes = [ qw/service:management-hardware.IBM:chassis-management-module service:management-hardware.IBM:management-module service:management-hardware.IBM:integrated-management-module2/ ] ;
2012-03-28 21:06:04 +00:00
xCAT::SLP:: dodiscover ( SrvTypes = > $ srvtypes , Callback = > \ & handle_new_slp_entity ) ;
2012-08-03 08:50:15 +00:00
2012-04-04 14:35:13 +00:00
my $ mpatab = xCAT::Table - > new ( "mpa" , - create = > 0 ) ;
my @ mpaentries ;
$ mpahash = { } ;
2012-06-19 14:35:27 +00:00
if ( ref $ request - > { environment } and ref $ request - > { environment } - > [ 0 ] - > { XCAT_CURRENTPASS } ) {
$ currentbladepass = $ request - > { environment } - > [ 0 ] - > { XCAT_CURRENTPASS } - > [ 0 ] ;
} else {
$ currentbladepass = "PASSW0RD" ;
}
if ( ref $ request - > { environment } and ref $ request - > { environment } - > [ 0 ] - > { XCAT_CURRENTUSER } ) {
$ currentbladeuser = $ request - > { environment } - > [ 0 ] - > { XCAT_CURRENTUSER } - > [ 0 ] ;
} else {
$ currentbladeuser = "USERID" ;
}
2012-04-04 14:35:13 +00:00
if ( $ mpatab ) {
@ mpaentries = $ mpatab - > getAllNodeAttribs ( [ qw/mpa username password/ ] ) ;
foreach ( @ mpaentries ) {
$ mpahash - > { $ _ - > { mpa } } = $ _ ;
}
}
my $ passwdtab = xCAT::Table - > new ( "passwd" , - create = > 0 ) ;
$ defaultbladeuser = "USERID" ;
$ defaultbladepass = "" ;
if ( $ passwdtab ) {
my @ ents = $ passwdtab - > getAttribs ( { key = > 'blade' } , 'username' , 'password' ) ;
foreach ( @ ents ) {
if ( $ _ - > { username } eq "HMC" ) { next ; }
if ( $ _ - > { username } ) { $ defaultbladeuser = $ _ - > { username } ; }
if ( $ _ - > { password } ) { $ defaultbladepass = $ _ - > { password } ; }
}
}
my $ mactab = xCAT::Table - > new ( "mac" ) ;
my % machash ;
2012-08-03 08:50:15 +00:00
my % node2machash ;
2012-04-05 17:06:39 +00:00
my % macuphash ;
my @ maclist = $ mactab - > getAllNodeAttribs ( [ qw/node mac/ ] ) ;
2012-04-04 14:35:13 +00:00
foreach ( @ maclist ) {
$ machash { $ _ - > { node } } = $ _ - > { mac } ;
2012-08-03 08:50:15 +00:00
$ node2machash { $ _ - > { mac } } = $ _ - > { node } ;
2012-04-04 14:35:13 +00:00
}
2012-05-18 21:01:39 +00:00
my $ mptab = xCAT::Table - > new ( 'mp' ) ;
if ( $ mptab ) {
2012-05-19 13:46:18 +00:00
my @ mpents = $ mptab - > getAllNodeAttribs ( [ 'node' , 'mpa' , 'id' ] ) ;
2012-05-18 21:01:39 +00:00
foreach ( @ mpents ) {
2012-05-19 13:46:18 +00:00
$ nodebymp { $ _ - > { mpa } } - > { $ _ - > { id } } = $ _ - > { node } ;
2012-05-18 21:01:39 +00:00
}
}
2012-08-03 08:50:15 +00:00
$ macmap = xCAT::MacMap - > new ( ) ;
$ macmap - > refresh_table ( ) ;
my @ toconfig ;
foreach my $ mac ( keys ( % searchmacs ) ) {
my $ node = $ macmap - > find_mac ( $ mac , 1 ) ;
unless ( $ node ) {
if ( defined $ node2machash { $ mac } ) {
$ node = $ node2machash { $ mac } ;
} else {
next ;
}
}
my $ data = $ searchmacs { $ mac } ;
$ data - > { nodename } = $ node ;
$ data - > { macaddress } = $ mac ;
$ chassisbyuuid { $ data - > { attributes } - > { "enclosure-uuid" } - > [ 0 ] } = $ node ;
push @ toconfig , $ data ;
}
2012-03-28 21:06:04 +00:00
foreach my $ data ( @ toconfig ) {
2012-04-04 14:35:13 +00:00
my $ mac = $ data - > { macaddress } ;
my $ nodename = $ data - > { nodename } ;
my $ addr = $ data - > { peername } ; #todo, use sockaddr and remove the 427 port from it instead?
if ( $ addr =~ /^fe80/ ) { #Link local address requires scope index
$ addr . = "%" . $ data - > { scopeid } ;
}
2012-05-19 13:46:18 +00:00
$ flexchassisuuid { $ nodename } = $ data - > { attributes } - > { "enclosure-uuid" } - > [ 0 ] ;
2012-08-03 08:50:15 +00:00
2012-04-04 14:35:13 +00:00
if ( $ data - > { SrvType } eq "service:management-hardware.IBM:chassis-management-module" ) {
2012-05-24 19:40:21 +00:00
sendmsg ( ":Found " . $ data - > { SrvType } . " at address $addr" , $ callback , $ nodename ) ;
2012-08-03 08:50:15 +00:00
setup_cmm_pass ( $ nodename ) ;
if ( $ machash { $ nodename } =~ /$mac/i ) { #ignore prospects already known to mac table
configure_hosted_elements ( $ nodename ) ;
next ;
}
2012-04-04 14:35:13 +00:00
unless ( do_blade_setup ( $ data , curraddr = > $ addr ) ) {
next ;
}
2012-05-18 21:01:39 +00:00
configure_hosted_elements ( $ nodename ) ;
unless ( do_blade_setup ( $ data , curraddr = > $ addr , pass2 = > 1 ) ) {
next ;
}
2012-05-24 19:40:21 +00:00
sendmsg ( ":Configuration complete, configuration may take a few minutes to take effect" , $ callback , $ nodename ) ;
2012-04-05 17:06:39 +00:00
$ macuphash { $ nodename } = { mac = > $ mac } ;
2012-04-04 14:35:13 +00:00
}
2012-03-28 21:06:04 +00:00
}
2012-04-10 12:34:04 +00:00
$ mactab - > setNodesAttribs ( \ % macuphash ) ;
2012-03-28 21:06:04 +00:00
}
2012-05-18 22:48:06 +00:00
sub setupIMM {
my $ node = shift ;
my % args = @ _ ;
2012-05-19 13:46:05 +00:00
my $ slpdata = $ args { slpdata } ;
2012-10-22 20:09:07 +00:00
my $ ipmitab = xCAT::Table - > new ( 'ipmi' , - create = > 1 ) ;
2012-05-19 13:46:05 +00:00
my $ ient = $ ipmitab - > getNodeAttribs ( $ node , [ qw/bmc bmcid/ ] , prefetchcache = > 1 ) ;
2012-05-18 22:48:06 +00:00
my $ newaddr ;
if ( $ ient ) {
2012-05-19 13:46:05 +00:00
my $ bmcid = $ ient - > { bmcid } ;
2012-08-03 08:50:15 +00:00
if ( $ bmcid and $ slpdata - > { macaddress } =~ /$bmcid/ ) {
sendmsg ( "The IMM has been configured (ipmi.bmcid). Skipped." , $ callback , $ node ) ;
return ;
} #skip configuration, we already know this one
2012-05-18 22:48:06 +00:00
$ newaddr = $ ient - > { bmc } ;
}
2012-10-22 20:09:07 +00:00
my @ ips = ( ) ;
my $ autolla = 0 ;
if ( $ newaddr and not $ newaddr =~ /^fe80:.*%.*/ ) {
2012-05-18 22:48:06 +00:00
@ ips = xCAT::NetworkUtils:: getipaddr ( $ newaddr , GetAllAddresses = > 1 ) ;
2012-10-22 20:09:07 +00:00
} else {
if ( $ args { curraddr } =~ /^fe80:.*%.*/ ) { #if SLP were able to glean an LLA out of this, let's just roll with that result
$ ipmitab - > setNodeAttribs ( $ node , { bmc = > $ args { curraddr } } ) ;
$ autolla = 1 ;
}
2012-05-18 22:48:06 +00:00
}
2012-10-22 20:09:07 +00:00
if ( not scalar @ ips and not $ autolla ) {
2012-08-03 08:50:15 +00:00
sendmsg ( ":Cannot find the IP attribute for bmc" , $ callback , $ node ) ;
return ;
}
2012-10-22 20:09:07 +00:00
my $ targips ;
if ( scalar ( @ ips ) ) {
$ targips = join ( ',' , @ ips ) ;
} elsif ( $ autolla ) {
$ targips = $ args { curraddr } ;
}
sendmsg ( ":Configuration of " . $ node . "[$targips] commencing, configuration may take a few minutes to take effect" , $ callback ) ;
2012-05-23 19:19:50 +00:00
my $ child = fork ( ) ;
if ( $ child ) { return ; }
unless ( defined $ child ) { die "error spawining process" }
2012-05-18 22:48:06 +00:00
#ok, with all ip addresses in hand, time to enable IPMI and set all the ip addresses (still static only, TODO: dhcp
my $ ssh = new xCAT:: SSHInteract ( - username = > $ args { username } ,
- password = > $ args { password } ,
- host = > $ args { curraddr } ,
- nokeycheck = > 1 ,
- output_record_separator = > "\r" ,
Timeout = > 15 ,
Errmode = > 'return' ,
2012-10-10 14:16:57 +00:00
Prompt = > '/> $/' ) ;
2012-05-18 22:48:06 +00:00
if ( $ ssh and $ ssh - > atprompt ) { #we are in and good to issue commands
2012-10-31 15:21:45 +00:00
$ ssh - > cmd ( "accseccfg -pe 0 -rc 0 -ci 0 -lf 0 -lp 0" ) ; #disable the more insane password rules, this isn't by and large a human used interface
2012-05-18 22:48:06 +00:00
$ ssh - > cmd ( "users -1 -n " . $ args { username } . " -p " . $ args { password } . " -a super" ) ; #this gets ipmi going
foreach my $ ip ( @ ips ) {
if ( $ ip =~ /:/ ) {
$ ssh - > cmd ( "ifconfig eth0 -ipv6static enable -i6 $ip" ) ;
} else {
2012-05-19 21:47:28 +00:00
( my $ sip , my $ mask , my $ gw ) = xCAT_plugin::bmcconfig:: net_parms ( $ ip ) ;
2012-05-24 20:35:03 +00:00
my $ cmd = "ifconfig eth0 -c static -i $ip -s $mask" ;
2012-05-24 20:39:14 +00:00
if ( $ gw ) { $ cmd . = " -g $gw" ; }
2012-05-24 20:35:03 +00:00
$ ssh - > cmd ( $ cmd ) ;
2012-05-18 22:48:06 +00:00
}
}
2012-05-18 22:55:31 +00:00
$ ssh - > close ( ) ;
2012-05-19 13:46:18 +00:00
$ ipmitab - > setNodeAttribs ( $ node , { bmcid = > $ slpdata - > { macaddress } } ) ;
2012-05-18 22:48:06 +00:00
}
2012-05-24 19:52:17 +00:00
exit ( 0 ) ;
2012-05-18 22:48:06 +00:00
}
2012-05-18 21:01:39 +00:00
sub configure_hosted_elements {
my $ cmm = shift ;
my $ uuid = $ flexchassisuuid { $ cmm } ;
my $ node ;
my $ immdata ;
my $ slot ;
2012-05-18 22:48:06 +00:00
my $ user = $ passwordmap { $ cmm } - > { username } ;
my $ pass = $ passwordmap { $ cmm } - > { password } ;
2012-05-24 13:50:37 +00:00
foreach $ immdata ( values % { $ flexchassismap { $ uuid } } ) {
2012-05-18 21:01:39 +00:00
$ slot = $ immdata - > { attributes } - > { slot } - > [ 0 ] ;
if ( $ node = $ nodebymp { $ cmm } - > { $ slot } ) {
2012-05-18 22:48:06 +00:00
my $ addr = $ immdata - > { peername } ; #todo, use sockaddr and remove the 427 port from it instead?
if ( $ addr =~ /^fe80/ ) { #Link local address requires scope index
$ addr . = "%" . $ immdata - > { scopeid } ;
}
2012-05-19 21:47:28 +00:00
if ( $ doneaddrs { $ node } ) { next ; }
$ doneaddrs { $ node } = 1 ;
2012-05-19 13:46:05 +00:00
setupIMM ( $ node , slpdata = > $ immdata , curraddr = > $ addr , username = > $ user , password = > $ pass ) ;
2012-05-24 13:50:37 +00:00
} else {
sendmsg ( ": Ignoring target in bay $slot, no node found with mp.mpa/mp.id matching" , $ callback , $ cmm ) ;
2012-05-18 21:01:39 +00:00
}
2012-05-24 13:50:37 +00:00
2012-05-18 21:01:39 +00:00
}
2012-05-23 19:19:50 +00:00
while ( wait ( ) > 0 ) { }
2012-05-18 21:01:39 +00:00
}
2012-05-19 13:46:25 +00:00
sub setup_cmm_pass {
my $ nodename = shift ;
2012-04-04 14:35:13 +00:00
my $ localuser = $ defaultbladeuser ;
my $ localpass = $ defaultbladepass ;
if ( $ mpahash - > { $ nodename } ) {
if ( $ mpahash - > { $ nodename } - > { username } ) {
2012-07-26 18:59:08 +00:00
$ localuser = $ mpahash - > { $ nodename } - > { username } ;
2012-04-04 14:35:13 +00:00
}
if ( $ mpahash - > { $ nodename } - > { password } ) {
2012-07-26 18:59:08 +00:00
$ localpass = $ mpahash - > { $ nodename } - > { password } ;
2012-04-04 14:35:13 +00:00
}
}
2012-05-19 13:46:25 +00:00
$ passwordmap { $ nodename } - > { username } = $ localuser ;
$ passwordmap { $ nodename } - > { password } = $ localpass ;
}
sub do_blade_setup {
my $ data = shift ;
my % args = @ _ ;
my $ addr = $ args { curraddr } ;
my $ nodename = $ data - > { nodename } ;
my $ localuser = $ passwordmap { $ nodename } - > { username } ;
my $ localpass = $ passwordmap { $ nodename } - > { password } ;
2012-04-04 14:35:13 +00:00
if ( not $ localpass or $ localpass eq "PASSW0RD" ) {
sendmsg ( [ 1 , ":Password for blade must be specified in either mpa or passwd tables, and it must not be PASSW0RD" ] , $ callback , $ nodename ) ;
return 0 ;
}
require xCAT_plugin::blade ;
2012-05-18 21:01:39 +00:00
my @ cmds ;
my % exargs ;
if ( $ args { pass2 } ) {
@ cmds = qw/initnetwork=*/ ;
% exargs = ( nokeycheck = > 1 ) ; #still not at the 'right' ip, so the known hosts shouldn't be bothered
} else {
@ cmds = qw/snmpcfg=enable sshcfg=enable textid=*/ ; # initnetwork=*/; defer initnetwork until after chassis members have been configured
2012-06-19 14:35:27 +00:00
% exargs = ( curruser = > $ currentbladeuser , currpass = > $ currentbladepass ) ;
2012-05-18 21:01:39 +00:00
}
2012-05-09 13:48:02 +00:00
my $ result ;
2012-06-19 14:35:27 +00:00
$@ = "" ;
2012-05-09 13:48:02 +00:00
my $ rc = eval { $ result = xCAT_plugin::blade:: clicmds (
2012-04-04 14:35:13 +00:00
$ nodename ,
$ localuser ,
$ localpass ,
$ nodename ,
0 ,
curraddr = > $ addr ,
2012-05-18 21:01:39 +00:00
% exargs ,
2012-04-04 14:35:13 +00:00
cmds = > \ @ cmds ) ;
2012-05-09 13:48:02 +00:00
1 ;
} ;
2012-06-19 14:35:27 +00:00
my $ errmsg = $@ ;
if ( $ errmsg ) {
if ( $ errmsg =~ /Incorrect Password/ ) {
sendmsg ( [ 1 , "Failed to set up Management module due to Incorrect Password (You may try the environment variables XCAT_CURRENTUSER and/or XCAT_CURRENTPASS to try a different value)" ] , $ callback , $ nodename ) ;
} else {
sendmsg ( [ 1 , "Failed to set up Management module due to $errmsg" ] , $ callback , $ nodename ) ;
}
return 0 ;
2012-05-09 13:48:02 +00:00
}
2012-04-04 14:35:13 +00:00
if ( $ result ) {
if ( $ result - > [ 0 ] ) {
2012-06-19 14:35:27 +00:00
if ( $ result - > [ 2 ] =~ /Incorrect Password/ ) {
sendmsg ( [ 1 , "Failed to set up Management module due to Incorrect Password (You may try the environment variables XCAT_CURRENTUSER and/or XCAT_CURRENTPASS to try a different value)" ] , $ callback , $ nodename ) ;
return 0 ;
}
2012-11-21 19:59:03 +00:00
my $ errors = $ result - > [ 2 ] ;
if ( ref $ errors ) {
foreach my $ error ( @$ errors ) {
sendmsg ( [ $ result - > [ 0 ] , $ error ] , $ callback , $ nodename ) ;
}
} else {
sendmsg ( [ $ result - > [ 0 ] , $ result - > [ 2 ] ] , $ callback , $ nodename ) ;
}
2012-06-19 14:35:27 +00:00
return 0 ;
2012-04-04 14:35:13 +00:00
}
}
2012-05-19 13:46:31 +00:00
return $ rc ;
2012-04-04 14:35:13 +00:00
}
2012-03-28 21:06:04 +00:00
1 ;