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 ;
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' ,
} ;
}
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 ;
$ net =~ /([0-9]+)\.([0-9]+)\.([0-9]+)\.([0-9]+)/ ;
my $ netnum = ( $ 1 << 24 ) + ( $ 2 << 16 ) + ( $ 3 << 8 ) + $ 4 ;
2011-05-06 20:11:07 +00:00
if ( $ gw eq '<xcatmaster>' ) {
$ gw = xCAT::Utils - > my_ip_facing ( $ ip ) ;
}
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 ;
}
2007-10-26 22:44:33 +00:00
my $ sitetable = xCAT::Table - > new ( 'site' ) ;
my $ ipmitable = xCAT::Table - > new ( 'ipmi' ) ;
my $ passtable = xCAT::Table - > new ( 'passwd' ) ;
my $ tmphash ;
my $ username = 'USERID' ;
my $ gennedpassword = 0 ;
my $ bmc ;
my $ password = 'PASSW0RD' ;
2007-10-31 03:39:56 +00:00
if ( $ passtable ) { ( $ tmphash ) = $ passtable - > getAttribs ( { key = > 'ipmi' } , 'username' , 'password' ) ; }
2007-10-26 22:44:33 +00:00
#Check for generics, can grab for both user and pass with a query
#since they cannot be in disparate records in passwd tab
if ( $ tmphash - > { username } ) {
$ username = $ tmphash - > { username } ;
}
if ( $ tmphash - > { password } ) { #It came for free with the last query
$ password = $ tmphash - > { password } ;
}
$ tmphash = ( $ sitetable - > getAttribs ( { key = > 'genpasswords' } , 'value' ) ) [ 0 ] ;
if ( $ tmphash - > { value } eq "1" or $ tmphash - > { value } =~ /y(es)?/i ) {
2010-09-13 18:54:26 +00:00
$ password = genpassword ( 8 ) . "1c" ;
2007-10-26 22:44:33 +00:00
$ gennedpassword = 1 ;
2010-09-13 18:54:26 +00:00
$ tmphash = $ ipmitable - > getNodeAttribs ( $ node , [ 'bmc' , 'username' , 'bmcport' ] ) ;
2007-10-26 22:44:33 +00:00
} else {
2009-03-02 19:26:21 +00:00
$ tmphash = $ ipmitable - > getNodeAttribs ( $ node , [ 'bmc' , 'username' , 'bmcport' , 'password' ] ) ;
2007-10-26 22:44:33 +00:00
if ( $ tmphash - > { password } ) {
$ password = $ tmphash - > { password } ;
}
}
2009-03-02 19:26:21 +00:00
my $ bmcport ;
if ( defined $ tmphash - > { bmcport } ) {
$ bmcport = $ tmphash - > { bmcport } ;
}
2007-10-26 22:44:33 +00:00
if ( $ tmphash - > { bmc } ) {
$ bmc = $ tmphash - > { bmc } ;
}
if ( $ tmphash - > { username } ) {
$ username = $ tmphash - > { username } ;
}
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 ;
}
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 ) {
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: '$netmask', username: '$username', password: '$password'" , ) ;
$ callback - > ( { error = > [ "Invalid table configuration for bmcconfig" ] , errorcode = > [ 1 ] } ) ;
return 1 ;
}
my $ response = { bmcip = > $ ip , netmask = > $ mask , gateway = > $ gw , username = > $ username , password = > $ password } ;
if ( defined $ bmcport ) {
$ response - > { bmcport } = $ bmcport ;
}
$ callback - > ( $ response ) ;
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 ;