-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:
jbjohnso 2008-01-25 15:07:53 +00:00
parent 7f2a3b8ea4
commit 1812d2e372
8 changed files with 79 additions and 20 deletions

View File

@ -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;

View File

@ -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()

View File

@ -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) {

View File

@ -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');

View File

@ -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;

View File

@ -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})) {

View File

@ -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;

View File

@ -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);