git-svn-id: https://svn.code.sf.net/p/xcat/code/xcat-core/trunk@4963 8638fb3e-16cb-4fca-ae20-7b5d299a9bcd
		
			
				
	
	
		
			1695 lines
		
	
	
		
			55 KiB
		
	
	
	
		
			Perl
		
	
	
	
	
	
			
		
		
	
	
			1695 lines
		
	
	
		
			55 KiB
		
	
	
	
		
			Perl
		
	
	
	
	
	
# IBM(c) 2007 EPL license http://www.eclipse.org/legal/epl-v10.html
 | 
						|
 | 
						|
package xCAT::PPC;
 | 
						|
use strict;
 | 
						|
use lib "/opt/xcat/lib/perl";
 | 
						|
use xCAT::Table;
 | 
						|
use xCAT::Utils;
 | 
						|
use xCAT::SvrUtils;
 | 
						|
use xCAT::Usage;
 | 
						|
use POSIX "WNOHANG";
 | 
						|
use Storable qw(freeze thaw);
 | 
						|
use Time::HiRes qw(gettimeofday sleep);
 | 
						|
use IO::Select;
 | 
						|
use Socket;
 | 
						|
use xCAT::PPCcli; 
 | 
						|
use xCAT::GlobalDef;
 | 
						|
use xCAT::DBobjUtils;
 | 
						|
use xCAT_monitoring::monitorctrl;
 | 
						|
use Thread qw(yield);
 | 
						|
 | 
						|
 | 
						|
##########################################
 | 
						|
# Globals
 | 
						|
##########################################
 | 
						|
my %modules = (
 | 
						|
        rinv      => { hmc    => "xCAT::PPCinv",
 | 
						|
                       fsp    => "xCAT::FSPinv",
 | 
						|
                       bpa    => "xCAT::FSPinv",
 | 
						|
		       },
 | 
						|
        rpower    => { hmc    => "xCAT::PPCpower",
 | 
						|
                       fsp    => "xCAT::FSPpower",
 | 
						|
                       bpa    => "xCAT::FSPpower",
 | 
						|
		       },
 | 
						|
        rvitals   => { hmc    => "xCAT::PPCvitals",
 | 
						|
                       fsp    => "xCAT::FSPvitals",
 | 
						|
                       bpa    => "xCAT::FSPvitals",
 | 
						|
		       },
 | 
						|
        rscan     => { hmc    => "xCAT::PPCscan",
 | 
						|
		       },
 | 
						|
        mkvm      => { hmc    => "xCAT::PPCvm",
 | 
						|
		      },
 | 
						|
        rmvm      => { hmc    => "xCAT::PPCvm",
 | 
						|
		      },
 | 
						|
        lsvm      => { hmc    => "xCAT::PPCvm",
 | 
						|
		      },
 | 
						|
        chvm      => { hmc    => "xCAT::PPCvm",
 | 
						|
		      },
 | 
						|
        rnetboot  => { hmc    => "xCAT::PPCboot",
 | 
						|
                       fsp    => "xCAT::FSPboot",
 | 
						|
		      },
 | 
						|
        getmacs   => { hmc    => "xCAT::PPCmac",
 | 
						|
                       fsp    => "xCAT::FSPmac",
 | 
						|
		      },
 | 
						|
        reventlog => { hmc    => "xCAT::PPClog",
 | 
						|
		      },
 | 
						|
        rspconfig => { hmc    => "xCAT::PPCcfg",
 | 
						|
                       fsp    => "xCAT::PPCcfg",
 | 
						|
                       bpa    => "xCAT::PPCcfg",
 | 
						|
		      },
 | 
						|
        rflash    => { hmc    => "xCAT::PPCrflash",
 | 
						|
                       fsp    => "xCAT::FSPflash",
 | 
						|
                       bpa    => "xCAT::FSPflash",
 | 
						|
	              },
 | 
						|
        mkhwconn  => { hmc    => "xCAT::PPCconn",
 | 
						|
                       fsp    => "xCAT::PPCconn",
 | 
						|
                       bpa    => "xCAT::PPCconn",
 | 
						|
		      },
 | 
						|
        rmhwconn  => { hmc    => "xCAT::PPCconn",
 | 
						|
                       fsp    => "xCAT::PPCconn",
 | 
						|
                       bpa    => "xCAT::PPCconn",
 | 
						|
		      },
 | 
						|
        lshwconn  => { hmc    => "xCAT::PPCconn",
 | 
						|
                       fsp    => "xCAT::PPCconn",
 | 
						|
                       bpa    => "xCAT::PPCconn",
 | 
						|
		      },
 | 
						|
        renergy   => { hmc    => "xCAT::PPCenergy",
 | 
						|
		     },
 | 
						|
        );
 | 
						|
 | 
						|
 | 
						|
##########################################
 | 
						|
# Database errors
 | 
						|
##########################################
 | 
						|
my %errmsg = (
 | 
						|
        NODE_UNDEF =>"Node not defined in '%s' database",
 | 
						|
        NO_ATTR    =>"'%s' not defined in '%s' database",  
 | 
						|
        NO_UNDEF   =>"'%s' not defined in '%s' database for '%s'",
 | 
						|
        DB_UNDEF   =>"'%s' database not defined"
 | 
						|
        );
 | 
						|
 | 
						|
##########################################################################
 | 
						|
# Invokes the callback with the specified message                    
 | 
						|
##########################################################################
 | 
						|
sub send_msg {
 | 
						|
 | 
						|
    my $request = shift;
 | 
						|
    my $ecode   = shift;
 | 
						|
    my %output;
 | 
						|
 | 
						|
    #################################################
 | 
						|
    # Called from child process - send to parent
 | 
						|
    #################################################
 | 
						|
    if ( exists( $request->{pipe} )) {
 | 
						|
        my $out = $request->{pipe};
 | 
						|
 | 
						|
        $output{errorcode} = $ecode;
 | 
						|
        $output{data} = \@_;
 | 
						|
        print $out freeze( [\%output] );
 | 
						|
        print $out "\nENDOFFREEZE6sK4ci\n";
 | 
						|
    }
 | 
						|
    #################################################
 | 
						|
    # Called from parent - invoke callback directly
 | 
						|
    #################################################
 | 
						|
    elsif ( exists( $request->{callback} )) {
 | 
						|
        my $callback = $request->{callback};
 | 
						|
 | 
						|
        $output{errorcode} = $ecode;
 | 
						|
        $output{data} = \@_;
 | 
						|
        $callback->( \%output );
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
##########################################################################
 | 
						|
# Fork child to execute remote commands
 | 
						|
##########################################################################
 | 
						|
sub process_command {
 | 
						|
 | 
						|
    my $request  = shift;
 | 
						|
    my %nodes    = ();
 | 
						|
    my $callback = $request->{callback};
 | 
						|
    my $sitetab  = xCAT::Table->new( 'site' );
 | 
						|
    my @site     = qw(ppcmaxp ppctimeout maxssh ppcretry fsptimeout powerinterval); 
 | 
						|
    my $start;
 | 
						|
 | 
						|
    #######################################
 | 
						|
    # Default site table attributes 
 | 
						|
    #######################################
 | 
						|
    $request->{ppcmaxp}    = 64;
 | 
						|
    $request->{ppctimeout} = 0;
 | 
						|
    $request->{fsptimeout} = 0;
 | 
						|
    $request->{ppcretry}   = 3;
 | 
						|
    $request->{maxssh}     = 8;
 | 
						|
 | 
						|
    #######################################
 | 
						|
    # Get site table attributes 
 | 
						|
    #######################################
 | 
						|
    if ( defined( $sitetab )) {
 | 
						|
        foreach ( @site ) {
 | 
						|
            my ($ent) = $sitetab->getAttribs({ key=>$_},'value');
 | 
						|
            if ( defined($ent) ) { 
 | 
						|
                $request->{$_} = $ent->{value}; 
 | 
						|
            }
 | 
						|
        }
 | 
						|
    }
 | 
						|
    if ( exists( $request->{verbose} )) {
 | 
						|
        $start = Time::HiRes::gettimeofday();
 | 
						|
    }
 | 
						|
 | 
						|
    #xCAT doesn't support FSPpower,FSPinv and FSPrflash by default
 | 
						|
    $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$/  )
 | 
						|
              ) {
 | 
						|
	        #support FSPpower, FSPinv and FSPrflash 
 | 
						|
	        $request->{fsp_api} = 1;
 | 
						|
            }
 | 
						|
    } 
 | 
						|
 | 
						|
    #######################################
 | 
						|
    # Group nodes based on command
 | 
						|
    #######################################
 | 
						|
    my $nodes = preprocess_nodes( $request );
 | 
						|
    if ( !defined( $nodes )) {
 | 
						|
        return(1);
 | 
						|
    }
 | 
						|
 | 
						|
    #get new node status
 | 
						|
    my %oldnodestatus=(); #saves the old node status
 | 
						|
        my @allerrornodes=();
 | 
						|
    my $check=0;
 | 
						|
    my $global_check=1;
 | 
						|
    if ($sitetab) {
 | 
						|
        (my $ref) = $sitetab->getAttribs({key => 'nodestatus'}, 'value');
 | 
						|
        if ($ref) {
 | 
						|
            if ($ref->{value} =~ /0|n|N/) { $global_check=0; }
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    my $command=$request->{command};
 | 
						|
    if (($command eq 'rpower') || ($command eq 'rnetboot')) {
 | 
						|
        my $subcommand="temp";
 | 
						|
        if ($command eq 'rpower') {  $subcommand=$request->{op}; }
 | 
						|
        if (($global_check) && ($subcommand ne 'stat') && ($subcommand ne 'status') && ($subcommand ne 'state')) { 
 | 
						|
            $check=1; 
 | 
						|
            my $noderange = $request->{node}; 
 | 
						|
            my @allnodes=@$noderange;
 | 
						|
 | 
						|
            #save the old status
 | 
						|
            my $nodelisttab = xCAT::Table->new('nodelist');
 | 
						|
            if ($nodelisttab) {
 | 
						|
                my $tabdata     = $nodelisttab->getNodesAttribs(\@allnodes, ['node', 'status']);
 | 
						|
                foreach my $node (@allnodes)
 | 
						|
                {
 | 
						|
                    my $tmp1 = $tabdata->{$node}->[0];
 | 
						|
                    if ($tmp1) { 
 | 
						|
                        if ($tmp1->{status}) { $oldnodestatus{$node}=$tmp1->{status}; }
 | 
						|
                        else { $oldnodestatus{$node}=""; }
 | 
						|
                    }
 | 
						|
                }
 | 
						|
            }
 | 
						|
            #print "oldstatus:" . Dumper(\%oldnodestatus);
 | 
						|
 | 
						|
            #set the new status to the nodelist.status
 | 
						|
            my %newnodestatus=(); 
 | 
						|
            my $newstat;
 | 
						|
            if (($subcommand eq 'off') || ($subcommand eq 'softoff')) { 
 | 
						|
                my $newstat=$::STATUS_POWERING_OFF; 
 | 
						|
                $newnodestatus{$newstat}=\@allnodes;
 | 
						|
            } else {
 | 
						|
                #get the current nodeset stat
 | 
						|
                if (@allnodes>0) {
 | 
						|
                    my $nsh={};
 | 
						|
                    my ($ret, $msg)=xCAT::SvrUtils->getNodesetStates(\@allnodes, $nsh);
 | 
						|
                    if (!$ret) { 
 | 
						|
                        foreach (keys %$nsh) {
 | 
						|
                            my $newstat=xCAT_monitoring::monitorctrl->getNodeStatusFromNodesetState($_, $command);
 | 
						|
                            $newnodestatus{$newstat}=$nsh->{$_};
 | 
						|
                        }
 | 
						|
                    } else {
 | 
						|
                        trace( $request, $msg );
 | 
						|
                    }
 | 
						|
                }
 | 
						|
            }
 | 
						|
            #print "newstatus" . Dumper(\%newnodestatus);
 | 
						|
            xCAT_monitoring::monitorctrl::setNodeStatusAttributes(\%newnodestatus, 1);
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
 | 
						|
 | 
						|
    #######################################
 | 
						|
    # Fork process
 | 
						|
    #######################################
 | 
						|
    my $children = 0;
 | 
						|
    my $fds = new IO::Select;
 | 
						|
 | 
						|
    # For the commands getmacs and rnetboot, each time 
 | 
						|
    # to fork process, pick out the HMC that has the 
 | 
						|
    # least process number created to connect to the HMC.
 | 
						|
    # After the process by preprocess_nodes, the $nodes 
 | 
						|
    # variable has following structure:
 | 
						|
    # $nodes
 | 
						|
    #   |hcp
 | 
						|
    #       |[[hcp,node1_attr], [hcp,node2_attr] ...]
 | 
						|
    #       |count    //node number managed by the hcp
 | 
						|
    #       |runprocess    //the process number connect to the hcp
 | 
						|
    #       |index    //the index of node will be forked of the hcp
 | 
						|
    if ( ($request->{command} =~ /^(getmacs)$/ && exists( $request->{opt}->{D} )) || ($request->{command} =~ /^(rnetboot)$/) ) {
 | 
						|
        my %pid_owner = ();
 | 
						|
 | 
						|
        $request->{maxssh} = int($request->{maxssh}/2);
 | 
						|
        # Use the CHID signal to control the 
 | 
						|
        #connection number of certain hcp    
 | 
						|
        $SIG{CHLD} = sub { my $pid = 0; while (($pid = waitpid(-1, WNOHANG)) > 0) 
 | 
						|
            { $nodes->{$pid_owner{$pid}}{'runprocess'}--; delete $pid_owner{$pid}; $children--; } };
 | 
						|
 | 
						|
        $SIG{INT} = $SIG{TERM} = sub { #prepare to process job termination and propogate it down
 | 
						|
            foreach (keys %pid_owner) {
 | 
						|
                kill 9, $_;
 | 
						|
            }
 | 
						|
            exit 0;
 | 
						|
        };
 | 
						|
 | 
						|
        my $hasnode = 1;
 | 
						|
        while ($hasnode) {
 | 
						|
            while ( $children >= $request->{ppcmaxp} ) {
 | 
						|
                my $handlednodes={};
 | 
						|
                child_response( $callback, $fds, $handlednodes);
 | 
						|
 | 
						|
                #update the node status to the nodelist.status table
 | 
						|
                if ($check) {
 | 
						|
                    updateNodeStatus($handlednodes, \@allerrornodes);
 | 
						|
                }
 | 
						|
 | 
						|
                Time::HiRes::sleep(0.1);
 | 
						|
            }
 | 
						|
            # Pick out the hcp which has least processes
 | 
						|
            my $least_processes = $request->{maxssh};
 | 
						|
            my $least_hcp;
 | 
						|
            my $got_one = 0;
 | 
						|
            while (!$got_one) {
 | 
						|
                $hasnode = 0;
 | 
						|
                foreach my $hcp (keys %$nodes) {
 | 
						|
                    if ($nodes->{$hcp}{'index'} < $nodes->{$hcp}{'count'}) {
 | 
						|
                        $hasnode = 1;
 | 
						|
                        if ($nodes->{$hcp}{'runprocess'} < $least_processes) {
 | 
						|
                            $least_processes = $nodes->{$hcp}{'runprocess'};
 | 
						|
                            $least_hcp = $hcp;
 | 
						|
                        }
 | 
						|
                    }
 | 
						|
                }
 | 
						|
 | 
						|
                if (!$hasnode) {
 | 
						|
                    # There are no node in the $nodes
 | 
						|
                    goto ENDOFFORK;
 | 
						|
                }
 | 
						|
 | 
						|
                if ($least_processes < $request->{maxssh}) {
 | 
						|
                    $got_one = 1;
 | 
						|
                } else {
 | 
						|
                    my $handlednodes={};
 | 
						|
                    child_response( $callback, $fds, $handlednodes);
 | 
						|
 | 
						|
                    #update the node status to the nodelist.status table
 | 
						|
                    if ($check) {
 | 
						|
                        updateNodeStatus($handlednodes, \@allerrornodes);
 | 
						|
                    }
 | 
						|
                    Time::HiRes::sleep(0.1);
 | 
						|
                }
 | 
						|
            }
 | 
						|
 | 
						|
            Time::HiRes::sleep(0.1);
 | 
						|
            my ($pipe, $pid) = fork_cmd( $nodes->{$least_hcp}{'nodegroup'}->[$nodes->{$least_hcp}{'index'}]->[0], 
 | 
						|
                    $nodes->{$least_hcp}{'nodegroup'}->[$nodes->{$least_hcp}{'index'}]->[1], $request );
 | 
						|
 | 
						|
            if ($pid) {
 | 
						|
                $pid_owner{$pid} = $least_hcp;
 | 
						|
                $nodes->{$least_hcp}{'index'}++;
 | 
						|
                $nodes->{$least_hcp}{'runprocess'}++;
 | 
						|
            }
 | 
						|
 | 
						|
            if ( $pipe ) {
 | 
						|
                $fds->add( $pipe );
 | 
						|
                $children++;
 | 
						|
            }
 | 
						|
        }
 | 
						|
    } elsif ( $request->{command} =~ /^(getmacs)$/ && exists( $request->{opt}->{arp} ) ) {
 | 
						|
        my $node;
 | 
						|
        my $data;
 | 
						|
        my $unreachable_nodes;
 | 
						|
        my $noderange = join (',', @$nodes);
 | 
						|
        my @output = xCAT::Utils->runcmd("/opt/xcat/bin/pping $noderange", -1);
 | 
						|
 | 
						|
        foreach my $line (@output) {
 | 
						|
            my ($hostname, $result) = split ':', $line;
 | 
						|
            my ($token,    $status) = split ' ', $result;
 | 
						|
            chomp($token);
 | 
						|
            if ($token eq 'ping') {
 | 
						|
                $node->{$hostname}->{reachable} = 1;
 | 
						|
            }
 | 
						|
        }
 | 
						|
 | 
						|
        foreach my $n ( @$nodes ) {
 | 
						|
            if ( $node->{$n}->{reachable} ) {
 | 
						|
                my $output;
 | 
						|
                my $IP = xCAT::Utils::toIP( $n );
 | 
						|
                if ( xCAT::Utils->isAIX() ) {
 | 
						|
                    $output = `/usr/sbin/arp -a`;
 | 
						|
                } else {
 | 
						|
                    $output = `/sbin/arp -n`;
 | 
						|
                }
 | 
						|
 | 
						|
                my ($ip, $mac);
 | 
						|
                my @lines = split /\n/, $output;
 | 
						|
                foreach my $line ( @lines ) {
 | 
						|
                    if ( xCAT::Utils->isAIX() && $line =~ /\((\S+)\)\s+at\s+(\S+)/ ) {
 | 
						|
                        ($ip, $mac) = ($1,$2);
 | 
						|
                        ######################################################
 | 
						|
                        # Change mac format to be same as linux. For example:
 | 
						|
                        # '0:d:60:f4:f8:22' to '00:0d:60:f4:f8:22'
 | 
						|
                        ######################################################
 | 
						|
                        if ( $mac)
 | 
						|
                        {
 | 
						|
                            my @mac_sections = split /:/, $mac;
 | 
						|
                            for my $m (@mac_sections)
 | 
						|
                            {
 | 
						|
                                $m = "0$m" if ( length($m) == 1);
 | 
						|
                            }
 | 
						|
                            $mac = join ':', @mac_sections;
 | 
						|
                        }
 | 
						|
                    } elsif ( $line =~ /^(\S+)+\s+\S+\s+(\S+)\s/ ) {
 | 
						|
                        ($ip, $mac) = ($1,$2);
 | 
						|
                    } else {
 | 
						|
                        ($ip, $mac) = (undef,undef);
 | 
						|
                    }
 | 
						|
                    if ( @$IP[1] !~ $ip ) {
 | 
						|
                        ($ip, $mac) = (undef,undef);
 | 
						|
                    } else {
 | 
						|
                        last;
 | 
						|
                    }
 | 
						|
                }
 | 
						|
                if ( $ip && $mac ) {
 | 
						|
                    if ( !exists( $request->{opt}->{d} ) ) {
 | 
						|
                        #####################################
 | 
						|
                        # Write adapter mac to database
 | 
						|
                        #####################################
 | 
						|
                        my $mactab = xCAT::Table->new( "mac", -create=>1, -autocommit=>1 );
 | 
						|
                        $mactab->setNodeAttribs( $n,{mac=>$mac} );
 | 
						|
                        $mactab->close();
 | 
						|
                    }
 | 
						|
 | 
						|
                    $callback->({node=>[{name=>[$n],data=>["\n#IP           MAC\n$ip  $mac\n"]}]});
 | 
						|
                }
 | 
						|
            } else {
 | 
						|
                $unreachable_nodes = join (",", $n, $unreachable_nodes);
 | 
						|
            }
 | 
						|
        }
 | 
						|
        $callback->({data=>["Unreachable Nodes:"]});
 | 
						|
        $callback->({data=>["$unreachable_nodes\n"]});
 | 
						|
    } elsif ( $request->{command} =~ /^rpower$/ ) {
 | 
						|
        my $hw;
 | 
						|
        my $sessions;
 | 
						|
        my $pid_owner;
 | 
						|
        my $remain_node = $nodes;
 | 
						|
 | 
						|
        while ( scalar($remain_node) ) {
 | 
						|
            $remain_node = ();
 | 
						|
            foreach my $hash ( @$nodes ) {
 | 
						|
                $SIG{CHLD} = sub { my $pid = 0; while (($pid = waitpid(-1, WNOHANG)) > 0) { $hw->{$pid_owner->{$pid}}--; $children--; } };
 | 
						|
 
 | 
						|
                while ( $children >= $request->{ppcmaxp} ) {
 | 
						|
                    my $handlednodes={};
 | 
						|
                    child_response( $callback, $fds, $handlednodes);
 | 
						|
 | 
						|
                    #update the node status to the nodelist.status table
 | 
						|
                    if ($check) {
 | 
						|
                        updateNodeStatus($handlednodes, \@allerrornodes);
 | 
						|
                    }
 | 
						|
 | 
						|
                    Time::HiRes::sleep(0.1);
 | 
						|
                }
 | 
						|
                if ( $hw->{@$hash[0]} >= $request->{maxssh} ) {
 | 
						|
                    my $handlednodes={};
 | 
						|
                    child_response( $callback, $fds, $handlednodes);
 | 
						|
 | 
						|
                    #update the node status to the nodelist.status table
 | 
						|
                    if ($check) {
 | 
						|
                        updateNodeStatus($handlednodes, \@allerrornodes);
 | 
						|
                    }
 | 
						|
 | 
						|
                    Time::HiRes::sleep(0.1);
 | 
						|
                    push( @$remain_node, [@$hash[0], @$hash[1]] );
 | 
						|
                    next;
 | 
						|
                }
 | 
						|
 | 
						|
                my ($pipe,$pid) = fork_cmd( @$hash[0], @$hash[1], $request );
 | 
						|
 | 
						|
                if ($pid) {
 | 
						|
                    $pid_owner->{$pid} = @$hash[0];
 | 
						|
                    $hw->{@$hash[0]}++;
 | 
						|
                }
 | 
						|
 | 
						|
                if ( $pipe ) {
 | 
						|
                    $fds->add( $pipe );
 | 
						|
                    $children++;
 | 
						|
                }
 | 
						|
            }
 | 
						|
 | 
						|
            $nodes = $remain_node;
 | 
						|
        }
 | 
						|
    } else {
 | 
						|
        $SIG{CHLD} = sub { while (waitpid(-1, WNOHANG) > 0) { $children--; } };
 | 
						|
        my $hw;
 | 
						|
        my $sessions;
 | 
						|
 | 
						|
        foreach ( @$nodes ) {
 | 
						|
            while ( $children >= $request->{ppcmaxp} ) {
 | 
						|
                my $handlednodes={};
 | 
						|
                child_response( $callback, $fds, $handlednodes);
 | 
						|
 | 
						|
                #update the node status to the nodelist.status table
 | 
						|
                if ($check) {
 | 
						|
                    updateNodeStatus($handlednodes, \@allerrornodes);
 | 
						|
                }
 | 
						|
 | 
						|
                Time::HiRes::sleep(0.1);
 | 
						|
            }
 | 
						|
            ###################################
 | 
						|
            # sleep between connects to same
 | 
						|
            # HMC/IVM so as not to overwelm it
 | 
						|
            ###################################
 | 
						|
            if ( $hw ne @$_[0] ) {
 | 
						|
                $sessions = 1;
 | 
						|
            } elsif ( $sessions++ >= $request->{maxssh} ) {
 | 
						|
                sleep(1);
 | 
						|
                $sessions = 1;
 | 
						|
            }
 | 
						|
            $hw = @$_[0];
 | 
						|
 | 
						|
            my ($pipe) = fork_cmd( @$_[0], @$_[1], $request );
 | 
						|
            if ( $pipe ) {
 | 
						|
                $fds->add( $pipe );
 | 
						|
                $children++;
 | 
						|
            }
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
ENDOFFORK:
 | 
						|
    #######################################
 | 
						|
    # Process responses from children
 | 
						|
    #######################################
 | 
						|
    while ( $fds->count > 0 or $children > 0 ) {
 | 
						|
        my $handlednodes={};
 | 
						|
        child_response( $callback, $fds, $handlednodes);
 | 
						|
 | 
						|
        #update the node status to the nodelist.status table
 | 
						|
        if ($check) {
 | 
						|
            updateNodeStatus($handlednodes, \@allerrornodes);
 | 
						|
        }
 | 
						|
 | 
						|
        Time::HiRes::sleep(0.1);
 | 
						|
    }
 | 
						|
 | 
						|
    #drain one more time
 | 
						|
    my $rc=1;
 | 
						|
    while ( $rc>0 ) {
 | 
						|
        my $handlednodes={};
 | 
						|
        $rc=child_response( $callback, $fds, $handlednodes);
 | 
						|
        #update the node status to the nodelist.status table
 | 
						|
        if ($check) {
 | 
						|
            updateNodeStatus($handlednodes, \@allerrornodes);
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    if ( exists( $request->{verbose} )) {
 | 
						|
        my $elapsed = Time::HiRes::gettimeofday() - $start;
 | 
						|
        my $msg     = sprintf( "Total Elapsed Time: %.3f sec\n", $elapsed );
 | 
						|
        trace( $request, $msg );
 | 
						|
    }
 | 
						|
 | 
						|
    if ($check) {
 | 
						|
        #print "allerrornodes=@allerrornodes\n";
 | 
						|
        #revert the status back for there is no-op for the nodes
 | 
						|
        my %old=(); 
 | 
						|
        foreach my $node (@allerrornodes) {
 | 
						|
            my $stat=$oldnodestatus{$node};
 | 
						|
            if (exists($old{$stat})) {
 | 
						|
                my $pa=$old{$stat};
 | 
						|
                push(@$pa, $node);
 | 
						|
            }
 | 
						|
            else {
 | 
						|
                $old{$stat}=[$node];
 | 
						|
            }
 | 
						|
        } 
 | 
						|
        xCAT_monitoring::monitorctrl::setNodeStatusAttributes(\%old, 1);
 | 
						|
    }  
 | 
						|
 | 
						|
 | 
						|
    return(0);
 | 
						|
}
 | 
						|
 | 
						|
##########################################################################
 | 
						|
# updateNodeStatus
 | 
						|
##########################################################################
 | 
						|
sub updateNodeStatus {
 | 
						|
    my $handlednodes=shift;
 | 
						|
    my $allerrornodes=shift;
 | 
						|
    foreach my $node (keys(%$handlednodes)) {
 | 
						|
        if ($handlednodes->{$node} == -1) { push(@$allerrornodes, $node); }  
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
##########################################################################
 | 
						|
# Verbose mode (-V)
 | 
						|
##########################################################################
 | 
						|
sub trace {
 | 
						|
 | 
						|
    my $request = shift;
 | 
						|
    my $msg   = shift;
 | 
						|
 | 
						|
    my ($sec,$min,$hour,$mday,$mon,$yr,$wday,$yday,$dst) = localtime(time);
 | 
						|
    my $formatted = sprintf "%02d:%02d:%02d %5d %s", $hour,$min,$sec,$$,$msg;
 | 
						|
 | 
						|
    my $callback = $request->{callback};
 | 
						|
    $callback->( {data=>[$formatted]} );
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
##########################################################################
 | 
						|
# Send response from child process back to xCAT client
 | 
						|
##########################################################################
 | 
						|
sub child_response {
 | 
						|
 | 
						|
    my $callback = shift;
 | 
						|
    my $fds = shift;
 | 
						|
    my $errornodes=shift;
 | 
						|
    my @ready_fds = $fds->can_read(1);
 | 
						|
    my $rc = @ready_fds;
 | 
						|
 | 
						|
    foreach my $rfh (@ready_fds) {
 | 
						|
        my $data = <$rfh>;
 | 
						|
 | 
						|
        #################################
 | 
						|
        # Read from child process
 | 
						|
        #################################
 | 
						|
        if ( defined( $data )) {
 | 
						|
            while ($data !~ /ENDOFFREEZE6sK4ci/) {
 | 
						|
                $data .= <$rfh>;
 | 
						|
            }
 | 
						|
            my $responses = thaw($data);
 | 
						|
            foreach ( @$responses ) {
 | 
						|
                #save the nodes that has errors for node status monitoring
 | 
						|
                if ((exists($_->{errorcode})) && ($_->{errorcode} != 0))  { 
 | 
						|
                    if ($errornodes) { $errornodes->{$_->{node}->[0]->{name}->[0]}=-1; } 
 | 
						|
                } else {
 | 
						|
                    if ($errornodes) { $errornodes->{$_->{node}->[0]->{name}->[0]}=1; } 
 | 
						|
                }
 | 
						|
                $callback->( $_ );
 | 
						|
            }
 | 
						|
            next;
 | 
						|
        }
 | 
						|
        #################################
 | 
						|
        # Done - close handle
 | 
						|
        #################################
 | 
						|
        $fds->remove($rfh);
 | 
						|
        close($rfh);
 | 
						|
    }
 | 
						|
    yield; #Try to avoid useless iterations as much as possible
 | 
						|
    return $rc;
 | 
						|
} 
 | 
						|
 | 
						|
 | 
						|
##########################################################################
 | 
						|
# Finds attributes for given node is various databases
 | 
						|
##########################################################################
 | 
						|
sub resolve_hcp {
 | 
						|
    my $request   = shift;
 | 
						|
    my $noderange = shift;
 | 
						|
    my @nodegroup = ();
 | 
						|
    my $tab       = ($request->{hwtype} eq "fsp" or $request->{hwtype} eq "bpa") ? "ppcdirect" : "ppchcp";
 | 
						|
    my $db        = xCAT::Table->new( $tab );
 | 
						|
 | 
						|
    ####################################
 | 
						|
    # Database not defined 
 | 
						|
    ####################################
 | 
						|
    if ( !defined( $db )) {
 | 
						|
        send_msg( $request, 1, sprintf( $errmsg{DB_UNDEF}, $tab ));
 | 
						|
        return undef;
 | 
						|
    }
 | 
						|
    ####################################
 | 
						|
    # Process each node
 | 
						|
    ####################################
 | 
						|
    foreach my $hcp ( @$noderange ) {
 | 
						|
#        my ($ent) = $db->getAttribs( {hcp=>$hcp},"hcp" );
 | 
						|
#        my ($ent) = $db->getNodeAttribs( $hcp, ["hcp"]);
 | 
						|
 | 
						|
#        if ( !defined( $ent )) {
 | 
						|
#            my $msg = sprintf( "$hcp: $errmsg{NODE_UNDEF}", $tab );
 | 
						|
#            send_msg( $request, 1, $msg );
 | 
						|
#            next;
 | 
						|
#        }
 | 
						|
        ################################
 | 
						|
        # Get userid and password
 | 
						|
        ################################
 | 
						|
        my @cred = xCAT::PPCdb::credentials( $hcp, $request->{hwtype} );
 | 
						|
        $request->{$hcp}{cred} = \@cred;
 | 
						|
 | 
						|
        ################################
 | 
						|
        # Save values
 | 
						|
        ################################
 | 
						|
        push @nodegroup,[$hcp];
 | 
						|
    }
 | 
						|
    return( \@nodegroup );
 | 
						|
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
##########################################################################
 | 
						|
# Group nodes depending on command
 | 
						|
##########################################################################
 | 
						|
sub preprocess_nodes {
 | 
						|
 | 
						|
    my $request   = shift;
 | 
						|
    my $noderange = $request->{node};
 | 
						|
    my $method    = $request->{method};
 | 
						|
    my %nodehash  = ();
 | 
						|
    my @nodegroup = ();
 | 
						|
    my %hcpgroup  = ();
 | 
						|
    my %tabs      = ();
 | 
						|
    my $netwk;
 | 
						|
 | 
						|
    ########################################
 | 
						|
    # Special cases
 | 
						|
    #   rscan - Nodes are hardware control pts 
 | 
						|
    #   FSPpower, FSPinv and FSPrflash 
 | 
						|
    ########################################
 | 
						|
    if (( !$request->{hcp} && ($request->{hcp} ne "hmc" )) 
 | 
						|
        and ($request->{command} !~ /^renergy$/)
 | 
						|
        and (( $request->{command} =~ /^(rscan|rspconfig)$/ ) 
 | 
						|
            or ($request->{hwtype} eq "fsp" or $request->{hwtype} eq "bpa" ) 
 | 
						|
            or ($request->{command} eq 'lshwconn' and $request->{nodetype} eq 'hmc')) and ($request->{fsp_api} != 1)
 | 
						|
       ) {
 | 
						|
        my $result = resolve_hcp( $request, $noderange );
 | 
						|
        return( $result );
 | 
						|
    }
 | 
						|
    ##########################################
 | 
						|
    # Special processing - rnetboot 
 | 
						|
    ##########################################
 | 
						|
    if ( $request->{command} eq "rnetboot" ) { 
 | 
						|
        $netwk = resolve_netwk( $request, $noderange );
 | 
						|
        if ( !defined( %$netwk )) {
 | 
						|
            return undef;
 | 
						|
        }
 | 
						|
    }
 | 
						|
    ##########################################
 | 
						|
    # Open databases needed
 | 
						|
    ##########################################
 | 
						|
    foreach ( qw(ppc vpd nodetype) ) {
 | 
						|
        $tabs{$_} = xCAT::Table->new($_);
 | 
						|
 | 
						|
        if ( !exists( $tabs{$_} )) { 
 | 
						|
            send_msg( $request, 1, sprintf( $errmsg{DB_UNDEF}, $_ )); 
 | 
						|
            return undef;
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    ##########################################
 | 
						|
    # Group nodes
 | 
						|
    ##########################################
 | 
						|
    foreach my $node ( @$noderange ) {
 | 
						|
        my $d = resolve( $request, $node, \%tabs );
 | 
						|
 | 
						|
        ######################################
 | 
						|
        # Error locating node attributes
 | 
						|
        ######################################
 | 
						|
        if ( ref($d) ne 'ARRAY' ) {
 | 
						|
            send_msg( $request, 1, "$node: $d");
 | 
						|
            next;
 | 
						|
        }
 | 
						|
        ######################################
 | 
						|
        # Get data values 
 | 
						|
        ######################################
 | 
						|
        my $hcp  = @$d[3];
 | 
						|
        my $mtms = @$d[2];
 | 
						|
 
 | 
						|
        ######################################
 | 
						|
        # Special case for mkhwconn
 | 
						|
        ######################################
 | 
						|
        if ( $request->{command} eq "mkhwconn" and 
 | 
						|
              exists $request->{opt}->{p})
 | 
						|
        {
 | 
						|
            $nodehash{ $request->{opt}->{p}}{$mtms}{$node} = $d;
 | 
						|
        }
 | 
						|
        ######################################
 | 
						|
        #The common case
 | 
						|
        ######################################
 | 
						|
        else 
 | 
						|
        {
 | 
						|
            $nodehash{$hcp}{$mtms}{$node} = $d;
 | 
						|
        }
 | 
						|
    } 
 | 
						|
 | 
						|
    ##########################################
 | 
						|
    # Get userid and password
 | 
						|
    ##########################################
 | 
						|
    while (my ($hcp,$hash) = each(%nodehash) ) {   
 | 
						|
        my @cred;
 | 
						|
        if ($request->{hcp} && ($request->{hcp} eq "hmc" )) {
 | 
						|
            @cred = xCAT::PPCdb::credentials( $hcp, $request->{hcp} );
 | 
						|
        } else {
 | 
						|
            @cred = xCAT::PPCdb::credentials( $hcp, $request->{hwtype} );
 | 
						|
        }
 | 
						|
            $request->{$hcp}{cred} = \@cred;
 | 
						|
    } 
 | 
						|
    ##########################################
 | 
						|
    # Group the nodes - we will fork one 
 | 
						|
    # process per nodegroup array element. 
 | 
						|
    ##########################################
 | 
						|
 | 
						|
    ##########################################
 | 
						|
    # These commands are grouped on an
 | 
						|
    # LPAR-by-LPAR basis - fork one process
 | 
						|
    # per LPAR.  
 | 
						|
    ##########################################
 | 
						|
    if ( ($method =~ /^(getmacs)$/ && exists( $request->{opt}->{D} )) || ($method =~ /^(rnetboot)$/) ) {
 | 
						|
        while (my ($hcp,$hash) = each(%nodehash) ) {    
 | 
						|
            @nodegroup = ();
 | 
						|
            while (my ($mtms,$h) = each(%$hash) ) {
 | 
						|
                while (my ($lpar,$d) = each(%$h)) {
 | 
						|
                    push @$d, $lpar;
 | 
						|
 | 
						|
                    ##########################
 | 
						|
                    # Save network info
 | 
						|
                    ##########################
 | 
						|
                    if ( $method =~ /^rnetboot$/ ) {
 | 
						|
                        push @$d, $netwk->{$lpar}; 
 | 
						|
                    }
 | 
						|
                    push @nodegroup,[$hcp,$d]; 
 | 
						|
                }
 | 
						|
            }
 | 
						|
            $hcpgroup{$hcp}{'nodegroup'} = [@nodegroup];
 | 
						|
            $hcpgroup{$hcp}{'count'} = $#nodegroup + 1;
 | 
						|
            $hcpgroup{$hcp}{'runprocess'} = 0;
 | 
						|
            $hcpgroup{$hcp}{'index'} = 0;
 | 
						|
        }
 | 
						|
        return( \%hcpgroup );
 | 
						|
    }
 | 
						|
 | 
						|
    elsif ( $method =~ /^(getmacs)$/ && exists( $request->{opt}->{arp} ) ) {
 | 
						|
        return( $noderange );
 | 
						|
    }
 | 
						|
 | 
						|
    ##########################################
 | 
						|
    # Power control commands are grouped 
 | 
						|
    # by CEC which is the smallest entity 
 | 
						|
    # that commands can be sent to in parallel.  
 | 
						|
    # If commands are sent in parallel to a
 | 
						|
    # single CEC, the CEC itself will serialize 
 | 
						|
    # them - fork one process per CEC.
 | 
						|
    ##########################################
 | 
						|
    elsif ( $method =~ /^powercmd/ || $method =~ /^renergy/ ) {
 | 
						|
        while (my ($hcp,$hash) = each(%nodehash) ) {    
 | 
						|
            while (my ($mtms,$h) = each(%$hash) ) {    
 | 
						|
                push @nodegroup,[$hcp,$h]; 
 | 
						|
            }
 | 
						|
        }
 | 
						|
        return( \@nodegroup );
 | 
						|
    }
 | 
						|
    ##########################################
 | 
						|
    # All other commands are grouped by
 | 
						|
    # hardware control point - fork one
 | 
						|
    # process per hardware control point.
 | 
						|
    ##########################################
 | 
						|
    while (my ($hcp,$hash) = each(%nodehash) ) {    
 | 
						|
        push @nodegroup,[$hcp,$hash]; 
 | 
						|
    }
 | 
						|
    return( \@nodegroup );
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
##########################################################################
 | 
						|
# Finds attributes for given node is various databases 
 | 
						|
##########################################################################
 | 
						|
sub resolve_netwk {
 | 
						|
 | 
						|
    my $request   = shift;
 | 
						|
    my $noderange = shift;
 | 
						|
    my %nethash   = xCAT::DBobjUtils->getNetwkInfo( $noderange );
 | 
						|
    my $tab       = xCAT::Table->new( 'mac' );
 | 
						|
    my %result    = ();
 | 
						|
    my $ip;
 | 
						|
 | 
						|
    #####################################
 | 
						|
    # Network attributes undefined 
 | 
						|
    #####################################
 | 
						|
    if ( !%nethash ) {
 | 
						|
        send_msg( $request,1,sprintf( $errmsg{NODE_UNDEF}, "networks" ));
 | 
						|
        return undef;
 | 
						|
    }
 | 
						|
    #####################################
 | 
						|
    # mac database undefined
 | 
						|
    #####################################
 | 
						|
    if ( !defined( $tab )) {
 | 
						|
        send_msg( $request, 1, sprintf( $errmsg{DB_UNDEF}, "mac" ));
 | 
						|
        return undef;
 | 
						|
    }
 | 
						|
 | 
						|
    foreach ( @$noderange ) {
 | 
						|
        #################################
 | 
						|
        # Get gateway (-G)
 | 
						|
        #################################
 | 
						|
        if ( !exists( $nethash{$_} )) {
 | 
						|
            my $msg = sprintf( "$_: $errmsg{NODE_UNDEF}", "networks");
 | 
						|
            send_msg( $request, 1, $msg );
 | 
						|
            next;
 | 
						|
        }
 | 
						|
        my $gateway = $nethash{$_}{gateway};
 | 
						|
        if ( !defined( $gateway )) {
 | 
						|
            my $msg = sprintf("$_: $errmsg{NO_ATTR}","gateway","networks");
 | 
						|
            send_msg( $request, 1, $msg );
 | 
						|
            next;
 | 
						|
        }
 | 
						|
        $ip = xCAT::Utils::toIP( $gateway );
 | 
						|
        if ( @$ip[0] != 0 ) {
 | 
						|
            send_msg( $request, 1, "$_: Cannot resolve '$gateway'" );
 | 
						|
            next;  
 | 
						|
        }
 | 
						|
        my $gateway_ip = @$ip[1];
 | 
						|
 | 
						|
        #################################
 | 
						|
        # Get server (-S)
 | 
						|
        #################################
 | 
						|
        my $server = xCAT::Utils->GetMasterNodeName( $_ );
 | 
						|
        if ( $server == 1 ) {
 | 
						|
            send_msg( $request, 1, "$_: Unable to identify master" );
 | 
						|
            next;
 | 
						|
        }
 | 
						|
        $ip = xCAT::Utils::toIP( $server );
 | 
						|
        if ( @$ip[0] != 0 ) {
 | 
						|
            send_msg( $request, 1, "$_: Cannot resolve '$server'" );
 | 
						|
            next;  
 | 
						|
        }
 | 
						|
        my $server_ip = @$ip[1];
 | 
						|
 | 
						|
        #################################
 | 
						|
        # Get client (-C)
 | 
						|
        #################################
 | 
						|
        $ip = xCAT::Utils::toIP( $_ ); 
 | 
						|
        if ( @$ip[0] != 0 ) {
 | 
						|
            send_msg( $request, 1, "$_: Cannot resolve '$_'" );
 | 
						|
            next;  
 | 
						|
        }
 | 
						|
        my $client_ip = @$ip[1];
 | 
						|
 | 
						|
        #################################
 | 
						|
        # Get mac-address (-m)
 | 
						|
        #################################
 | 
						|
        my ($ent) = $tab->getNodeAttribs( $_, ['mac'] );
 | 
						|
        if ( !defined($ent) ) {
 | 
						|
            my $msg = sprintf( "$_: $errmsg{NO_ATTR}","mac","mac");
 | 
						|
            send_msg( $request, 1, $msg );
 | 
						|
            next;
 | 
						|
        }
 | 
						|
        #################################
 | 
						|
        # Save results 
 | 
						|
        #################################
 | 
						|
        $result{$_}{gateway} = $gateway_ip;
 | 
						|
        $result{$_}{server}  = $server_ip;
 | 
						|
        $result{$_}{client}  = $client_ip;
 | 
						|
        $result{$_}{mac}     = $ent->{mac};
 | 
						|
    }
 | 
						|
    return( \%result );
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
##########################################################################
 | 
						|
# Finds attributes for given node is various databases 
 | 
						|
##########################################################################
 | 
						|
sub resolve {
 | 
						|
 | 
						|
    my $request = shift;
 | 
						|
    my $node    = shift;
 | 
						|
    my $tabs    = shift;
 | 
						|
    my @attribs = qw(id pprofile parent hcp);
 | 
						|
    my @values  = ();
 | 
						|
 | 
						|
    #################################
 | 
						|
    # Get node type 
 | 
						|
    #################################
 | 
						|
    my $ent = $tabs->{nodetype}->getNodeAttribs($node,[qw(nodetype node)]);
 | 
						|
    if ( !defined( $ent )) {
 | 
						|
        return( sprintf( $errmsg{NODE_UNDEF}, "nodetype" ));
 | 
						|
    }
 | 
						|
    #################################
 | 
						|
    # Check for type
 | 
						|
    #################################
 | 
						|
    if ( !exists( $ent->{nodetype} )) {
 | 
						|
        return( sprintf( $errmsg{NO_ATTR}, "nodetype","nodetype" ));
 | 
						|
    }
 | 
						|
    #################################
 | 
						|
    # Check for valid "type"
 | 
						|
    #################################
 | 
						|
    my ($type) = grep( 
 | 
						|
            /^$::NODETYPE_LPAR|$::NODETYPE_OSI|$::NODETYPE_BPA|$::NODETYPE_FSP$/, 
 | 
						|
            split /,/, $ent->{nodetype} );
 | 
						|
 | 
						|
    if ( !defined( $type )) {
 | 
						|
        return( "Invalid node type: $ent->{nodetype}" );
 | 
						|
    }
 | 
						|
    #################################
 | 
						|
    # Get attributes 
 | 
						|
    #################################
 | 
						|
    my ($att) = $tabs->{ppc}->getNodeAttribs( $node, \@attribs );
 | 
						|
 | 
						|
    if ( !defined( $att )) { 
 | 
						|
        return( sprintf( $errmsg{NODE_UNDEF}, "ppc" )); 
 | 
						|
    }
 | 
						|
    #################################
 | 
						|
    # Special lpar processing 
 | 
						|
    #################################
 | 
						|
    if ( $type =~ /^$::NODETYPE_OSI|$::NODETYPE_LPAR$/ ) {
 | 
						|
        $att->{bpa}  = 0;
 | 
						|
        $att->{type} = "lpar";
 | 
						|
        $att->{node} = $att->{parent};
 | 
						|
 | 
						|
        if ( !exists( $att->{parent} )) {
 | 
						|
            return( sprintf( $errmsg{NO_ATTR}, "parent", "ppc" )); 
 | 
						|
        }
 | 
						|
        #############################
 | 
						|
        # Get BPA (if any)
 | 
						|
        #############################
 | 
						|
        if (( $request->{command} eq "rvitals" ) &&
 | 
						|
                ( $request->{method}  =~ /^all|temp$/ )) { 
 | 
						|
            my ($ent) = $tabs->{ppc}->getNodeAttribs( $att->{parent},['parent']);
 | 
						|
 | 
						|
            #############################
 | 
						|
            # Find MTMS in vpd database 
 | 
						|
            #############################
 | 
						|
            if (( defined( $ent )) && exists( $ent->{parent} )) {
 | 
						|
                my @attrs = qw(mtm serial);
 | 
						|
                my ($vpd) = $tabs->{vpd}->getNodeAttribs($ent->{parent},\@attrs);
 | 
						|
 | 
						|
                ########################
 | 
						|
                # Verify attributes
 | 
						|
                ########################
 | 
						|
                foreach ( @attrs ) {
 | 
						|
                    if ( !defined( $vpd ) || !exists( $vpd->{$_} )) {
 | 
						|
                        return( sprintf( $errmsg{NO_UNDEF}, $_, "vpd", $ent->{parent} ));
 | 
						|
                    }
 | 
						|
                }
 | 
						|
                $att->{bpa} = "$vpd->{mtm}*$vpd->{serial}";
 | 
						|
            }
 | 
						|
        }
 | 
						|
    }
 | 
						|
    #################################
 | 
						|
    # Optional and N/A fields 
 | 
						|
    #################################
 | 
						|
    elsif ( $type =~ /^$::NODETYPE_FSP$/ ) {
 | 
						|
        $att->{pprofile} = 0;
 | 
						|
        $att->{id}       = 0;
 | 
						|
        $att->{fsp}      = 0;
 | 
						|
        $att->{node}     = $node;
 | 
						|
        $att->{type}     = $type;
 | 
						|
        $att->{parent}   = exists($att->{parent}) ? $att->{parent} : 0;
 | 
						|
        $att->{bpa}      = $att->{parent};
 | 
						|
    }
 | 
						|
    elsif ( $type =~ /^$::NODETYPE_BPA$/ ) {
 | 
						|
        $att->{pprofile} = 0;
 | 
						|
        $att->{id}       = 0;
 | 
						|
        $att->{bpa}      = 0;
 | 
						|
        $att->{parent}   = 0;
 | 
						|
        $att->{fsp}      = 0;
 | 
						|
        $att->{node}     = $node;
 | 
						|
        $att->{type}     = $type;
 | 
						|
    }
 | 
						|
    #################################
 | 
						|
    # Find MTMS in vpd database 
 | 
						|
    #################################
 | 
						|
    my @attrs = qw(mtm serial);
 | 
						|
    my ($vpd) = $tabs->{vpd}->getNodeAttribs($att->{node}, \@attrs );
 | 
						|
 | 
						|
    if ( !defined( $vpd )) {
 | 
						|
        return( sprintf( $errmsg{NODE_UNDEF}, "vpd: ($att->{node})" )); 
 | 
						|
    }
 | 
						|
    ################################
 | 
						|
    # Verify both vpd attributes
 | 
						|
    ################################
 | 
						|
    foreach ( @attrs ) {
 | 
						|
        if ( !exists( $vpd->{$_} )) {
 | 
						|
            return( sprintf( $errmsg{NO_ATTR}, $_, "vpd: ($att->{node})" ));
 | 
						|
        }
 | 
						|
    }
 | 
						|
    $att->{fsp} = "$vpd->{mtm}*$vpd->{serial}";
 | 
						|
 | 
						|
    #################################
 | 
						|
    # Verify required attributes
 | 
						|
    #################################
 | 
						|
    foreach my $at ( @attribs ) {
 | 
						|
        if ( !exists( $att->{$at} )) {
 | 
						|
            return( sprintf( $errmsg{NO_ATTR}, $at, "ppc" ));
 | 
						|
        } 
 | 
						|
    }
 | 
						|
    #################################
 | 
						|
    # Build array of data 
 | 
						|
    #################################
 | 
						|
    foreach ( qw(id pprofile fsp hcp type bpa) ) {
 | 
						|
        push @values, $att->{$_};
 | 
						|
    }
 | 
						|
    return( \@values );
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
 | 
						|
##########################################################################
 | 
						|
# Forks a process to run the ssh command
 | 
						|
##########################################################################
 | 
						|
sub fork_cmd {
 | 
						|
 | 
						|
    my $host    = shift;
 | 
						|
    my $nodes   = shift;
 | 
						|
    my $request = shift;
 | 
						|
 | 
						|
    #######################################
 | 
						|
    # Pipe childs output back to parent
 | 
						|
    #######################################
 | 
						|
    my $parent;
 | 
						|
    my $child;
 | 
						|
    pipe $parent, $child;
 | 
						|
    my $pid = xCAT::Utils->xfork;
 | 
						|
 | 
						|
    if ( !defined($pid) ) {
 | 
						|
        ###################################
 | 
						|
        # Fork error
 | 
						|
        ###################################
 | 
						|
        send_msg( $request, 1, "Fork error: $!" );
 | 
						|
        return undef;
 | 
						|
    }
 | 
						|
    elsif ( $pid == 0 ) {
 | 
						|
        ###################################
 | 
						|
        # Child process
 | 
						|
        ###################################
 | 
						|
        close( $parent );
 | 
						|
        $request->{pipe} = $child;
 | 
						|
 | 
						|
        invoke_cmd( $host, $nodes, $request );
 | 
						|
        exit(0);
 | 
						|
    }
 | 
						|
    else {
 | 
						|
        ###################################
 | 
						|
        # Parent process
 | 
						|
        ###################################
 | 
						|
        close( $child );
 | 
						|
        return( $parent, $pid );
 | 
						|
    }
 | 
						|
    return(0);
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
##########################################################################
 | 
						|
# Run the command, process the response, and send to parent
 | 
						|
##########################################################################
 | 
						|
sub invoke_cmd {
 | 
						|
 | 
						|
    my $host    = shift;
 | 
						|
    my $nodes   = shift;
 | 
						|
    my $request = shift;
 | 
						|
    my $hwtype  = $request->{hwtype};
 | 
						|
    my $verbose = $request->{verbose};
 | 
						|
    my $cmd     = $request->{command};
 | 
						|
    my $power   = $request->{hcp};
 | 
						|
    my @exp;
 | 
						|
    my $verbose_log;
 | 
						|
    my @outhash;
 | 
						|
 | 
						|
    ########################################
 | 
						|
    # If the request command is renergy, just
 | 
						|
    # uses the xCAT CIM Client to handle it
 | 
						|
    ########################################
 | 
						|
    if ( $request->{command} eq "renergy" ) {
 | 
						|
        my $result = &runcmd($request, $host, $nodes);
 | 
						|
 | 
						|
        ########################################
 | 
						|
        # Format and send back to parent
 | 
						|
        ########################################
 | 
						|
        foreach my $line ( @$result ) {
 | 
						|
            my %output;
 | 
						|
            $output{node}->[0]->{name}->[0] = @$line[0];
 | 
						|
            $output{node}->[0]->{data}->[0]->{contents}->[0] = @$line[1];
 | 
						|
            $output{errorcode} = @$line[2];
 | 
						|
            push @outhash, \%output;
 | 
						|
        }
 | 
						|
        my $out = $request->{pipe};
 | 
						|
        print $out freeze( [@outhash] );
 | 
						|
        print $out "\nENDOFFREEZE6sK4ci\n";
 | 
						|
 | 
						|
        return;
 | 
						|
    }
 | 
						|
 | 
						|
    ########################################
 | 
						|
    # Direct-attached FSP handler 
 | 
						|
    ########################################
 | 
						|
    if ( ($power ne "hmc") && ( $hwtype eq "fsp" or $hwtype eq "bpa") && $request->{fsp_api} == 0) {
 | 
						|
 | 
						|
        ####################################
 | 
						|
        # Dynamically load FSP module
 | 
						|
        ####################################
 | 
						|
        eval { require xCAT::PPCfsp };
 | 
						|
        if ( $@ ) {
 | 
						|
            send_msg( $request, 1, $@ );
 | 
						|
            return;
 | 
						|
        }
 | 
						|
        my @exp = xCAT::PPCfsp::connect( $request, $host );
 | 
						|
 | 
						|
        ####################################
 | 
						|
        # Error connecting 
 | 
						|
        ####################################
 | 
						|
        if ( ref($exp[0]) ne "LWP::UserAgent" ) {
 | 
						|
            send_msg( $request, 1, $exp[0] );
 | 
						|
            return;
 | 
						|
        }
 | 
						|
        my $result = xCAT::PPCfsp::handler( $host, $request, \@exp );
 | 
						|
 | 
						|
        ####################################
 | 
						|
        # Output verbose Perl::LWP 
 | 
						|
        ####################################
 | 
						|
        if ( $verbose ) {
 | 
						|
            $verbose_log = $exp[3];
 | 
						|
 | 
						|
            my %output;
 | 
						|
            $output{data} = [$$verbose_log];
 | 
						|
            unshift @$result, \%output;
 | 
						|
        }
 | 
						|
        my $out = $request->{pipe};
 | 
						|
        print $out freeze( $result );
 | 
						|
        print $out "\nENDOFFREEZE6sK4ci\n";
 | 
						|
        return;
 | 
						|
    }
 | 
						|
 | 
						|
    ########################################
 | 
						|
    # HMC and IVM-managed handler
 | 
						|
    # Connect to list of remote servers
 | 
						|
    ########################################
 | 
						|
   if (  $request->{fsp_api} == 0 ) { 
 | 
						|
       foreach ( split /,/, $host ) {
 | 
						|
           if ( $power ne "hmc" ) {
 | 
						|
               @exp = xCAT::PPCcli::connect( $request, $hwtype, $_ );
 | 
						|
           } else {
 | 
						|
               @exp = xCAT::PPCcli::connect( $request, $power, $_);
 | 
						|
           }
 | 
						|
           ####################################
 | 
						|
           # Successfully connected 
 | 
						|
           ####################################
 | 
						|
           if ( ref($exp[0]) eq "Expect" ) {
 | 
						|
              last;
 | 
						|
           }
 | 
						|
       }
 | 
						|
    
 | 
						|
       ########################################
 | 
						|
       # Error connecting 
 | 
						|
       ########################################
 | 
						|
       if ( ref($exp[0]) ne "Expect" ) {
 | 
						|
           send_msg( $request, 1, $exp[0] );
 | 
						|
           return;
 | 
						|
       }
 | 
						|
    }
 | 
						|
 | 
						|
    ########################################
 | 
						|
    # Process specific command 
 | 
						|
    ########################################
 | 
						|
    my $result = runcmd( $request, $nodes, \@exp );
 | 
						|
 | 
						|
    ########################################
 | 
						|
    # Close connection to remote server
 | 
						|
    ########################################
 | 
						|
    if(  $request->{fsp_api} == 0 ) {
 | 
						|
        xCAT::PPCcli::disconnect( \@exp );
 | 
						|
    }
 | 
						|
 | 
						|
    ########################################
 | 
						|
    # Get verbose Expect output
 | 
						|
    ########################################
 | 
						|
    if ( $verbose ) {
 | 
						|
        $verbose_log = $exp[6];
 | 
						|
    }
 | 
						|
    ########################################
 | 
						|
    # Return error
 | 
						|
    ######################################## 
 | 
						|
    if ( ref($result) ne 'ARRAY' ) {
 | 
						|
        send_msg( $request, 1, $$verbose_log.$result );
 | 
						|
        return;
 | 
						|
    }
 | 
						|
    ########################################
 | 
						|
    # Prepend verbose output 
 | 
						|
    ########################################
 | 
						|
    if ( defined( $verbose_log )) {
 | 
						|
        my %output;
 | 
						|
        $output{data} = [$$verbose_log];
 | 
						|
        push @outhash, \%output;
 | 
						|
    }
 | 
						|
    ########################################
 | 
						|
    # Send result back to parent process
 | 
						|
    ########################################
 | 
						|
    if ( @$result[0] eq "FORMATDATA6sK4ci" ) {
 | 
						|
        my $out = $request->{pipe};
 | 
						|
 | 
						|
        push @outhash, @$result[1];
 | 
						|
        print $out freeze( [@outhash] );
 | 
						|
        print $out "\nENDOFFREEZE6sK4ci\n";
 | 
						|
        return;
 | 
						|
    }
 | 
						|
    ########################################
 | 
						|
    # Format and send back to parent
 | 
						|
    ########################################
 | 
						|
    foreach ( @$result ) {
 | 
						|
        my %output;
 | 
						|
        $output{node}->[0]->{name}->[0] = @$_[0];
 | 
						|
        $output{node}->[0]->{data}->[0]->{contents}->[0] = @$_[1];
 | 
						|
        $output{errorcode} = @$_[2];
 | 
						|
        push @outhash, \%output;
 | 
						|
    }
 | 
						|
    my $out = $request->{pipe};
 | 
						|
    print $out freeze( [@outhash] );
 | 
						|
    print $out "\nENDOFFREEZE6sK4ci\n";
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
##########################################################################
 | 
						|
# Run the command method specified
 | 
						|
##########################################################################
 | 
						|
sub runcmd {
 | 
						|
 | 
						|
    my $request = shift;
 | 
						|
    my $cmd     = $request->{command};
 | 
						|
    my $method  = $request->{method};
 | 
						|
    my $hwtype  = $request->{hwtype};
 | 
						|
    #my $modname = $modules{$cmd};
 | 
						|
    my $modname = $modules{$cmd}{$hwtype};
 | 
						|
 | 
						|
    ######################################
 | 
						|
    # Command not supported
 | 
						|
    ######################################
 | 
						|
    if ( !defined( $modname )) {
 | 
						|
        return( ["$cmd not a supported command by $hwtype method"] );
 | 
						|
    }   
 | 
						|
    ######################################
 | 
						|
    # Load specific module
 | 
						|
    ######################################
 | 
						|
    eval "require $modname";
 | 
						|
    if ( $@ ) {
 | 
						|
        return( [$@] );
 | 
						|
    }
 | 
						|
    ######################################
 | 
						|
    # Invoke method 
 | 
						|
    ######################################
 | 
						|
    no strict 'refs';
 | 
						|
    my $result = ${$modname."::"}{$method}->($request,@_);
 | 
						|
    use strict;
 | 
						|
 | 
						|
    return( $result );
 | 
						|
 | 
						|
}
 | 
						|
 | 
						|
##########################################################################
 | 
						|
# Pre-process request from xCat daemon. Send the request to the the service
 | 
						|
# nodes of the HCPs.
 | 
						|
##########################################################################
 | 
						|
sub preprocess_request {
 | 
						|
 | 
						|
    my $package  = shift;
 | 
						|
    my $req      = shift;
 | 
						|
    #if ($req->{_xcatdest}) { return [$req]; }    #exit if preprocessed
 | 
						|
    if ($req->{_xcatpreprocessed}->[0] == 1 ) { return [$req]; }
 | 
						|
    my $callback = shift;
 | 
						|
    my @requests;
 | 
						|
 | 
						|
    #####################################
 | 
						|
    # Parse arguments
 | 
						|
    #####################################
 | 
						|
    my $opt = parse_args($package, $req, $callback);
 | 
						|
    if ( ref($opt) eq 'ARRAY' ) 
 | 
						|
    {
 | 
						|
        send_msg( $req, 1, @$opt );
 | 
						|
        return(1);
 | 
						|
    }
 | 
						|
 | 
						|
    $req->{opt} = $opt;
 | 
						|
 | 
						|
    ####################################
 | 
						|
    # Get hwtype 
 | 
						|
    ####################################
 | 
						|
    $package =~ s/xCAT_plugin:://;
 | 
						|
 | 
						|
    ####################################
 | 
						|
    # Prompt for usage if needed and on MN
 | 
						|
    ####################################
 | 
						|
    my $noderange = $req->{node}; #Should be arrayref
 | 
						|
        my $command = $req->{command}->[0];
 | 
						|
    my $extrargs = $req->{arg};
 | 
						|
    my @exargs=($req->{arg});
 | 
						|
    if (ref($extrargs)) {
 | 
						|
        @exargs=@$extrargs;
 | 
						|
    }
 | 
						|
    if ($ENV{'XCATBYPASS'}){
 | 
						|
        my $usage_string=xCAT::Usage->parseCommand($command, @exargs);
 | 
						|
        if ($usage_string) {
 | 
						|
            $callback->({data=>[$usage_string]});
 | 
						|
            $req = {};
 | 
						|
            return ;
 | 
						|
        }
 | 
						|
        if (!$noderange) {
 | 
						|
            $usage_string="Missing noderange";
 | 
						|
            $callback->({data=>[$usage_string]});
 | 
						|
            $req = {};
 | 
						|
            return ;
 | 
						|
        }   
 | 
						|
    }   
 | 
						|
 | 
						|
 | 
						|
    ##################################################################
 | 
						|
    # get the HCPs for the LPARs in order to figure out which service 
 | 
						|
    # nodes to send the requests to
 | 
						|
    ###################################################################
 | 
						|
    my $hcptab_name = ($package eq "fsp" or $package eq "bpa") ? "ppcdirect" : "ppchcp";
 | 
						|
    my $hcptab  = xCAT::Table->new( $hcptab_name );
 | 
						|
    unless ($hcptab ) {
 | 
						|
        $callback->({data=>["Cannot open $hcptab_name table"]});
 | 
						|
        $req = {};
 | 
						|
        return;
 | 
						|
    }
 | 
						|
    # Check if each node is hcp 
 | 
						|
    my %hcp_hash=();
 | 
						|
    my @missednodes=();
 | 
						|
    foreach ( @$noderange ) {
 | 
						|
        my ($ent) = $hcptab->getAttribs( {hcp=>$_},"hcp" );
 | 
						|
        if ( !defined( $ent )) {
 | 
						|
            push @missednodes, $_;
 | 
						|
            next;
 | 
						|
        }
 | 
						|
        push @{$hcp_hash{$_}{nodes}}, $_;
 | 
						|
    }
 | 
						|
 | 
						|
    #check if the left-over nodes are lpars
 | 
						|
    if (@missednodes > 0) {
 | 
						|
        my $ppctab = xCAT::Table->new("ppc");
 | 
						|
        unless ($ppctab) { 
 | 
						|
            $callback->({data=>["Cannot open ppc table"]});
 | 
						|
            $req = {};
 | 
						|
            return;
 | 
						|
        }
 | 
						|
        foreach my $node (@missednodes) {
 | 
						|
            my $ent=$ppctab->getNodeAttribs($node,['hcp']);
 | 
						|
            if (defined($ent->{hcp})) { push @{$hcp_hash{$ent->{hcp}}{nodes}}, $node;}
 | 
						|
            else { 
 | 
						|
                $callback->({data=>["The node $node is neither a hcp nor an lpar"]});
 | 
						|
                $req = {};
 | 
						|
                return;
 | 
						|
            }
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    # find service nodes for the HCPs
 | 
						|
    # build an individual request for each service node
 | 
						|
    my $service  = "xcat";
 | 
						|
    my @hcps=keys(%hcp_hash);
 | 
						|
    my $sn = xCAT::Utils->get_ServiceNode(\@hcps, $service, "MN");
 | 
						|
 | 
						|
    # build each request for each service node
 | 
						|
    foreach my $snkey (keys %$sn)
 | 
						|
    {
 | 
						|
        #$callback->({data=>["The service node $snkey "]});
 | 
						|
        my $reqcopy = {%$req};
 | 
						|
        $reqcopy->{'_xcatdest'} = $snkey;
 | 
						|
        $reqcopy->{_xcatpreprocessed}->[0] = 1;
 | 
						|
        my $hcps1=$sn->{$snkey};
 | 
						|
        my @nodes=();
 | 
						|
        foreach (@$hcps1) { 
 | 
						|
            push @nodes, @{$hcp_hash{$_}{nodes}};
 | 
						|
        }
 | 
						|
        $reqcopy->{node} = \@nodes;
 | 
						|
        #print "nodes=@nodes\n";
 | 
						|
        push @requests, $reqcopy;
 | 
						|
    }
 | 
						|
    return \@requests;
 | 
						|
}
 | 
						|
####################################
 | 
						|
# Parse arguments
 | 
						|
####################################
 | 
						|
sub parse_args
 | 
						|
{
 | 
						|
    my $package = shift;
 | 
						|
    my $req     = shift;
 | 
						|
    my $callback= shift;
 | 
						|
    $package =~ s/xCAT_plugin:://;
 | 
						|
    #    if ( exists $req->{opt})
 | 
						|
    #    {
 | 
						|
    #        return $req->{opt};
 | 
						|
    #    }
 | 
						|
 | 
						|
    #################################
 | 
						|
    # To match the old logic
 | 
						|
    ##################################
 | 
						|
    my $command = $req->{command}->[0];
 | 
						|
    my $stdin   = $req->{stdin}->[0];
 | 
						|
    $req->{command}  = $command;
 | 
						|
    $req->{stdin}    = $stdin; 
 | 
						|
    $req->{hwtype}   = $package; 
 | 
						|
    $req->{callback} = $callback; 
 | 
						|
    $req->{method}   = "parse_args";
 | 
						|
 | 
						|
    my $opt = runcmd( $req);
 | 
						|
 | 
						|
    $req->{command} = [ $command];
 | 
						|
    $req->{stdin}   = [ $stdin];
 | 
						|
    return $opt;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
##########################################################################
 | 
						|
# Process request from xCat daemon
 | 
						|
##########################################################################
 | 
						|
sub process_request {
 | 
						|
 | 
						|
    my $package  = shift;
 | 
						|
    my $req      = shift;
 | 
						|
    my $callback = shift;
 | 
						|
    my $subreq      = shift;
 | 
						|
 | 
						|
    ####################################
 | 
						|
    # Get hwtype 
 | 
						|
    ####################################
 | 
						|
    $package =~ s/xCAT_plugin:://;
 | 
						|
 | 
						|
    ####################################
 | 
						|
    # Build hash to pass around 
 | 
						|
    ####################################
 | 
						|
    my $request = {%$req};
 | 
						|
    $request->{command} = $req->{command}->[0];
 | 
						|
    $request->{stdin}   = $req->{stdin}->[0]; 
 | 
						|
#    $request->{hwtype}  = $package;
 | 
						|
    $request->{callback}= $callback;
 | 
						|
    $request->{subreq}  = $subreq;
 | 
						|
    #########################
 | 
						|
    #This is a special case for rspconfig and mkhwconn, 
 | 
						|
    #we shouldn't set hwtype as$package. and reserved for other commands.
 | 
						|
    #probably for all HW ctrl commands it still true?
 | 
						|
    #########################
 | 
						|
    if($request->{command} ne "rspconfig" and 
 | 
						|
        $request->{command} ne "mkhwconn") {
 | 
						|
        $request->{hwtype}  = $package;
 | 
						|
    }
 | 
						|
 | 
						|
    ####################################
 | 
						|
    # Option -V for verbose output
 | 
						|
    ####################################
 | 
						|
    if ( exists( $request->{opt}->{V} )) {
 | 
						|
        $request->{verbose} = 1;
 | 
						|
    }
 | 
						|
    ####################################
 | 
						|
    # Process remote command
 | 
						|
    ####################################
 | 
						|
    process_command( $request );
 | 
						|
}
 | 
						|
 | 
						|
##########################################################################
 | 
						|
# connect hmc via ssh and execute remote command
 | 
						|
##########################################################################
 | 
						|
sub sshcmds_on_hmc
 | 
						|
{
 | 
						|
    my $ip = shift;
 | 
						|
    my $user = shift;
 | 
						|
    my $password = shift;
 | 
						|
    my @cmds = @_;
 | 
						|
 | 
						|
    my %handled;
 | 
						|
    my @data;
 | 
						|
    my @exp;
 | 
						|
    for my $cmd (@cmds)
 | 
						|
    {
 | 
						|
        if ( $cmd =~ /(.+?)=(.*)/)
 | 
						|
        {
 | 
						|
            my ($command,$value) = ($1,$2);
 | 
						|
            $handled{$command} = $value;
 | 
						|
        }
 | 
						|
    }
 | 
						|
    my %request = (
 | 
						|
            ppcretry => 1,
 | 
						|
            verbose  => 0,
 | 
						|
            ppcmaxp    => 64,
 | 
						|
            ppctimeout => 0,
 | 
						|
            fsptimeout => 0,
 | 
						|
            ppcretry   => 3,
 | 
						|
            maxssh     => 8 
 | 
						|
 | 
						|
            );
 | 
						|
 | 
						|
    my $valid_ip;
 | 
						|
    foreach my $individual_ip ( split /,/, $ip ) {
 | 
						|
        ################################
 | 
						|
        # Get userid and password 
 | 
						|
        ################################
 | 
						|
        my @cred = xCAT::PPCdb::credentials( $individual_ip, "hmc" );
 | 
						|
        $request{$individual_ip}{cred} = \@cred;
 | 
						|
 | 
						|
        @exp = xCAT::PPCcli::connect( \%request, 'hmc', $individual_ip);
 | 
						|
        ####################################
 | 
						|
        # Successfully connected 
 | 
						|
        ####################################
 | 
						|
        if ( ref($exp[0]) eq "Expect" ) {
 | 
						|
            $valid_ip = $individual_ip;
 | 
						|
            last;
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    ########################################
 | 
						|
    # Error connecting 
 | 
						|
    ########################################
 | 
						|
    if ( ref($exp[0]) ne "Expect" ) {
 | 
						|
        return ([1,@cmds]);
 | 
						|
    }
 | 
						|
    ########################################
 | 
						|
    # Process specific command 
 | 
						|
    ########################################
 | 
						|
    for my $cmd ( keys %handled)
 | 
						|
    {
 | 
						|
        my $result;
 | 
						|
        if ($cmd eq 'network_reset')
 | 
						|
        {
 | 
						|
            $result = xCAT::PPCcli::network_reset( \@exp, $valid_ip, $handled{$cmd});
 | 
						|
            my $RC = shift( @$result);
 | 
						|
        }
 | 
						|
        push @data, @$result[0]; 
 | 
						|
    }
 | 
						|
    ########################################
 | 
						|
    # Close connection to remote server
 | 
						|
    ########################################
 | 
						|
    xCAT::PPCcli::disconnect( \@exp );
 | 
						|
 | 
						|
    return ([0, undef, \@data]);
 | 
						|
}
 | 
						|
 | 
						|
##########################################################################
 | 
						|
# logon asm and update configuration
 | 
						|
##########################################################################
 | 
						|
sub updconf_in_asm
 | 
						|
{
 | 
						|
    my $ip = shift;
 | 
						|
    my $target_dev = shift;
 | 
						|
    my @cmds = @_;
 | 
						|
 | 
						|
    eval { require xCAT::PPCfsp };
 | 
						|
    if ( $@ ) {
 | 
						|
        return ([1,@cmds]);
 | 
						|
    }
 | 
						|
 | 
						|
    my %handled;
 | 
						|
    for my $cmd (@cmds)
 | 
						|
    {
 | 
						|
        if ( $cmd =~ /(.+?)=(.*)/)
 | 
						|
        {
 | 
						|
            my ($command,$value) = ($1,$2);
 | 
						|
            $handled{$command} = $value;
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    my %request = (
 | 
						|
            ppcretry    => 1,
 | 
						|
            verbose     => 0,
 | 
						|
            ppcmaxp     => 64,
 | 
						|
            ppctimeout  => 0,
 | 
						|
            fsptimeout  => 0,
 | 
						|
            ppcretry    => 3,
 | 
						|
            maxssh      => 8,
 | 
						|
            arg         => \@cmds,
 | 
						|
            method      => \%handled,
 | 
						|
            command     => 'rspconfig',
 | 
						|
            hwtype      => lc($target_dev->{'type'}),
 | 
						|
            );
 | 
						|
 | 
						|
    my $valid_ip;
 | 
						|
    my @exp;
 | 
						|
    foreach my $individual_ip ( split /,/, $ip ) {
 | 
						|
        ################################
 | 
						|
        # Get userid and password 
 | 
						|
        ################################
 | 
						|
        my @cred = xCAT::PPCdb::credentials( $individual_ip, lc($target_dev->{'type'}));
 | 
						|
        $request{$individual_ip}{cred} = \@cred;
 | 
						|
        $request{node} = [$individual_ip];  
 | 
						|
 | 
						|
        @exp = xCAT::PPCfsp::connect(\%request, $individual_ip);
 | 
						|
        ####################################
 | 
						|
        # Successfully connected 
 | 
						|
        ####################################
 | 
						|
        if ( ref($exp[0]) eq "LWP::UserAgent" ) {
 | 
						|
            $valid_ip = $individual_ip;
 | 
						|
            last;
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    ####################################
 | 
						|
    # Error connecting 
 | 
						|
    ####################################
 | 
						|
    if ( ref($exp[0]) ne "LWP::UserAgent" ) {
 | 
						|
        return ([1,@cmds]);
 | 
						|
    }
 | 
						|
    my $result = xCAT::PPCfsp::handler( $valid_ip, \%request, \@exp );
 | 
						|
    my $RC = shift( @$result);
 | 
						|
    my @data;
 | 
						|
    push @data, @$result[0];
 | 
						|
 | 
						|
    return ([0, undef, \@data]);
 | 
						|
}
 | 
						|
 | 
						|
sub check_fsp_api
 | 
						|
{
 | 
						|
    my $request = shift;
 | 
						|
    
 | 
						|
#    my $fsp_api = "/opt/xcat/sbin/fsp-api";
 | 
						|
    my $fsp_api    = ($::XCATROOT) ? "$::XCATROOT/sbin/fsp-api" : "/opt/xcat/sbin/fsp-api";
 | 
						|
    my $libfsp  = "/usr/lib/libfsp.a";
 | 
						|
#    my $libfsp  = "/opt/xcat/lib/libfsp.a";
 | 
						|
#    my $libfsp    = ($::XCATROOT) ? "$::XCATROOT/lib/libfsp.a" : "/opt/xcat/lib/libfsp.a";
 | 
						|
#    my $hw_svr  = "/opt/csm/csmbin/hdwr_svr";
 | 
						|
    
 | 
						|
    my $msg = ();
 | 
						|
#    if((-e $fsp_api) && (-x $fsp_api)&& (-e $libfsp) && (-e $hw_svr)) {
 | 
						|
    if((-e $fsp_api) && (-x $fsp_api)&& (-e $libfsp)) {
 | 
						|
    	return 0;
 | 
						|
    }
 | 
						|
    
 | 
						|
    return -1;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
 | 
						|
1;
 | 
						|
 |