mirror of
				https://github.com/xcat2/xcat-core.git
				synced 2025-11-04 05:12:30 +00:00 
			
		
		
		
	git-svn-id: https://svn.code.sf.net/p/xcat/code/xcat-core/branches/2.8@16073 8638fb3e-16cb-4fca-ae20-7b5d299a9bcd
		
			
				
	
	
		
			182 lines
		
	
	
		
			6.0 KiB
		
	
	
	
		
			Perl
		
	
	
	
	
	
			
		
		
	
	
			182 lines
		
	
	
		
			6.0 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 xCAT::PasswordUtils;
 | 
						|
use xCAT::IMMUtils;
 | 
						|
use xCAT::TableUtils;
 | 
						|
use IO::Select;
 | 
						|
use Socket;
 | 
						|
 | 
						|
sub handled_commands {
 | 
						|
    return {
 | 
						|
          getbmcconfig => 'bmcconfig',
 | 
						|
	  remoteimmsetup => '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]+)/ or next; #next if ipv6, TODO: IPv6 support
 | 
						|
    my $netnum = ($1<<24)+($2<<16)+($3<<8)+$4;
 | 
						|
    if ($gw eq '<xcatmaster>') {
 | 
						|
	$gw=xCAT::NetworkUtils->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 $tmphash;
 | 
						|
  my $username;
 | 
						|
  my $gennedpassword=0;
 | 
						|
  my $bmc;
 | 
						|
  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) {
 | 
						|
    $password = genpassword(10)."1cA!";
 | 
						|
    $gennedpassword=1;
 | 
						|
  } else {
 | 
						|
    $password = $authmap->{$node}->{password};
 | 
						|
  }
 | 
						|
  my $bmcport;
 | 
						|
  if (defined $tmphash->{$node}->[0]->{bmcport}) {
 | 
						|
      $bmcport = $tmphash->{$node}->[0]->{bmcport};
 | 
						|
  }
 | 
						|
  if ($tmphash->{$node}->[0]->{bmc} ) {
 | 
						|
    $bmc=$tmphash->{$node}->[0]->{bmc};
 | 
						|
  }
 | 
						|
  $username = $authmap->{$node}->{username};
 | 
						|
  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;
 | 
						|
  }
 | 
						|
  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;
 | 
						|
  }
 | 
						|
  my $bmcport_counter=0;
 | 
						|
  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: '$mask', username: '$username', password: '$password'",  );
 | 
						|
	     $callback->({error=>["Invalid table configuration for bmcconfig"],errorcode=>[1]});
 | 
						|
	     return 1;
 | 
						|
	  }
 | 
						|
	  if ($request->{command}->[0] eq 'remoteimmsetup') {
 | 
						|
	     xCAT::IMMUtils::setupIMM($node,cliusername=>$cliusername,clipassword=>$clipassword,username=>$username,password=>$password,callback=>$callback);
 | 
						|
             return;
 | 
						|
	  }
 | 
						|
	  my $response={bmcip=>$ip,netmask=>$mask,gateway=>$gw,username=>$username,password=>$password};
 | 
						|
	  if (defined $bmcport) {
 | 
						|
	      if ($bmcport =~ /,/) {
 | 
						|
	      	my @sbmcport = (split /,/,$bmcport);
 | 
						|
		$response->{bmcport}=$sbmcport[$bmcport_counter];
 | 
						|
	      } else {
 | 
						|
	      	$response->{bmcport}=$bmcport;
 | 
						|
	      }
 | 
						|
	  }
 | 
						|
	  if (defined $tmphash->{$node}->[0]->{taggedvlan}) {
 | 
						|
	      if ($tmphash->{$node}->[0]->{taggedvlan} =~ /,/) {
 | 
						|
	      		my @staggedvlan = (split /,/,$tmphash->{$node}->[0]->{taggedvlan});
 | 
						|
			$response->{taggedvlan}=$staggedvlan[$bmcport_counter];
 | 
						|
	       } else {
 | 
						|
	      $response->{taggedvlan}=$tmphash->{$node}->[0]->{taggedvlan};
 | 
						|
	      }
 | 
						|
	  }
 | 
						|
  	$callback->($response);
 | 
						|
	$bmcport_counter += 1;
 | 
						|
  }
 | 
						|
  if ($gennedpassword) { # save generated password
 | 
						|
    $ipmitable->setNodeAttribs($node,{password=>$password});
 | 
						|
  }
 | 
						|
 | 
						|
  return 1;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
 | 
						|
1;
 | 
						|
 |