2007-10-26 22:44:33 +00:00
# IBM(c) 2007 EPL license http://www.eclipse.org/legal/epl-v10.html
package xCAT_plugin::bmcconfig ;
use Data::Dumper ;
use xCAT::Table ;
2008-03-31 20:15:15 +00:00
use xCAT::MsgUtils ;
2011-05-06 20:11:07 +00:00
use xCAT::Utils ;
2012-11-29 20:30:22 +00:00
use xCAT::PasswordUtils ;
2012-11-29 22:01:42 +00:00
use xCAT::IMMUtils ;
2012-08-09 04:07:40 +00:00
use xCAT::TableUtils ;
2008-09-06 22:41:48 +00:00
use IO::Select ;
2008-02-26 18:44:34 +00:00
use Socket ;
2007-10-26 22:44:33 +00:00
sub handled_commands {
return {
getbmcconfig = > 'bmcconfig' ,
2012-11-29 20:30:22 +00:00
remoteimmsetup = > 'bmcconfig' ,
2007-10-26 22:44:33 +00:00
} ;
}
sub genpassword {
my $ length = shift ;
my $ password = '' ;
my $ characters = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890' ;
srand ; #have to reseed, rand is not rand otherwise
while ( length ( $ password ) < $ length ) {
$ password . = substr ( $ characters , int ( rand 63 ) , 1 ) ;
}
return $ password ;
}
sub net_parms {
my $ ip = shift ;
2008-03-31 20:15:15 +00:00
if ( inet_aton ( $ ip ) ) {
$ ip = inet_ntoa ( inet_aton ( $ ip ) ) ;
} else {
xCAT::MsgUtils - > message ( "S" , "Unable to resolve $ip" ) ;
return undef ;
}
2007-10-26 22:44:33 +00:00
my $ nettab = xCAT::Table - > new ( 'networks' ) ;
unless ( $ nettab ) { return undef } ;
my @ nets = $ nettab - > getAllAttribs ( 'net' , 'mask' , 'gateway' ) ;
foreach ( @ nets ) {
my $ net = $ _ - > { 'net' } ;
my $ mask = $ _ - > { 'mask' } ;
my $ gw = $ _ - > { 'gateway' } ;
$ ip =~ /([0-9]+)\.([0-9]+)\.([0-9]+)\.([0-9]+)/ ;
my $ ipnum = ( $ 1 << 24 ) + ( $ 2 << 16 ) + ( $ 3 << 8 ) + $ 4 ;
$ mask =~ /([0-9]+)\.([0-9]+)\.([0-9]+)\.([0-9]+)/ ;
my $ masknum = ( $ 1 << 24 ) + ( $ 2 << 16 ) + ( $ 3 << 8 ) + $ 4 ;
2012-05-24 20:35:10 +00:00
$ net =~ /([0-9]+)\.([0-9]+)\.([0-9]+)\.([0-9]+)/ or next ; #next if ipv6, TODO: IPv6 support
2007-10-26 22:44:33 +00:00
my $ netnum = ( $ 1 << 24 ) + ( $ 2 << 16 ) + ( $ 3 << 8 ) + $ 4 ;
2011-05-06 20:11:07 +00:00
if ( $ gw eq '<xcatmaster>' ) {
2012-08-09 04:07:40 +00:00
$ gw = xCAT::NetworkUtils - > my_ip_facing ( $ ip ) ;
2011-05-06 20:11:07 +00:00
}
2007-10-26 22:44:33 +00:00
if ( ( $ ipnum & $ masknum ) == $ netnum ) {
return ( $ ip , $ mask , $ gw ) ;
}
}
2008-03-31 20:15:15 +00:00
xCAT::MsgUtils - > message ( "S" , "xCAT BMC configuration error, no appropriate network for $ip found in networks, unable to determine netmask" ) ;
2007-10-26 22:44:33 +00:00
}
2008-09-06 22:41:48 +00:00
sub ok_with_node {
my $ node = shift ;
#Here we connect to the node on a privileged port (in the clear) and ask the
#node if it just asked us for credential. It's convoluted, but it is
#a convenient way to see if root on the ip has approved requests for
#credential retrieval. Given the nature of the situation, it is only ok
#to assent to such requests before users can log in. During postscripts
#stage in stateful nodes and during the rc scripts of stateless boot
my $ select = new IO:: Select ;
#sleep 0.5; # gawk script race condition might exist, try to lose just in case
my $ sock = new IO::Socket:: INET ( PeerAddr = > $ node ,
Proto = > "tcp" ,
PeerPort = > shift ) ;
my $ rsp ;
unless ( $ sock ) { return 0 } ;
$ select - > add ( $ sock ) ;
print $ sock "CREDOKBYYOU?\n" ;
unless ( $ select - > can_read ( 5 ) ) { #wait for data for up to five seconds
return 0 ;
}
my $ response = <$sock> ;
chomp ( $ response ) ;
if ( $ response eq "CREDOKBYME" ) {
return 1 ;
}
return 0 ;
}
2007-10-26 22:44:33 +00:00
sub process_request {
my $ request = shift ;
my $ callback = shift ;
2008-01-25 15:07:53 +00:00
my $ node = $ request - > { '_xcat_clienthost' } - > [ 0 ] ;
2008-09-06 22:41:48 +00:00
unless ( ok_with_node ( $ node , 300 ) ) {
$ callback - > ( { error = > [ "Unable to prove root on your IP approves of this request" ] , errorcode = > [ 1 ] } ) ;
return ;
}
2012-05-22 02:54:17 +00:00
#my $sitetable = xCAT::Table->new('site');
2007-10-26 22:44:33 +00:00
my $ ipmitable = xCAT::Table - > new ( 'ipmi' ) ;
my $ tmphash ;
2012-11-29 20:30:22 +00:00
my $ username ;
2007-10-26 22:44:33 +00:00
my $ gennedpassword = 0 ;
my $ bmc ;
2012-11-29 20:30:22 +00:00
my $ password ;
$ tmphash = $ ipmitable - > getNodesAttribs ( [ $ node ] , [ 'bmc' , 'username' , 'bmcport' , 'password' , 'taggedvlan' ] ) ;
my $ authmap = xCAT::PasswordUtils:: getIPMIAuth ( noderange = > [ $ node ] , ipmihash = > $ tmphash ) ;
if ( $ ::XCATSITEVALS { genpasswords } eq "1" or $ ::XCATSITEVALS { genpasswords } =~ /y(es)?/i ) {
2012-01-18 19:43:02 +00:00
$ password = genpassword ( 10 ) . "1cA!" ;
2007-10-26 22:44:33 +00:00
$ gennedpassword = 1 ;
} else {
2012-11-29 20:30:22 +00:00
$ password = $ authmap - > { $ node } - > { password } ;
2007-10-26 22:44:33 +00:00
}
2009-03-02 19:26:21 +00:00
my $ bmcport ;
2012-11-29 20:30:22 +00:00
if ( defined $ tmphash - > { $ node } - > [ 0 ] - > { bmcport } ) {
$ bmcport = $ tmphash - > { $ node } - > [ 0 ] - > { bmcport } ;
2007-10-26 22:44:33 +00:00
}
2012-11-29 20:30:22 +00:00
if ( $ tmphash - > { $ node } - > [ 0 ] - > { bmc } ) {
$ bmc = $ tmphash - > { $ node } - > [ 0 ] - > { bmc } ;
2007-10-26 22:44:33 +00:00
}
2012-11-29 20:30:22 +00:00
$ username = $ authmap - > { $ node } - > { username } ;
2012-12-04 15:58:41 +00:00
my $ cliusername ;
if ( $ authmap - > { $ node } - > { cliusername } ) {
$ cliusername = $ authmap - > { $ node } - > { cliusername } ;
} else {
$ cliusername = $ username ;
}
my $ clipassword ;
if ( $ authmap - > { $ node } - > { clipassword } ) {
$ clipassword = $ authmap - > { $ node } - > { clipassword } ;
} else {
$ clipassword = $ password ;
}
2008-03-31 20:15:15 +00:00
unless ( defined $ bmc ) {
xCAT::MsgUtils - > message ( 'S' , "Unable to identify bmc for $node, refusing to give config data" ) ;
$ callback - > ( { error = > [ "Invalid table configuration for bmcconfig" ] , errorcode = > [ 1 ] } ) ;
return 1 ;
}
2013-04-26 14:06:49 +00:00
my $ bmcport_counter = 0 ;
2011-05-06 20:11:07 +00:00
foreach my $ sbmc ( split /,/ , $ bmc ) {
( my $ ip , my $ mask , my $ gw ) = net_parms ( $ sbmc ) ;
unless ( $ ip and $ mask and $ username and $ password ) {
2012-11-29 20:30:22 +00:00
xCAT::MsgUtils - > message ( 'S' , "Unable to determine IP, netmask, username, and/or pasword for $sbmc, ensure that host resolution is working. Best guess parameters would have been: IP: '$ip', netmask: '$mask', username: '$username', password: '$password'" , ) ;
2011-05-06 20:11:07 +00:00
$ callback - > ( { error = > [ "Invalid table configuration for bmcconfig" ] , errorcode = > [ 1 ] } ) ;
return 1 ;
}
2012-11-29 22:01:42 +00:00
if ( $ request - > { command } - > [ 0 ] eq 'remoteimmsetup' ) {
2012-12-04 15:58:41 +00:00
xCAT::IMMUtils:: setupIMM ( $ node , cliusername = > $ cliusername , clipassword = > $ clipassword , username = > $ username , password = > $ password , callback = > $ callback ) ;
2012-11-29 22:01:42 +00:00
return ;
}
2011-05-06 20:11:07 +00:00
my $ response = { bmcip = > $ ip , netmask = > $ mask , gateway = > $ gw , username = > $ username , password = > $ password } ;
if ( defined $ bmcport ) {
2013-04-26 14:06:49 +00:00
if ( $ bmcport =~ /,/ ) {
my @ sbmcport = ( split /,/ , $ bmcport ) ;
$ response - > { bmcport } = $ sbmcport [ $ bmcport_counter ] ;
} else {
$ response - > { bmcport } = $ bmcport ;
}
2011-05-06 20:11:07 +00:00
}
2012-11-29 20:30:22 +00:00
if ( defined $ tmphash - > { $ node } - > [ 0 ] - > { taggedvlan } ) {
2013-04-26 14:06:49 +00:00
if ( $ tmphash - > { $ node } - > [ 0 ] - > { taggedvlan } =~ /,/ ) {
my @ staggedvlan = ( split /,/ , $ tmphash - > { $ node } - > [ 0 ] - > { taggedvlan } ) ;
$ response - > { taggedvlan } = $ staggedvlan [ $ bmcport_counter ] ;
} else {
2012-11-29 20:30:22 +00:00
$ response - > { taggedvlan } = $ tmphash - > { $ node } - > [ 0 ] - > { taggedvlan } ;
2013-04-26 14:06:49 +00:00
}
2012-05-01 20:38:39 +00:00
}
2011-05-06 20:11:07 +00:00
$ callback - > ( $ response ) ;
2013-04-26 14:06:49 +00:00
$ bmcport_counter += 1 ;
2009-03-02 19:26:21 +00:00
}
2007-10-26 22:44:33 +00:00
if ( $ gennedpassword ) { # save generated password
$ ipmitable - > setNodeAttribs ( $ node , { password = > $ password } ) ;
}
return 1 ;
}
1 ;