83e79a0991
git-svn-id: https://svn.code.sf.net/p/xcat/code/xcat-core/trunk@12431 8638fb3e-16cb-4fca-ae20-7b5d299a9bcd
165 lines
5.4 KiB
Perl
165 lines
5.4 KiB
Perl
# IBM(c) 2007 EPL license http://www.eclipse.org/legal/epl-v10.html
|
|
package xCAT_plugin::bmcconfig;
|
|
use Data::Dumper;
|
|
use xCAT::Table;
|
|
use xCAT::MsgUtils;
|
|
use xCAT::Utils;
|
|
use IO::Select;
|
|
use Socket;
|
|
|
|
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;
|
|
if (inet_aton($ip)) {
|
|
$ip = inet_ntoa(inet_aton($ip));
|
|
} else {
|
|
xCAT::MsgUtils->message("S","Unable to resolve $ip");
|
|
return undef;
|
|
}
|
|
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;
|
|
if ($gw eq '<xcatmaster>') {
|
|
$gw=xCAT::Utils->my_ip_facing($ip);
|
|
}
|
|
if (($ipnum & $masknum)==$netnum) {
|
|
return ($ip,$mask,$gw);
|
|
}
|
|
}
|
|
xCAT::MsgUtils->message("S","xCAT BMC configuration error, no appropriate network for $ip found in networks, unable to determine netmask");
|
|
}
|
|
|
|
|
|
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;
|
|
}
|
|
|
|
sub process_request {
|
|
my $request = shift;
|
|
my $callback = shift;
|
|
my $node = $request->{'_xcat_clienthost'}->[0];
|
|
unless (ok_with_node($node,300)) {
|
|
$callback->({error=>["Unable to prove root on your IP approves of this request"],errorcode=>[1]});
|
|
return;
|
|
}
|
|
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';
|
|
if ($passtable) { ($tmphash)=$passtable->getAttribs({key=>'ipmi'},'username','password'); }
|
|
#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) {
|
|
$password = genpassword(10)."1cA!";
|
|
$gennedpassword=1;
|
|
$tmphash=$ipmitable->getNodeAttribs($node,['bmc','username','bmcport','taggedvlan']);
|
|
} else {
|
|
$tmphash=$ipmitable->getNodeAttribs($node,['bmc','username','bmcport','password','taggedvlan']);
|
|
if ($tmphash->{password}) {
|
|
$password = $tmphash->{password};
|
|
}
|
|
}
|
|
my $bmcport;
|
|
if (defined $tmphash->{bmcport}) {
|
|
$bmcport = $tmphash->{bmcport};
|
|
}
|
|
if ($tmphash->{bmc} ) {
|
|
$bmc=$tmphash->{bmc};
|
|
}
|
|
if ($tmphash->{username}) {
|
|
$username = $tmphash->{username};
|
|
}
|
|
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;
|
|
}
|
|
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;
|
|
}
|
|
if (defined $tmphash->{taggedvlan}) {
|
|
$response->{taggedvlan}=$tmphash->{taggedvlan};
|
|
}
|
|
$callback->($response);
|
|
}
|
|
if ($gennedpassword) { # save generated password
|
|
$ipmitable->setNodeAttribs($node,{password=>$password});
|
|
}
|
|
|
|
return 1;
|
|
}
|
|
|
|
|
|
|
|
1;
|
|
|