updated various bypass mode subroutines to be similar to xcatd again

git-svn-id: https://svn.code.sf.net/p/xcat/code/xcat-core/trunk@4652 8638fb3e-16cb-4fca-ae20-7b5d299a9bcd
This commit is contained in:
mellor 2009-11-23 16:16:33 +00:00
parent af1cd4333f
commit c6b79c7c15

View File

@ -189,7 +189,7 @@ sub submit_request {
# will load all plugin perl modules and build a list of supported
# commands
#
# NOTE: This is copied from xcatd (last merge 5/21/08).
# NOTE: This is copied from xcatd (last merge 11/23/09).
# TODO: Will eventually move to using common source....
###################################
sub scan_plugins {
@ -197,7 +197,10 @@ sub scan_plugins {
foreach (@plugins) {
/.*\/([^\/]*).pm$/;
my $modname = $1;
unless (eval { require "$_" }) { print "Error loading module $_ ...skipping\n"; next;}
unless (eval { require "$_" }) {
print "Error loading module $_ ...skipping\n";
next;
}
no strict 'refs';
my $cmd_adds=${"xCAT_plugin::".$modname."::"}{handled_commands}->();
foreach (keys %$cmd_adds) {
@ -222,6 +225,51 @@ sub scan_plugins {
}
}
}
sub scan_plugins {
my @plugins=glob($plugins_dir."/*.pm");
foreach (@plugins) {
/.*\/([^\/]*).pm$/;
my $modname = $1;
unless ( eval { require "$_" }) {
# xCAT::MsgUtils->message("S","Error loading module ".$_." ...skipping");
print "Error loading module $_ ...skipping\n";
next;
}
no strict 'refs';
my $cmd_adds=${"xCAT_plugin::".$modname."::"}{handled_commands}->();
foreach (keys %$cmd_adds) {
my $value = $_;
if (defined($cmd_handlers{$_})) {
my $add=1;
#This next bit of code iterates through the handlers.
#If the value doesn't contain an equal, and has an equivalent entry added by
# another plugin already, don't add (otherwise would hit the DB multiple times)
#referring to having redundant nodehm:mgt handlers registered, for example
# a better idea, restructure the cmd_handlers as a multi-level hash
# prove out this idea real quick before doing that
foreach (@{$cmd_handlers{$_}}) {
if (($_->[1] eq $cmd_adds->{$value}) and (($cmd_adds->{$value} !~ /=/) or ($_->[0] eq $modname))) {
$add = 0;
}
}
if ($add) { push @{$cmd_handlers{$_}},[$modname,$cmd_adds->{$_}]; }
#die "Conflicting handler information from $modname";
} else {
$cmd_handlers{$_} = [ [$modname,$cmd_adds->{$_}] ];
}
}
}
foreach (@plugins) {
no strict 'refs';
/.*\/([^\/]*).pm$/;
my $modname = $1;
unless (defined(${"xCAT_plugin::".$modname."::"}{init_plugin})) {
next;
}
${"xCAT_plugin::".$modname."::"}{init_plugin}->(\&do_request);
}
}
@ -229,7 +277,7 @@ sub scan_plugins {
# plugin_command
# will invoke the correct plugin
#
# NOTE: This is copied from xcatd (last merge 5/21/08).
# NOTE: This is copied from xcatd (last merge 11/23/09).
# TODO: Will eventually move to using common source....
###################################
sub plugin_command {
@ -237,6 +285,7 @@ sub plugin_command {
my $sock = shift;
my $callback = shift;
my %handler_hash;
my $usesiteglobal = 0;
# We require these only in bypass mode to reduce start up time for the normal case
#use lib "$::XCATROOT/lib/perl";
@ -274,10 +323,29 @@ sub plugin_command {
my $useunhandled=0;
if (defined($cmd_handlers{$req->{command}->[0]})) {
my $hdlspec;
my @globalhandlers=();
my $useglobals=1; #If it stays 1, then use globals normally, if 0, use only for 'unhandled_nodes, if -1, don't do at all
foreach (@{$cmd_handlers{$req->{command}->[0]}}) {
$hdlspec =$_->[1];
my $ownmod = $_->[0];
if ($hdlspec =~ /:/) { #Specificed a table lookup path for plugin name
if ($hdlspec =~ /^site:/) { #A site entry specifies a plugin
my $sitekey = $hdlspec;
$sitekey =~ s/^site://;
$sitetab = xCAT::Table->new('site');
my $sent = $sitetab->getAttribs({key=>$sitekey},['value']);
if ($sent and $sent->{value}) { #A site style plugin specification is just like
#a static global, it grabs all nodes rather than some
$useglobals = -1; #If they tried to specify anything, don't use the default global handlers at all
unless (@nodes) {
$handler_hash{$sent->{value}} = 1;
$usesiteglobal = 1;
}
foreach (@nodes) { #Specified a specific plugin, not a table lookup
$handler_hash{$sent->{value}}->{$_} = 1;
}
}
} elsif ($hdlspec =~ /:/) { #Specificed a table lookup path for plugin name
$useglobals = 0; #Only contemplate nodes that aren't caught through searching below in the global handler
$useunhandled=1;
my $table;
my $cols;
@ -301,12 +369,19 @@ sub plugin_command {
}
}
unless (@nodes) { #register the plugin in the event of usage
$handler_hash{$ownmod} = 1;
$useglobals = 1;
}
my $hdlrcache;
if ($hdlrtable) {
$hdlrcache = $hdlrtable->getNodesAttribs(\@nodes,\@columns);
}
foreach $node (@nodes) {
my $attribs = $hdlrtable->getNodeAttribs($node,\@columns);
unless (defined($attribs)) { next; } #TODO: This really ought to craft an unsupported response for this request
unless ($hdlrcache) { next; }
my $attribs = $hdlrcache->{$node}->[0]; #$hdlrtable->getNodeAttribs($node,\@columns);
unless (defined($attribs)) { next; }
foreach (@columns) {
my $col=$_;
if (defined($attribs->{$col})) {
@ -326,16 +401,37 @@ sub plugin_command {
}
$hdlrtable->close;
} else {
unless (@nodes) {
$handler_hash{$hdlspec} = 1;
}
foreach (@nodes) { #Specified a specific plugin, not a table lookup
$handler_hash{$hdlspec}->{$_} = 1;
}
push @globalhandlers,$hdlspec;
}
}
if ($useglobals == 1) { #Behavior when globals have not been overriden
my $hdlspec;
foreach $hdlspec (@globalhandlers) {
unless (@nodes) {
$handler_hash{$hdlspec} = 1;
}
foreach (@nodes) { #Specified a specific plugin, not a table lookup
$handler_hash{$hdlspec}->{$_} = 1;
}
}
} elsif ($useglobals == 0) {
unless (@nodes or $usesiteglobal) { #if something like 'makedhcp -n',
foreach (keys %handler_hash) {
if ($handler_hash{$_} == 1) {
delete ($handler_hash{$_})
}
}
}
foreach $hdlspec (@globalhandlers) {
unless (@nodes or $usesiteglobal) {
$handler_hash{$hdlspec} = 1;
}
foreach (keys %unhandled_nodes) { #Specified a specific plugin, not a table lookup
$handler_hash{$hdlspec}->{$_} = 1;
}
}
} #Otherwise, global handler is implicitly disabled
} else {
print "$req->{command}->[0] xCAT command not found \n";
return 1; #TODO: error back that request has no known plugin for it
}
if ($useunhandled) {
@ -352,7 +448,9 @@ sub plugin_command {
# if ($sock) {
# print $sock XMLout({node=>[{name=>[$_],data=>["Unable to identify plugin for this command, check relevant tables: $queuelist"],errorcode=>[1]}]},NoAttr=>1,RootName=>'xcatresponse');
# } else {
$callback->({node=>[{name=>[$_],data=>['Unable to identify plugin for this command, check relevant tables'],errorcode=>[1]}]});
my $tabdesc = $queuelist;
$tabdesc =~ s/=.*$//;
$callback->({node=>[{name=>[$_],error=>['Unable to identify plugin for this command, check relevant tables: '.$tabdesc],errorcode=>[1]}]});
# }
}
}
@ -367,6 +465,7 @@ sub plugin_command {
# }
foreach (keys %handler_hash) {
my $modname = $_;
# my $shouldbealivepid=$$;
if (-r $plugins_dir."/".$modname.".pm") {
require $plugins_dir."/".$modname.".pm";
# $plugin_numchildren++;
@ -384,7 +483,9 @@ sub plugin_command {
# }
# unless (defined $child) { die "Fork failed"; }
# if ($child == 0) {
# $parent_fd = $parfd;
# if ($parfd) { #If xCAT is doing multiple requests in same communication PID, things would get unfortunate otherwise
# $parent_fd = $parfd;
# }
my $oldprogname=$$progname;
$$progname=$oldprogname.": $modname instance";
# if ($sock) { close $pfd; }
@ -393,10 +494,11 @@ sub plugin_command {
$req->{node}=\@nodes;
}
no strict "refs";
# eval { #REMOVEEVALFORDEBUG
# if ($dispatch_requests) {
dispatch_request($req,$callback,$modname);
# } else {
# undef $SIG{CHLD};
# $SIG{CHLD}='DEFAULT';
# ${"xCAT_plugin::".$modname."::"}{process_request}->($req,$callback,\&do_request);
# }
$$progname=$oldprogname;
@ -404,6 +506,23 @@ sub plugin_command {
# close($parent_fd);
# xexit(0);
# }
# }; #REMOVEEVALFORDEBUG
# if ($sock or $shouldbealivepid != $$) { #We shouldn't still be alive, try to send as much detail to parent as possible as to why
# my $error= "$modname plugin bug, pid $$, process description: '$$progname'";
# if ($@) {
# $error .= " with error '$@'";
# } else { #Sys::Virt and perhaps Net::SNMP sometimes crashes in a way $@ won't catch..
# $error .= " with missing eval error, probably due to special manipulation of $@ or strange circumstances in an XS library, remove evals in xcatd marked 'REMOVEEVALFORDEBUG and run xcatd -f for more info";
# }
# if (scalar (@nodes)) { #Don't know which of the nodes, so one error message warning about the possibliity..
# $error .= " while trying to fulfill request for the following nodes: ".join(",",@nodes);
# }
# xCAT::MsgUtils->message("S","xcatd: $error");
# $callback->({error=>[$error],errorcode=>[1]});
# xexit(0); #Die like we should have done
# } elsif ($@) { #We are still alive, should be alive, but yet we have an error. This means we are in the case of 'do_request' or something similar. Forward up the death since our communication channel is intact..
# die $@;
# }
# } else {
# $plugin_children{$child}=1;
# close $parfd;
@ -430,7 +549,13 @@ sub plugin_command {
# if ($req->{transid}) {
# $done{transid}=$req->{transid}->[0];
# }
# if ($sock) { print $sock XMLout(\%done,RootName => 'xcatresponse',NoAttr=>1); }
# if ($sock) {
# my $clientpresence = new IO::Select; #The client may have gone away without confirmation, don't PIPE over this trivial thing
# $clientpresence->add($sock);
# if ($clientpresence->can_write(5)) {
# print $sock XMLout(\%done,RootName => 'xcatresponse',NoAttr=>1);
# }
# }
}
@ -440,7 +565,7 @@ sub plugin_command {
# dispatch_request
# dispatch the requested command
#
# NOTE: This is copied from xcatd (last merge 5/21/08).
# NOTE: This is copied from xcatd (last merge 11/23/09).
# All we really need from this subroutine is to call preprocess_request
# and to only run the command for nodes handled by the local server
# Will eventually move to using common source....
@ -464,7 +589,7 @@ sub dispatch_request {
#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})) {
undef $SIG{CHLD};
$SIG{CHLD}='DEFAULT';
$reqs = ${"xCAT_plugin::".$modname."::"}{preprocess_request}->($req,$dispatch_cb,\&do_request);
} else { #otherwise, pass it in without hierarchy support
$reqs = [$req];
@ -472,6 +597,11 @@ sub dispatch_request {
# $dispatch_children=0;
# $SIG{CHLD} = \&dispatch_reaper; #sub {my $cpid; while (($cpid =waitpid(-1, WNOHANG)) > 0) { if ($dispatched_children{$cpid}) { delete $dispatched_children{$cpid}; $dispatch_children--; } } };
my $onlyone=0;
if (defined $reqs and (scalar(@{$reqs}) == 1)) {
$onlyone=1;
}
foreach (@{$reqs}) {
# my $pfd;
# my $parfd; #use a private variable so it won't trounce itself recursively
@ -481,6 +611,17 @@ sub dispatch_request {
if ($_->{node}) {
$_->{noderange}->[0]=join(',',@{$_->{node}});
}
#----- end added to Client.pm -----#
if (ref $_->{'_xcatdest'} and (ref $_->{'_xcatdest'}) eq 'ARRAY') {
_->{'_xcatdest'} = $_->{'_xcatdest'}->[0];
}
if ($onlyone and not ($_->{'_xcatdest'} and xCAT::Utils->thishostisnot($_->{'_xcatdest'}))) {
$SIG{CHLD}='DEFAULT';
${"xCAT_plugin::".$modname."::"}{process_request}->($_,$dispatch_cb,\&do_request);
return;
}
# socketpair($pfd, $parfd,AF_UNIX,SOCK_STREAM,PF_UNSPEC) or die "socketpair: $!";
# $parfd->autoflush(1);
# $pfd->autoflush(1);
@ -496,25 +637,73 @@ sub dispatch_request {
# }
# undef $SIG{CHLD};
# $dispatch_parentfd = $parfd;
if ($_->{'_xcatdest'} and xCAT::Utils->thishostisnot($_->{'_xcatdest'})) {
my @prexcatdests=();
my @xcatdests=();
if (ref($_->{'_xcatdest'}) eq 'ARRAY') { #If array, consider it an 'anycast' operation, broadcast done through dupe
#requests, or an alternative join '&' maybe?
@prexcatdests=@{$_->{'_xcatdest'}};
} else {
@prexcatdests=($_->{'_xcatdest'});
}
foreach (@prexcatdests) {
if ($_ and /,/) {
push @xcatdests,split /,/,$_;
} else {
push @xcatdests,$_;
}
}
my $xcatdest;
my $numdests=scalar(@xcatdests);
my $request_satisfied=0;
foreach $xcatdest (@xcatdests) {
my $dlock;
if ($xcatdest and xCAT::Utils->thishostisnot($xcatdest)) {
#----- added to Client.pm -----#
$dispatch_cb->({warning=>['XCATBYPASS is set, skipping hierarchy call to '.$_->{'_xcatdest'}.'']});
#----- end added to Client.pm -----#
# $ENV{XCATHOST} = ( $_->{'_xcatdest'} =~ /:/ ? $_->{'_xcatdest'} : $_->{'_xcatdest'}.":3001" );
# $$progname.=": connection to ".$ENV{XCATHOST};
# eval {
# undef $_->{'_xcatdest'};
# xCAT::Client::submit_request($_,\&dispatch_callback,$xcatdir."/cert/server-cred.pem",$xcatdir."/cert/server-cred.pem",$xcatdir."/cert/ca.pem");
# };
# if ($@) {
# dispatch_callback({error=>["Error dispatching command to ".$ENV{XCATHOST}.""],errorcode=>[1]});
# syslog("local4|err","Error dispatching request: ".$@);
# }
} else {
$$progname.=": locally executing";
undef $SIG{CHLD};
${"xCAT_plugin::".$modname."::"}{process_request}->($_,$dispatch_cb,\&do_request);
# #mkpath("/var/lock/xcat/"); #For now, limit intra-xCAT requests to one at a time, to mitigate DB handle usage
# #open($dlock,">","/var/lock/xcat/dispatchto_$xcatdest");
# #flock($dlock,LOCK_EX);
# $ENV{XCATHOST} = ($xcatdest =~ /:/ ? $xcatdest : $xcatdest.":3001" );
# $$progname.=": connection to ".$ENV{XCATHOST};
# my $errstr;
# eval {
# undef $_->{'_xcatdest'};
# xCAT::Client::submit_request($_,\&dispatch_callback,$xcatdir."/cert/server-cred.pem",$xcatdir."/cert/server-cred.pem",$xcatdir."/cert/ca.pem");
# };
# if ($@) {
# $errstr=$@;
# }
# #unlink("/var/lock/xcat/dispatchto_$xcatdest");
# #flock($dlock,LOCK_UN);
# if ($errstr) {
# if ($numdests == 1) {
# dispatch_callback({error=>["Unable to dispatch command to ".$ENV{XCATHOST}.", command will not make changes to that server ($errstr)"],errorcode=>[1]});
# xCAT::MsgUtils->message("S","Error dispatching request to ".$ENV{XCATHOST}.": ".$errstr);
# } else {
# xCAT::MsgUtils->message("S","Error dispatching request to ".$ENV{XCATHOST}.", trying other service nodes: ".$errstr);
# }
# next;
# } else {
# $request_satisfied=1;
# last;
# }
} else {
$$progname.=": locally executing";
$SIG{CHLD}='DEFAULT';
# ${"xCAT_plugin::".$modname."::"}{process_request}->($_,\&dispatch_callback,\&do_request);
#----- changed in Client.pm -----#
${"xCAT_plugin::".$modname."::"}{process_request}->($_,\&dispatch_cb,\&do_request);
#----- end changed in Client.pm -----#
last;
}
}
# if ($numdests > 1 and not $request_satisfied) {
# xCAT::MsgUtils->message("S","Error dispatching a request to all possible service nodes for request");
# dispatch_callback({error=>["Failed to dispatch command to any of the following service nodes: ".join(",",@xcatdests)],errorcode=>[1]});
# }
# xexit;
}
#while (($dispatch_children > 0) and ($child_fdset->count > 0)) { relay_dispatch($child_fdset) }
@ -522,11 +711,12 @@ sub dispatch_request {
}
###################################
# do_request
# called from a plugin to execute another xCAT plugin command internally
#
# NOTE: This is copied from xcatd (last merge 5/21/08).
# NOTE: This is copied from xcatd (last merge 11/23/09).
# Will eventually move to using common source....
###################################
sub do_request {