From 1a23a4b27e2d0cef57110d7f39a5788a948c11cd Mon Sep 17 00:00:00 2001 From: jjhua Date: Mon, 2 Aug 2010 08:35:45 +0000 Subject: [PATCH] add the multiple hardware control points function git-svn-id: https://svn.code.sf.net/p/xcat/code/xcat-core/trunk@6938 8638fb3e-16cb-4fca-ae20-7b5d299a9bcd --- xCAT-server/lib/perl/xCAT/PPC.pm | 258 +++++++++++++++++++++++++++---- 1 file changed, 227 insertions(+), 31 deletions(-) diff --git a/xCAT-server/lib/perl/xCAT/PPC.pm b/xCAT-server/lib/perl/xCAT/PPC.pm index e0ef7964c..f34c91c15 100644 --- a/xCAT-server/lib/perl/xCAT/PPC.pm +++ b/xCAT-server/lib/perl/xCAT/PPC.pm @@ -6,6 +6,7 @@ use lib "/opt/xcat/lib/perl"; use xCAT::Table; use xCAT::Utils; use xCAT::SvrUtils; +use xCAT::FSPUtils; use xCAT::Usage; use POSIX "WNOHANG"; use Storable qw(freeze thaw); @@ -129,11 +130,15 @@ sub send_msg { sub process_command { my $request = shift; + my $hcps_will= shift; + my $failed_nodes = shift; + my $failed_msg = shift; my %nodes = (); my $callback = $request->{callback}; my $sitetab = xCAT::Table->new( 'site' ); my @site = qw(ppcmaxp ppctimeout maxssh ppcretry fsptimeout powerinterval); my $start; + my $verbose = $request->{verbose}; ####################################### # Default site table attributes @@ -160,29 +165,29 @@ sub process_command { } #xCAT doesn't support FSPpower,FSPinv and FSPrflash by default - $request->{fsp_api} = 0; + #$request->{fsp_api} = 0; ####################################### # FSPpower, FSPinv and FSPrflash handler ######################################### - my $hwtype = $request->{hwtype}; - if ( $hwtype eq "fsp" or $hwtype eq "bpa") { - my $fsp_api = check_fsp_api($request); - if($fsp_api == 0 && - ($request->{command} =~ /^(rpower)$/ || $request->{command} =~ /^rinv$/ || $request->{command} =~ /^rflash$/ - || $request->{command} =~ /^getmacs$/ || $request->{command} =~ /^rnetboot$/ || $request->{command} =~ /^rvitals$/ - || $request->{command} =~ /^mkhwconn$/ || $request->{command} =~ /^rmhwconn$/ || $request->{command} =~ /^lshwconn$/ - || $request->{command} =~ /^rscan$/ || ($request->{command} =~ /^rspconfig$/ && $request->{method} =~ /^passwd$/) - ) - ) { + #my $hwtype = $request->{hwtype}; + #if ( $hwtype eq "fsp" or $hwtype eq "bpa") { + # my $fsp_api = check_fsp_api($request); + # if($fsp_api == 0 && + # ($request->{command} =~ /^(rpower)$/ || $request->{command} =~ /^rinv$/ || $request->{command} =~ /^rflash$/ + # || $request->{command} =~ /^getmacs$/ || $request->{command} =~ /^rnetboot$/ || $request->{command} =~ /^rvitals$/ + # || $request->{command} =~ /^mkhwconn$/ || $request->{command} =~ /^rmhwconn$/ || $request->{command} =~ /^lshwconn$/ + # || $request->{command} =~ /^rscan$/ || ($request->{command} =~ /^rspconfig$/ && $request->{method} =~ /^passwd$/) + # ) + # ) { #support FSPpower, FSPinv and FSPrflash - $request->{fsp_api} = 1; - } - } + # $request->{fsp_api} = 1; + # } + #} ####################################### # Group nodes based on command ####################################### - my $nodes = preprocess_nodes( $request ); + my $nodes = preprocess_nodes( $request, $hcps_will ); if ( !defined( $nodes )) { return(1); } @@ -288,7 +293,7 @@ sub process_command { while ($hasnode) { while ( $children >= $request->{ppcmaxp} ) { my $handlednodes={}; - child_response( $callback, $fds, $handlednodes); + child_response( $callback, $fds, $handlednodes, $failed_nodes, $failed_msg, $verbose); #update the node status to the nodelist.status table if ($check) { @@ -322,7 +327,7 @@ sub process_command { $got_one = 1; } else { my $handlednodes={}; - child_response( $callback, $fds, $handlednodes); + child_response( $callback, $fds, $handlednodes, $failed_nodes, $failed_msg, $verbose); #update the node status to the nodelist.status table if ($check) { @@ -373,7 +378,7 @@ sub process_command { while ( $children >= $request->{ppcmaxp} ) { my $handlednodes={}; - child_response( $callback, $fds, $handlednodes); + child_response( $callback, $fds, $handlednodes, $failed_nodes, $failed_msg, $verbose); #update the node status to the nodelist.status table if ($check) { @@ -384,7 +389,7 @@ sub process_command { } if ( $hw->{@$hash[0]} >= $request->{maxssh} ) { my $handlednodes={}; - child_response( $callback, $fds, $handlednodes); + child_response( $callback, $fds, $handlednodes, $failed_nodes, $failed_msg, $verbose); #update the node status to the nodelist.status table if ($check) { @@ -419,7 +424,7 @@ sub process_command { foreach ( @$nodes ) { while ( $children >= $request->{ppcmaxp} ) { my $handlednodes={}; - child_response( $callback, $fds, $handlednodes); + child_response( $callback, $fds, $handlednodes, $failed_nodes, $failed_msg, $verbose); #update the node status to the nodelist.status table if ($check) { @@ -454,7 +459,7 @@ ENDOFFORK: ####################################### while ( $fds->count > 0 or $children > 0 ) { my $handlednodes={}; - child_response( $callback, $fds, $handlednodes); + child_response( $callback, $fds, $handlednodes, $failed_nodes, $failed_msg, $verbose); #update the node status to the nodelist.status table if ($check) { @@ -468,7 +473,7 @@ ENDOFFORK: my $rc=1; while ( $rc>0 ) { my $handlednodes={}; - $rc=child_response( $callback, $fds, $handlednodes); + $rc=child_response( $callback, $fds, $handlednodes, $failed_nodes, $failed_msg, $verbose); #update the node status to the nodelist.status table if ($check) { updateNodeStatus($handlednodes, \@allerrornodes); @@ -537,6 +542,9 @@ sub child_response { my $callback = shift; my $fds = shift; my $errornodes=shift; + my $failed_nodes=shift; + my $failed_msg=shift; + my $verbose=shift; my @ready_fds = $fds->can_read(1); my $rc = @ready_fds; @@ -565,11 +573,28 @@ sub child_response { if ($nodename eq $_->{node}->[0]->{name}->[0]) { #save the nodes that has errors for node status monitoring if ((exists($_->{errorcode})) && ($_->{errorcode} != 0)) { - if ($errornodes) { $errornodes->{$_->{node}->[0]->{name}->[0]}=-1; } + push(@$failed_nodes, $nodename); + if( defined( $failed_msg->{$nodename} )) { + my $f = $failed_msg->{$nodename}; + my $c = scalar(@$f); + $failed_msg->{$nodename}->[$c] = $_; + } else { + $failed_msg->{$nodename}->[0] = $_; + } + + if ($errornodes) { $errornodes->{$_->{node}->[0]->{name}->[0]}=-1; } + #if verbose, print all the message; + #if not, print successful mesg for success, or all the failed mesg for failed. + if ( $verbose ) { + $callback->( $_ ); + } + + } else { - if ($errornodes) { $errornodes->{$_->{node}->[0]->{name}->[0]}=1; } + if ($errornodes) { $errornodes->{$_->{node}->[0]->{name}->[0]}=1; } + $callback->( $_ ); } - $callback->( $_ ); + #$callback->( $_ ); } } } @@ -637,6 +662,7 @@ sub resolve_hcp { sub preprocess_nodes { my $request = shift; + my $hcps_will = shift; my $noderange = $request->{node}; my $method = $request->{method}; my %nodehash = (); @@ -696,7 +722,9 @@ sub preprocess_nodes { ###################################### # Get data values ###################################### - my $hcp = @$d[3]; + #my $hcp = @$d[3]; + my $hcp = $hcps_will->{$node}; + @$d[3] = $hcp; my $mtms = @$d[2]; ###################################### @@ -1139,7 +1167,15 @@ sub invoke_cmd { # Error connecting #################################### if ( ref($exp[0]) ne "LWP::UserAgent" ) { - send_msg( $request, 1, $exp[0] ); + #send_msg( $request, 1, $exp[0] ); + my %output; + $output{node}->[0]->{name}->[0] = $host; + $output{node}->[0]->{data}->[0]->{contents}->[0] = "(trying ASM )$exp[0]"; + $output{errorcode} = 1; + push @outhash, \%output; + my $out = $request->{pipe}; + print $out freeze( [@outhash] ); + print $out "\nENDOFFREEZE6sK4ci\n"; return; } my $result = xCAT::PPCfsp::handler( $host, $request, \@exp ); @@ -1238,8 +1274,17 @@ sub invoke_cmd { foreach ( @$result ) { my %output; $output{node}->[0]->{name}->[0] = @$_[0]; - $output{node}->[0]->{data}->[0]->{contents}->[0] = @$_[1]; + #$output{node}->[0]->{data}->[0]->{contents}->[0] = @$_[1]; $output{errorcode} = @$_[2]; + if($output{errorcode} != 0) { + if($request->{fsp_api} == 1) { + $output{node}->[0]->{data}->[0]->{contents}->[0] = "(trying fsp-api)@$_[1]"; + } else { + $output{node}->[0]->{data}->[0]->{contents}->[0] = "(trying HMC )@$_[1]"; + } + } else { + $output{node}->[0]->{data}->[0]->{contents}->[0] = @$_[1]; + } push @outhash, \%output; } my $out = $request->{pipe}; @@ -1425,8 +1470,14 @@ sub preprocess_request { } foreach my $node (@missednodes) { my $ent=$ppctab->getNodeAttribs($node,['hcp']); - if (defined($ent->{hcp})) { push @{$hcp_hash{$ent->{hcp}}{nodes}}, $node;} - else { + #if (defined($ent->{hcp})) { push @{$hcp_hash{$ent->{hcp}}{nodes}}, $node;} + if (defined($ent->{hcp})) { + #for multiple hardware control points, the hcps should be split to nodes + my @h = split(",", $ent->{hcp}); + foreach my $hcp (@h) { + push @{$hcp_hash{$hcp}{nodes}}, $node; + } + } else { $callback->({data=>["The node $node is neither a hcp nor an lpar"]}); $req = {}; return; @@ -1453,6 +1504,8 @@ sub preprocess_request { push @nodes, @{$hcp_hash{$_}{nodes}}; } @nodes = sort @nodes; + my %hash = map{$_=>1} @nodes; #remove the repeated node for multiple hardware control points + @nodes =keys %hash; $reqcopy->{node} = \@nodes; #print "nodes=@nodes\n"; push @requests, $reqcopy; @@ -1606,7 +1659,119 @@ sub process_request { #################################### # Process remote command #################################### - process_command( $request ); + #process_command( $request ); + + #The following code supports for Multiple hardware control points. + #use @failed_nodes to store the nodes which need to be run. + #print "before process_command\n"; + my %failed_msg = (); # store the error msgs + my $t = $request->{node}; + my @failed_nodes = @$t; + #print "-------failed nodes-------\n"; + #print Dumper(\@failed_nodes); + my $hcps = getHCPsOfNodes(\@failed_nodes, $callback); + if( !defined($hcps)) { + #Not found the hcp for one node + $request = {}; + return; + } + ##################### + #print Dumper($hcps); + #$VAR1 = { + # 'lpar01' => { + # 'num' => 2, + # 'hcp' => [ + # 'Server-9110-51A-SN1075ECF', + # 'c76v2hmc02' + # ] + # } + # }; + ###################### + while(1) { + my $lasthcp_type; + my %hcps_will = (); + my @next = (); + my $count; #to count the nodes who doesn't have hcp in the $hcps + if( @failed_nodes == 0 ) { + #all nodes succeeded --- no node in @$failed_nodes; + return ; + } + + foreach my $node (@failed_nodes) { + #for multiple, get the first hcp in the $hcps{$node}. + my $hcp_list = $hcps->{$node}->{hcp}; + #print Dumper($hcp_list); + my $thishcp= shift( @$hcp_list ); + if(!defined($thishcp) ) { + #if no hcp, count++; + $count++; + if($count == @failed_nodes) { + # all the hcps of the nodes are tried. But still failed. so output the error msg and exit. + #print Dumper(\%failed_msg); + #prompt all the error msg. + foreach my $failed_node (@failed_nodes) { + my $msg = $failed_msg{$failed_node}; + foreach my $item (@$msg) { + if($item) { + #print Dumper($item); + $callback->($item); + } # end of if + } # end of foreach + }#end of foreach + #output all the msgs of the failed nodes, so return + return ; + }#end of if + #if $count != @failed_nodes, let's check next node + next; + }#end of if + #print "thishcp:$thishcp\n"; + #get the nodetype of hcp: + my $thishcp_type = xCAT::FSPUtils->getTypeOfHcp($thishcp, $callback); + if(!defined($thishcp_type)) { + $request = {}; + next; + } + #print "lasthcp_type:$lasthcp_type ;thishcp_type:$thishcp_type\n"; + if(defined($lasthcp_type)) { + if ( $lasthcp_type ne $thishcp_type ) { + $callback->({data=>["the $node\'s hcp type is different from the other's in the specified noderange in the 'ppc' table."]}); + return; + } + } + + $lasthcp_type = $thishcp_type; + $hcps_will{$node} = $thishcp; + push(@next, $node); + + } #end of foreach + my $request_new; + %$request_new =%$request; + $request_new->{node} = \@next; + $request_new->{fsp_api} = 0; + if($lasthcp_type =~ /^(fsp|bpa)$/) { + #my $fsp_api = check_fsp_api($request); + #if($fsp_api == 0 ) { + $request_new->{fsp_api} = 1; + # } + } + $request_new->{hwtype} = $lasthcp_type; + #print Dumper($request_new); + @failed_nodes = () ; + process_command( $request_new , \%hcps_will, \@failed_nodes, \%failed_msg); + #print "after result:\n"; + #print Dumper(\@failed_nodes); + if($lasthcp_type =~ /^(fsp|bpa)$/) { + #through asmi ...... + $request_new->{fsp_api} = 0; + if(@failed_nodes != 0) { + my @temp = @failed_nodes; + @failed_nodes = (); + $request_new->{node} = \@temp; + process_command( $request_new , \%hcps_will, \@failed_nodes, \%failed_msg); + } + } + } #end of while(1) + } ########################################################################## @@ -1780,6 +1945,37 @@ sub check_fsp_api return -1; } +sub getHCPsOfNodes +{ + my $nodes = shift; + my $callback = shift; + my %hcps = (); + #get hcp from ppc. + foreach my $node( @$nodes) { + my $ppctab = xCAT::Table->new( 'ppc'); + unless($ppctab) { + $callback->({data=>["Cannot open ppc table"]}); + return undef; + } + #xCAT::MsgUtils->message('E', "Failed to open table 'ppc'.") if ( ! $ppctab); + my $hcp_hash = $ppctab->getNodeAttribs( $node,[qw(hcp)]); + my $hcp = $hcp_hash->{hcp}; + if ( !$hcp) { + #xCAT::MsgUtils->message('E', "Not found the hcp of $node"); + $callback->({data=>["Not found the hcp of $node"]}); + return undef; + } + #print "hcp:\n"; + #print Dumper($hcp); + my @h = split(",", $hcp); + $hcps{$node}{hcp} = \@h; + $hcps{$node}{num} = @h; + } + #print "in getHCPsOfNodes\n"; + #print Dumper(\%hcps); + return \%hcps; +} + 1;