-Change '!xcat' hash members to '_xcat', which can survive XML-ization
-Have the xcatd service script source a /etc/sysconfig/xcat if available (to allow setting of XCATCFG) -Modify xcatd to be able to relay requests to service nodes if the plugin can provide a map, using it's server key and certificate as client credentials -Provide a more helpful message for SSL connection issue -Modify Client.pm to accept custome key/cert/ca files to facilitate the aforementioned request relay. git-svn-id: https://svn.code.sf.net/p/xcat/code/xcat-core/trunk@324 8638fb3e-16cb-4fca-ae20-7b5d299a9bcd
This commit is contained in:
		@@ -66,6 +66,12 @@ my %resps;
 | 
			
		||||
sub submit_request {
 | 
			
		||||
  my $request = shift;
 | 
			
		||||
  my $callback = shift;
 | 
			
		||||
  my $keyfile = shift;
 | 
			
		||||
  my $certfile = shift;
 | 
			
		||||
  my $cafile = shift;
 | 
			
		||||
  unless ($keyfile) { $keyfile = $ENV{HOME}."/.xcat/client-key.pem"; }
 | 
			
		||||
  unless ($certfile) { $certfile = $ENV{HOME}."/.xcat/client-cert.pem"; }
 | 
			
		||||
  unless ($cafile) { $cafile  = $ENV{HOME}."/.xcat/ca.pem"; }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
# If XCATBYPASS is set, invoke the plugin process_request method directly
 | 
			
		||||
@@ -107,12 +113,12 @@ sub submit_request {
 | 
			
		||||
  }
 | 
			
		||||
  my $client = IO::Socket::SSL->new(
 | 
			
		||||
    PeerAddr => $xcathost,
 | 
			
		||||
    SSL_key_file => $ENV{HOME}."/.xcat/client-key.pem",
 | 
			
		||||
    SSL_cert_file => $ENV{HOME}."/.xcat/client-cert.pem",
 | 
			
		||||
    SSL_ca_file => $ENV{HOME}."/.xcat/ca.pem",
 | 
			
		||||
    SSL_key_file => $keyfile,
 | 
			
		||||
    SSL_cert_file => $certfile,
 | 
			
		||||
    SSL_ca_file => $cafile,
 | 
			
		||||
    SSL_use_cert => 1,
 | 
			
		||||
    );
 | 
			
		||||
  die "Connection failure: $@\n" unless ($client);
 | 
			
		||||
  die "Connection failure: $@ (SSL Timeout may mean the credentials in ~/.xcat are incorrect)\n" unless ($client);
 | 
			
		||||
  my $msg=XMLout($request,RootName=>xcatrequest,NoAttr=>1,KeyAttr=>[]);
 | 
			
		||||
  print $client $msg;
 | 
			
		||||
  my $response;
 | 
			
		||||
 
 | 
			
		||||
@@ -11,6 +11,9 @@
 | 
			
		||||
# Short-Description: xCATd
 | 
			
		||||
# Description: xCAT management service
 | 
			
		||||
### END INIT INFO
 | 
			
		||||
if [ -r /etc/sysconfig/xcat ]; then
 | 
			
		||||
	. /etc/sysconfig/xcat
 | 
			
		||||
fi
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
MStatus()
 | 
			
		||||
 
 | 
			
		||||
@@ -875,7 +875,7 @@ sub process_request {
 | 
			
		||||
    $invreq{arg} = ['mac'];
 | 
			
		||||
    $invreq{command} = ['rinv'];
 | 
			
		||||
    my $mac;
 | 
			
		||||
    my $ip = $request->{'!xcat_clientip'};
 | 
			
		||||
    my $ip = $request->{'_xcat_clientip'};
 | 
			
		||||
    my $arptable = `/sbin/arp -n`;
 | 
			
		||||
    my @arpents = split /\n/,$arptable;
 | 
			
		||||
    foreach  (@arpents) {
 | 
			
		||||
 
 | 
			
		||||
@@ -51,7 +51,7 @@ sub net_parms {
 | 
			
		||||
sub process_request  {
 | 
			
		||||
  my $request = shift;
 | 
			
		||||
  my $callback = shift;
 | 
			
		||||
  my $node = $request->{'!xcat_clienthost'}->[0];
 | 
			
		||||
  my $node = $request->{'_xcat_clienthost'}->[0];
 | 
			
		||||
  my $sitetable = xCAT::Table->new('site');
 | 
			
		||||
  my $ipmitable = xCAT::Table->new('ipmi');
 | 
			
		||||
  my $passtable = xCAT::Table->new('passwd');
 | 
			
		||||
 
 | 
			
		||||
@@ -129,11 +129,11 @@ sub nextdestiny {
 | 
			
		||||
    #TODO: service third party getdestiny..
 | 
			
		||||
  } else { #client asking to move along its own chain
 | 
			
		||||
    #TODO: SECURITY with this, any one on a node could advance the chain, for node, need to think of some strategy to deal with...
 | 
			
		||||
    unless ($request->{'!xcat_clienthost'}->[0]) {
 | 
			
		||||
    unless ($request->{'_xcat_clienthost'}->[0]) {
 | 
			
		||||
      #ERROR? malformed request
 | 
			
		||||
      return; #nothing to do here...
 | 
			
		||||
    }
 | 
			
		||||
    my $node = $request->{'!xcat_clienthost'}->[0];
 | 
			
		||||
    my $node = $request->{'_xcat_clienthost'}->[0];
 | 
			
		||||
    ($node) = noderange($node);
 | 
			
		||||
    unless ($node) {
 | 
			
		||||
      #not a node, don't trust it
 | 
			
		||||
@@ -186,11 +186,11 @@ sub getdestiny {
 | 
			
		||||
      @nodes = ($request->{node});
 | 
			
		||||
    }
 | 
			
		||||
  } else { # a client asking for it's own destiny.
 | 
			
		||||
    unless ($request->{'!xcat_clienthost'}->[0]) {
 | 
			
		||||
    unless ($request->{'_xcat_clienthost'}->[0]) {
 | 
			
		||||
      $callback->({destiny=>[ 'discover' ]});
 | 
			
		||||
      return;
 | 
			
		||||
    }
 | 
			
		||||
    my ($node) = noderange($request->{'!xcat_clienthost'}->[0]);
 | 
			
		||||
    my ($node) = noderange($request->{'_xcat_clienthost'}->[0]);
 | 
			
		||||
    unless ($node) { # it had a valid hostname, but isn't a node
 | 
			
		||||
      $callback->({destiny=>[ 'discover' ]}); 
 | 
			
		||||
      return;
 | 
			
		||||
 
 | 
			
		||||
@@ -86,7 +86,7 @@ sub process_request {
 | 
			
		||||
  my $callback = shift;
 | 
			
		||||
  my $doreq = shift;
 | 
			
		||||
  my $node = $request->{node}->[0];
 | 
			
		||||
  my $ip = $request->{'!xcat_clientip'};
 | 
			
		||||
  my $ip = $request->{'_xcat_clientip'};
 | 
			
		||||
  openlog("xCAT node discovery",'','local0');
 | 
			
		||||
  #First, fill in tables with data fields..
 | 
			
		||||
  if (defined($request->{mtm}) or defined($request->{serial})) {
 | 
			
		||||
 
 | 
			
		||||
@@ -18,7 +18,7 @@ sub process_request {
 | 
			
		||||
 my $req = shift;
 | 
			
		||||
 my $cb = shift;
 | 
			
		||||
 my $doreq = shift;
 | 
			
		||||
 my $ip = $req->{'!xcat_clientip'};
 | 
			
		||||
 my $ip = $req->{'_xcat_clientip'};
 | 
			
		||||
 my $mac = '';
 | 
			
		||||
 my $arptable = `/sbin/arp -n`;
 | 
			
		||||
 my @arpents = split /\n/,$arptable;
 | 
			
		||||
 
 | 
			
		||||
@@ -7,6 +7,7 @@ BEGIN
 | 
			
		||||
use lib "$::XCATROOT/lib/perl";
 | 
			
		||||
use xCAT::Utils;
 | 
			
		||||
use File::Path;
 | 
			
		||||
use xCAT::Client submit_request;
 | 
			
		||||
 | 
			
		||||
use IO::Socket::SSL;
 | 
			
		||||
if (xCAT::Utils->isLinux()) {
 | 
			
		||||
@@ -255,9 +256,9 @@ if (xCAT::Utils->isLinux()) {
 | 
			
		||||
        $peerhost=gethostbyaddr($client,AF_INET)."\n";
 | 
			
		||||
        my $req = eval { XMLin($data, SuppressEmpty=>undef,ForceArray=>1) };
 | 
			
		||||
        if ($req and $req->{command} and ($req->{command}->[0] eq "findme")) {
 | 
			
		||||
          $req->{'!xcat_clienthost'}=gethostbyaddr($client,AF_INET)."\n";
 | 
			
		||||
          $req->{'!xcat_clientip'}=inet_ntoa($client);
 | 
			
		||||
          $req->{'!xcat_clientport'}=$sport;
 | 
			
		||||
          $req->{'_xcat_clienthost'}=gethostbyaddr($client,AF_INET)."\n";
 | 
			
		||||
          $req->{'_xcat_clientip'}=inet_ntoa($client);
 | 
			
		||||
          $req->{'_xcat_clientport'}=$sport;
 | 
			
		||||
          if (defined($cmd_handlers{"findme"})) {
 | 
			
		||||
            $req->{cacheonly}->[0] = 1;
 | 
			
		||||
            plugin_command($req,undef,\&convey_response);
 | 
			
		||||
@@ -566,10 +567,60 @@ sub dispatch_request {
 | 
			
		||||
  my $req = shift;
 | 
			
		||||
  my $callback = shift;
 | 
			
		||||
  my $modname = shift;
 | 
			
		||||
  my $reqs = [];
 | 
			
		||||
  no strict  "refs";
 | 
			
		||||
  ${"xCAT_plugin::".$modname."::"}{process_request}->($req,$callback,\&do_request);
 | 
			
		||||
 | 
			
		||||
  #Hierarchy support.  Originally, the default scope for noderange commands was
 | 
			
		||||
  #going to be the servicenode associated unless overriden.
 | 
			
		||||
  #However, assume for example that you have blades and a blade is the service node
 | 
			
		||||
  #rpower being executed by the servicenode for one of its subnodes would have to
 | 
			
		||||
  #reach it's own management module.  This has the potential to be non-trivial for some quite possible network configurations.
 | 
			
		||||
  #Since plugins may commonly experience this, a preprocess_request implementation
 | 
			
		||||
  #will for now be required for a command to be scaled through service nodes
 | 
			
		||||
  #If the plugin offers a preprocess method, use it to set the request array
 | 
			
		||||
  if (defined(${"xCAT_plugin::".$modname."::"}{preprocess_request})) {
 | 
			
		||||
    $reqs = ${"xCAT_plugin::".$modname."::"}{preprocess_request}->($req);
 | 
			
		||||
  } else { #otherwise, pass it in without hierarchy support
 | 
			
		||||
    $reqs = [$req];
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  #TODO: calls to dispatch must be parallelized
 | 
			
		||||
  foreach (@{$reqs}) {
 | 
			
		||||
     if ($_->{'_xcatdest'} and thishostisnot($_->{'_xcatdest'})) {
 | 
			
		||||
	my $oldenv = $ENV{XCATHOST};
 | 
			
		||||
        $ENV{XCATHOST} =  ( $_->{'_xcatdest'} =~ /:/ ? $_->{'_xcatdest'} : $_->{'_xcatdest'}.":3001" );
 | 
			
		||||
        eval {
 | 
			
		||||
        undef $_->{'_xcatdest'};
 | 
			
		||||
        xCAT::Client::submit_request($_,$callback,$xcatdir."/cert/server-key.pem",$xcatdir."/cert/server-cert.pem",$xcatdir."/cert/ca.pem"); 
 | 
			
		||||
        };
 | 
			
		||||
        if ($@) {
 | 
			
		||||
	   $callback->({error=>["Error dispatching command to ".$ENV{XCATHOST}.""],errorcode=>[1]}); 
 | 
			
		||||
	   syslog("local4|err","Error dispatching request: ".$@);
 | 
			
		||||
	}
 | 
			
		||||
        $ENV{XCATHOST} = $oldenv;
 | 
			
		||||
     } else {
 | 
			
		||||
        ${"xCAT_plugin::".$modname."::"}{process_request}->($_,$callback,\&do_request);
 | 
			
		||||
     }
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
sub thishostisnot {
 | 
			
		||||
  my $comparison = shift;
 | 
			
		||||
  my @ips = split /\n/,`/sbin/ip addr`;
 | 
			
		||||
  my $comp=inet_aton($comparison);
 | 
			
		||||
  foreach (@ips) { 
 | 
			
		||||
    if (/^\s*inet/) {
 | 
			
		||||
	my @ents = split(/\s+/);
 | 
			
		||||
	my $ip=$ents[2];
 | 
			
		||||
	$ip =~ s/\/.*//;
 | 
			
		||||
	if (inet_aton($ip) eq $comp) { 
 | 
			
		||||
	  return 0;
 | 
			
		||||
	}
 | 
			
		||||
	#print Dumper(inet_aton($ip));
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
  return 1;
 | 
			
		||||
}
 | 
			
		||||
sub do_request {
 | 
			
		||||
  my $req = shift;
 | 
			
		||||
  my $second = shift;
 | 
			
		||||
@@ -627,7 +678,6 @@ sub convey_response {
 | 
			
		||||
  }
 | 
			
		||||
  print $parent_fd XMLout($resp,KeyAttr=>[], NoAttr=>1,RootName=>'xcatresponse');
 | 
			
		||||
  <$parent_fd>; #Block until parent acks data
 | 
			
		||||
  #print "woo";
 | 
			
		||||
#  KeyAttr => [], NoAttr => 1)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -672,9 +722,9 @@ sub service_connection {
 | 
			
		||||
        #printf $request."\n";
 | 
			
		||||
        $request="";
 | 
			
		||||
        if (validate($peername,$peerhost,$req)) {
 | 
			
		||||
          $req->{'!xcat_authname'} = [$peername];
 | 
			
		||||
          $req->{'!xcat_clienthost'} = [$peerhost];
 | 
			
		||||
          $req->{'!xcat_clientport'}= [$peerport];
 | 
			
		||||
          $req->{'_xcat_authname'} = [$peername];
 | 
			
		||||
          $req->{'_xcat_clienthost'} = [$peerhost];
 | 
			
		||||
          $req->{'_xcat_clientport'}= [$peerport];
 | 
			
		||||
          $$progname="xCATd SSL: ".$req->{command}->[0]." for ".($peername ? $peername ."@".$peerhost : $peerhost);
 | 
			
		||||
          if ($cmd_handlers{$req->{command}->[0]}) {
 | 
			
		||||
            return plugin_command($req,$sock,\&convey_response);
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user