mirror of
				https://github.com/xcat2/xcat-core.git
				synced 2025-11-04 05:12:30 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			2006 lines
		
	
	
		
			63 KiB
		
	
	
	
		
			Perl
		
	
	
		
			Executable File
		
	
	
	
	
			
		
		
	
	
			2006 lines
		
	
	
		
			63 KiB
		
	
	
	
		
			Perl
		
	
	
		
			Executable File
		
	
	
	
	
#!/usr/bin/env perl
 | 
						|
#
 | 
						|
# © Copyright 2009 Hewlett-Packard Development Company, L.P.
 | 
						|
# EPL license http://www.eclipse.org/legal/epl-v10.html
 | 
						|
#
 | 
						|
# Revision history:
 | 
						|
#   July, 2010    vallard@sumavi.com comments added.
 | 
						|
#   August, 2009	blade.pm adapted to generate hpblade.pm
 | 
						|
#
 | 
						|
package xCAT_plugin::hpblade;
 | 
						|
 | 
						|
BEGIN
 | 
						|
{
 | 
						|
    $::XCATROOT = $ENV{'XCATROOT'} ? $ENV{'XCATROOT'} : '/opt/xcat';
 | 
						|
}
 | 
						|
use lib "$::XCATROOT/lib/perl";
 | 
						|
 | 
						|
use strict;
 | 
						|
use xCAT::Table;
 | 
						|
use xCAT::Utils;
 | 
						|
use xCAT::TableUtils;
 | 
						|
use xCAT::ServiceNodeUtils;
 | 
						|
use xCAT::Usage;
 | 
						|
use IO::Socket;
 | 
						|
use Thread 'yield';
 | 
						|
use Storable qw(freeze thaw);
 | 
						|
use XML::Simple;
 | 
						|
use Net::SSLeay qw(die_now die_if_ssl_error);
 | 
						|
 | 
						|
 | 
						|
use Data::Dumper;
 | 
						|
use POSIX "WNOHANG";
 | 
						|
use Getopt::Long;
 | 
						|
 | 
						|
#use xCAT::hpoa;	# require this dynamically below instead
 | 
						|
 | 
						|
sub handled_commands {
 | 
						|
    return {
 | 
						|
        findme         => 'blade',
 | 
						|
        getmacs        => 'nodehm:getmac,mgt',
 | 
						|
        rscan          => 'nodehm:mgt',
 | 
						|
        rpower         => 'nodehm:power,mgt',
 | 
						|
        gethpbladecons => 'hpblade',
 | 
						|
        getrvidparms   => 'nodehm:mgt',
 | 
						|
        rvitals        => 'nodehm:mgt',
 | 
						|
        rinv           => 'nodehm:mgt',
 | 
						|
        rbeacon        => 'nodehm:mgt',
 | 
						|
        rspreset       => 'nodehm:mgt',
 | 
						|
        rspconfig      => 'nodehm:mgt',
 | 
						|
        rbootseq       => 'nodehm:mgt',
 | 
						|
        reventlog      => 'nodehm:mgt',
 | 
						|
        switchblade    => 'nodehm:mgt',
 | 
						|
    };
 | 
						|
}
 | 
						|
 | 
						|
my $hpoa;
 | 
						|
my $activeOABay;
 | 
						|
my $slot;
 | 
						|
my ($username, $password);
 | 
						|
my %mm_comm_pids;
 | 
						|
my %macmap;             #Store responses from rinv for discovery
 | 
						|
my $macmaptimestamp;    #reflect freshness of cache
 | 
						|
my %oahash;
 | 
						|
my $curn;
 | 
						|
my $oa;
 | 
						|
my $getBladeStatusResponse; # Make this a global here so we can re-use the result
 | 
						|
my $status_noop = "XXXno-opXXX";
 | 
						|
my $eventHash;
 | 
						|
my $globalDebug = 0;
 | 
						|
my $ctx;
 | 
						|
my @cfgtext;
 | 
						|
 | 
						|
my %bootdevices = (
 | 
						|
    0 => 'IPL_NO_OP',
 | 
						|
    1 => 'CD',
 | 
						|
    2 => 'FLOPPY',
 | 
						|
    3 => 'USB',
 | 
						|
    4 => 'HDD',
 | 
						|
    5 => 'PXE_NIC1',
 | 
						|
    6 => 'PXE_NIC2',
 | 
						|
    7 => 'PXE_NIC3',
 | 
						|
    8 => 'PXE_NIC4'
 | 
						|
);
 | 
						|
 | 
						|
my %bootnumbers = (
 | 
						|
    'none'     => 0,
 | 
						|
    'c'        => 1,
 | 
						|
    'cd'       => 1,
 | 
						|
    'dvd'      => 1,
 | 
						|
    'cdrom'    => 1,
 | 
						|
    'dvdrom'   => 1,
 | 
						|
    'f'        => 2,
 | 
						|
    'floppy'   => 2,
 | 
						|
    'usb'      => 3,
 | 
						|
    'usbflash' => 3,
 | 
						|
    'flash'    => 3,
 | 
						|
    'h'        => 4,
 | 
						|
    'hd'       => 4,
 | 
						|
    'hdd'      => 4,
 | 
						|
    'hd0'      => 4,
 | 
						|
    'harddisk' => 4,
 | 
						|
    'eth0'     => 5,
 | 
						|
    'nic1'     => 5,
 | 
						|
    'net1'     => 5,
 | 
						|
    'net'      => 5,
 | 
						|
    'n'        => 5,
 | 
						|
    'pxe_nic1' => 5,
 | 
						|
    'eth1'     => 6,
 | 
						|
    'nic2'     => 6,
 | 
						|
    'net2'     => 6,
 | 
						|
    'pxe_nic2' => 6,
 | 
						|
    'eth2'     => 7,
 | 
						|
    'nic3'     => 7,
 | 
						|
    'net3'     => 7,
 | 
						|
    'pxe_nic3' => 7,
 | 
						|
    'eth3'     => 8,
 | 
						|
    'nic4'     => 8,
 | 
						|
    'net4'     => 8,
 | 
						|
    'pxe_nic4' => 8
 | 
						|
);
 | 
						|
 | 
						|
my @rscan_attribs = qw(nodetype name id mtm serial mpa groups mgt);
 | 
						|
my @rscan_header  = (
 | 
						|
    [ "type",          "%-8s" ],
 | 
						|
    [ "name",          "" ],
 | 
						|
    [ "id",            "%-8s" ],
 | 
						|
    [ "type-model",    "%-12s" ],
 | 
						|
    [ "serial-number", "%-15s" ],
 | 
						|
    [ "address",       "%s\n" ]);
 | 
						|
 | 
						|
sub waitforack {
 | 
						|
    my $sock   = shift;
 | 
						|
    my $select = new IO::Select;
 | 
						|
    $select->add($sock);
 | 
						|
    my $str;
 | 
						|
    if ($select->can_read(10)) { # Continue after 10 seconds, even if not acked...
 | 
						|
        if ($str = <$sock>) {
 | 
						|
        } else {
 | 
						|
            $select->remove($sock);    #Block until parent acks data
 | 
						|
        }
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
# Login to the OA using credentials found in the database.
 | 
						|
sub oaLogin {
 | 
						|
    my $oaName = shift;
 | 
						|
    my $result = "";
 | 
						|
    my $hopa   = "";
 | 
						|
    my $errHash;
 | 
						|
 | 
						|
    # we need to get the info on the OA. If the specfied OA is NOT the
 | 
						|
    # ACTIVE OA then we return failure because we can't get the desired
 | 
						|
    # info from a STANDBY OA.
 | 
						|
 | 
						|
    my ($username, $passwd, $encinfo);
 | 
						|
 | 
						|
    my $mpatab = xCAT::Table->new('mpa');
 | 
						|
    my $ent;
 | 
						|
    if (defined($mpatab)) {
 | 
						|
        ($ent) = $mpatab->getAttribs({ 'mpa' => $oaName }, 'username', 'password');
 | 
						|
        if (defined($ent->{password})) { $password = $ent->{password}; }
 | 
						|
        if (defined($ent->{username})) { $username = $ent->{username}; }
 | 
						|
    }
 | 
						|
 | 
						|
 | 
						|
    $hpoa = xCAT::hpoa->new('oaAddress' => $oaName);
 | 
						|
    my $loginResponse = $hpoa->userLogIn('username' => $username, 'password' => $password);
 | 
						|
    if ($loginResponse->fault) {
 | 
						|
        $errHash = $loginResponse->fault;
 | 
						|
        print Dumper($errHash);
 | 
						|
        $result = $loginResponse->oaErrorText;
 | 
						|
        if ($loginResponse->fault) {
 | 
						|
            return (1, "Error on login attempt");
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    my $response = $hpoa->getEnclosureInfo();
 | 
						|
    if ($response->fault) {
 | 
						|
        return (1, "Error on get Enclosure Info call");
 | 
						|
    }
 | 
						|
    my $numOABays = $response->result->{oaBays};
 | 
						|
 | 
						|
    # OK We now know how many oaBays we have in this enclosure. Ask the OAs in each bay
 | 
						|
    # if they are active. If they are not, then leave since we can't get what we want
 | 
						|
    # from a standby OA
 | 
						|
    $activeOABay = 0;
 | 
						|
 | 
						|
    for (my $oaBay = 1 ; $oaBay <= $numOABays ; $oaBay++) {
 | 
						|
        $response = $hpoa->getOaInfo(bayNumber => $oaBay);
 | 
						|
        if (!defined $response->result() || $response->result()->{oaRole} eq "OA_ABSENT" ||
 | 
						|
            $response->result->{youAreHere} eq "false") {
 | 
						|
 | 
						|
            # either there is no OA here or this is not the one I am currently
 | 
						|
            # communicating with
 | 
						|
            next;
 | 
						|
        } elsif ($response->result->{youAreHere} eq "true") {
 | 
						|
            $activeOABay = $oaBay;
 | 
						|
            last;
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    if (!$activeOABay) {
 | 
						|
        return (1, "Cannot determine active OnBoard Administrator");
 | 
						|
    }
 | 
						|
 | 
						|
    # Last thing. Need to determine if this is the active OA. If not, then we
 | 
						|
    # just tell the caller, and they can make the decision as to what they want
 | 
						|
    # to do.
 | 
						|
 | 
						|
    $response = $hpoa->getOaStatus(bayNumber => $activeOABay);
 | 
						|
    if ($response->result->{oaRole} ne "ACTIVE") {
 | 
						|
        return (-1);
 | 
						|
    }
 | 
						|
 | 
						|
    return ($hpoa);
 | 
						|
}
 | 
						|
 | 
						|
sub oaLogout
 | 
						|
{
 | 
						|
    my $hpoa = shift;
 | 
						|
 | 
						|
    my $response = $hpoa->userLogOut();
 | 
						|
}
 | 
						|
 | 
						|
sub convertSlot {
 | 
						|
    my $origSlot = shift;
 | 
						|
 | 
						|
    if ($origSlot =~ /\D/) {
 | 
						|
        my $slotNum   = $origSlot;
 | 
						|
        my $slotAlpha = $slotNum;
 | 
						|
 | 
						|
        $slotNum =~ s/\D//;
 | 
						|
        $slotAlpha =~ s/\d//;
 | 
						|
 | 
						|
        my $side;
 | 
						|
        if ($slotAlpha eq "a" or $slotAlpha eq "A") {
 | 
						|
            $side = 1;
 | 
						|
        } elsif ($slotAlpha eq "b" or $slotAlpha eq "B") {
 | 
						|
            $side = 2;
 | 
						|
        } else {
 | 
						|
            return (-1);
 | 
						|
        }
 | 
						|
 | 
						|
        my $returnSlot = $side * 16 + $slotNum;
 | 
						|
        return ($returnSlot);
 | 
						|
    }
 | 
						|
    return ($origSlot);
 | 
						|
}
 | 
						|
 | 
						|
sub gethpbladecons {
 | 
						|
    my $noderange = shift;
 | 
						|
    my $callback  = shift;
 | 
						|
    my $mpatab    = xCAT::Table->new('mpa');
 | 
						|
    my $passtab   = xCAT::Table->new('passwd');
 | 
						|
    my $tmp;
 | 
						|
    my $user = "USERID";
 | 
						|
 | 
						|
    if ($passtab) {
 | 
						|
        ($tmp) = $passtab->getAttribs({ 'key' => 'blade' }, 'username');
 | 
						|
        if (defined($tmp)) {
 | 
						|
            $user = $tmp->{username};
 | 
						|
        }
 | 
						|
    }
 | 
						|
    my $mptab = xCAT::Table->new('mp');
 | 
						|
    my $mptabhash = $mptab->getNodesAttribs($noderange, [ 'mpa', 'id' ]);
 | 
						|
    foreach my $node (@$noderange) {
 | 
						|
        my $rsp = { node => [ { name => [$node] } ] };
 | 
						|
        my $ent = $mptabhash->{$node}->[0]; #$mptab->getNodeAttribs($node,['mpa', 'id']);
 | 
						|
        if (defined($ent->{mpa})) {
 | 
						|
            $oa   = $ent->{mpa};
 | 
						|
            $slot = convertSlot($ent->{id});
 | 
						|
            if ($slot == 0) {               # want to open a console on the OA
 | 
						|
                $rsp->{node}->[0]->{mm} = $oa;
 | 
						|
            } else {
 | 
						|
                $hpoa = oaLogin($oa);
 | 
						|
                my $mpInfoResp = $hpoa->getBladeMpInfo("bayNumber" => $slot);
 | 
						|
                if ($mpInfoResp->fault) {
 | 
						|
                    $rsp->{node}->[0]->{error}     = ["Error getting MP info"];
 | 
						|
                    $rsp->{node}->[0]->{errorcode} = [1];
 | 
						|
                    $callback->($rsp);
 | 
						|
                    next;
 | 
						|
                }
 | 
						|
                my $ipaddress = $mpInfoResp->result->{ipAddress};
 | 
						|
                $rsp->{node}->[0]->{mm} = $ipaddress;
 | 
						|
            }
 | 
						|
            ($tmp) = $mpatab->getAttribs({ 'mpa' => $oa }, 'username');
 | 
						|
            $user = [ $tmp->{username} ];
 | 
						|
            $rsp->{node}->[0]->{username} = $user;
 | 
						|
        } else {
 | 
						|
            $rsp->{node}->[0]->{error}     = ["no mpa defined"];
 | 
						|
            $rsp->{node}->[0]->{errorcode} = [1];
 | 
						|
            $callback->($rsp);
 | 
						|
            next;
 | 
						|
        }
 | 
						|
        if (defined($ent->{id})) {
 | 
						|
            $rsp->{node}->[0]->{slot} = $ent->{id};
 | 
						|
        } else {
 | 
						|
            $rsp->{node}->[0]->{slot} = "";
 | 
						|
        }
 | 
						|
 | 
						|
        $callback->($rsp);
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
sub preprocess_request {
 | 
						|
    my $request = shift;
 | 
						|
 | 
						|
    #if ($request->{_xcatdest}) { return [$request]; }    #exit if preprocessed
 | 
						|
    if ((defined($request->{_xcatpreprocessed}))
 | 
						|
        && ($request->{_xcatpreprocessed}->[0] == 1))
 | 
						|
    {
 | 
						|
        return [$request];
 | 
						|
    }
 | 
						|
 | 
						|
    my $callback = shift;
 | 
						|
    my @requests;
 | 
						|
 | 
						|
    #display usage statement if -h is present or no noderage is specified
 | 
						|
    my $noderange = $request->{node};           #Should be arrayref
 | 
						|
    my $command   = $request->{command}->[0];
 | 
						|
    my $extrargs  = $request->{arg};
 | 
						|
    my @exargs    = ($request->{arg});
 | 
						|
    if (ref($extrargs)) {
 | 
						|
        @exargs = @$extrargs;
 | 
						|
    }
 | 
						|
 | 
						|
    my $usage_string = xCAT::Usage->parseCommand($command, @exargs);
 | 
						|
    if ($usage_string) {
 | 
						|
        $callback->({ data => $usage_string });
 | 
						|
        $request = {};
 | 
						|
        return;
 | 
						|
    }
 | 
						|
 | 
						|
    if (!$noderange) {
 | 
						|
        $usage_string = xCAT::Usage->getUsage($command);
 | 
						|
        $callback->({ data => $usage_string });
 | 
						|
        $request = {};
 | 
						|
        return;
 | 
						|
    }
 | 
						|
 | 
						|
    # require SOAP::Lite for hpoa.pm so we can do it dynamically
 | 
						|
    my $soapsupport = eval { require SOAP::Lite; };
 | 
						|
    unless ($soapsupport) {    #Still no SOAP::Lite module
 | 
						|
        $callback->({ error => "SOAP::Lite perl module missing.  Install perl-SOAP-Lite before running HP blade commands.", errorcode => [42] });
 | 
						|
        return [];
 | 
						|
    }
 | 
						|
    require xCAT::hpoa;
 | 
						|
 | 
						|
    #get the MMs for the nodes for the nodes in order to figure out which service nodes to send the requests to
 | 
						|
    my $mptab = xCAT::Table->new("mp");
 | 
						|
    unless ($mptab) {
 | 
						|
        $callback->({ data => ["Cannot open mp table"] });
 | 
						|
        $request = {};
 | 
						|
        return;
 | 
						|
    }
 | 
						|
    my %mpa_hash = ();
 | 
						|
    my $mptabhash = $mptab->getNodesAttribs($noderange, [ 'mpa', 'id' ]);
 | 
						|
    if ($request->{command}->[0] eq "gethpbladecons") { #Can handle it here and now
 | 
						|
        gethpbladecons($noderange, $callback);
 | 
						|
        return ();
 | 
						|
    }
 | 
						|
 | 
						|
 | 
						|
    foreach my $node (@$noderange) {
 | 
						|
        my $ent = $mptabhash->{$node}->[0]; #$mptab->getNodeAttribs($node,['mpa', 'id']);
 | 
						|
        if (defined($ent->{mpa})) { push @{ $mpa_hash{ $ent->{mpa} }{nodes} }, $node; }
 | 
						|
        else {
 | 
						|
            $callback->({ data => ["no mpa defined for node $node"] });
 | 
						|
            $request = {};
 | 
						|
            return;
 | 
						|
        }
 | 
						|
        my $tempid;
 | 
						|
        if (defined($ent->{id})) {
 | 
						|
 | 
						|
            #if the ide is defined, we need to see if there is a letter embedded in it. If there is,
 | 
						|
            #then we need to convert the id to the correct slot
 | 
						|
            $tempid = convertSlot($ent->{id});
 | 
						|
            push @{ $mpa_hash{ $ent->{mpa} }{ids} }, $tempid;
 | 
						|
        } else {
 | 
						|
            push @{ $mpa_hash{ $ent->{mpa} }{ids} }, "";
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    # find service nodes for the MMs
 | 
						|
    # build an individual request for each service node
 | 
						|
    my $service = "xcat";
 | 
						|
    my @mms     = keys(%mpa_hash);
 | 
						|
    my $sn = xCAT::ServiceNodeUtils->get_ServiceNode(\@mms, $service, "MN");
 | 
						|
 | 
						|
    # build each request for each service node
 | 
						|
    foreach my $snkey (keys %$sn)
 | 
						|
    {
 | 
						|
        #print "snkey=$snkey\n";
 | 
						|
        my $reqcopy = {%$request};
 | 
						|
        $reqcopy->{'_xcatdest'} = $snkey;
 | 
						|
        my $mms1     = $sn->{$snkey};
 | 
						|
        my @moreinfo = ();
 | 
						|
        my @nodes    = ();
 | 
						|
        foreach (@$mms1) {
 | 
						|
            push @nodes, @{ $mpa_hash{$_}{nodes} };
 | 
						|
            push @moreinfo, "\[$_\]\[" . join(',', @{ $mpa_hash{$_}{nodes} }) . "\]\[" . join(',', @{ $mpa_hash{$_}{ids} }) . "\]";
 | 
						|
        }
 | 
						|
        $reqcopy->{node} = \@nodes;
 | 
						|
 | 
						|
        #print "nodes=@nodes\n";
 | 
						|
        $reqcopy->{moreinfo} = \@moreinfo;
 | 
						|
        push @requests, $reqcopy;
 | 
						|
    }
 | 
						|
    return \@requests;
 | 
						|
}
 | 
						|
 | 
						|
sub build_more_info {
 | 
						|
    my $noderange = shift;
 | 
						|
    my $callback  = shift;
 | 
						|
    my $mptab     = xCAT::Table->new("mp");
 | 
						|
    my @moreinfo  = ();
 | 
						|
    unless ($mptab) {
 | 
						|
        $callback->({ data => ["Cannot open mp table"] });
 | 
						|
        return @moreinfo;
 | 
						|
    }
 | 
						|
    my %mpa_hash = ();
 | 
						|
    my $mptabhash = $mptab->getNodesAttribs($noderange, [ 'mpa', 'id' ]);
 | 
						|
    foreach my $node (@$noderange) {
 | 
						|
        my $ent = $mptabhash->{$node}->[0]; #$mptab->getNodeAttribs($node,['mpa', 'id']);
 | 
						|
        if (defined($ent->{mpa})) { push @{ $mpa_hash{ $ent->{mpa} }{nodes} }, $node; }
 | 
						|
        else {
 | 
						|
            $callback->({ data => ["no mpa defined for node $node"] });
 | 
						|
            return @moreinfo;
 | 
						|
        }
 | 
						|
        if (defined($ent->{id})) { push @{ $mpa_hash{ $ent->{mpa} }{ids} }, $ent->{id}; }
 | 
						|
        else { push @{ $mpa_hash{ $ent->{mpa} }{ids} }, ""; }
 | 
						|
    }
 | 
						|
 | 
						|
    foreach (keys %mpa_hash) {
 | 
						|
        push @moreinfo, "\[$_\]\[" . join(',', @{ $mpa_hash{$_}{nodes} }) . "\]\[" . join(',', @{ $mpa_hash{$_}{ids} }) . "\]";
 | 
						|
 | 
						|
    }
 | 
						|
 | 
						|
    return \@moreinfo;
 | 
						|
}
 | 
						|
 | 
						|
sub handle_depend {
 | 
						|
    my $request  = shift;
 | 
						|
    my $callback = shift;
 | 
						|
    my $doreq    = shift;
 | 
						|
    my $dp       = shift;
 | 
						|
    my %node     = ();
 | 
						|
    my $dep      = @$dp[0];
 | 
						|
    my $dep_hash = @$dp[1];
 | 
						|
 | 
						|
    # send all dependencies (along w/ those dependent on nothing)
 | 
						|
    # build moreinfo for dependencies
 | 
						|
    my %mpa_hash = ();
 | 
						|
    my @moreinfo = ();
 | 
						|
    my $reqcopy  = {%$request};
 | 
						|
    my @nodes    = ();
 | 
						|
 | 
						|
    foreach my $node (keys %$dep) {
 | 
						|
        my $mpa = @{ $dep_hash->{$node} }[0];
 | 
						|
        push @{ $mpa_hash{$mpa}{nodes} }, $node;
 | 
						|
        push @{ $mpa_hash{$mpa}{ids} },   @{ $dep_hash->{$node} }[1];
 | 
						|
    }
 | 
						|
    foreach (keys %mpa_hash) {
 | 
						|
        push @nodes, @{ $mpa_hash{$_}{nodes} };
 | 
						|
        push @moreinfo, "\[$_\]\[" . join(',', @{ $mpa_hash{$_}{nodes} }) . "\]\[" . join(',', @{ $mpa_hash{$_}{ids} }) . "\]";
 | 
						|
    }
 | 
						|
    $reqcopy->{node}     = \@nodes;
 | 
						|
    $reqcopy->{moreinfo} = \@moreinfo;
 | 
						|
    process_request($reqcopy, $callback, $doreq, 1);
 | 
						|
 | 
						|
    my $start = Time::HiRes::gettimeofday();
 | 
						|
 | 
						|
    # build list of dependent nodes w/delays
 | 
						|
    while (my ($name, $h) = each(%$dep)) {
 | 
						|
        foreach (keys %$h) {
 | 
						|
            if ($h->{$_} =~ /(^\d+$)/) {
 | 
						|
                $node{$_} = $1 / 1000.0;
 | 
						|
            }
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    # send each dependent node as its delay expires
 | 
						|
    while (%node) {
 | 
						|
        my @noderange = ();
 | 
						|
        my $delay     = 0.1;
 | 
						|
        my $elapsed   = Time::HiRes::gettimeofday() - $start;
 | 
						|
 | 
						|
        # sort in ascending delay order
 | 
						|
        foreach (sort { $node{$a} <=> $node{$b} } keys %node) {
 | 
						|
            if ($elapsed < $node{$_}) {
 | 
						|
                $delay = $node{$_} - $elapsed;
 | 
						|
                last;
 | 
						|
            }
 | 
						|
            push @noderange, $_;
 | 
						|
            delete $node{$_};
 | 
						|
        }
 | 
						|
        if (@noderange) {
 | 
						|
            %mpa_hash = ();
 | 
						|
            foreach my $node (@noderange) {
 | 
						|
                my $mpa = @{ $dep_hash->{$node} }[0];
 | 
						|
                push @{ $mpa_hash{$mpa}{nodes} }, $node;
 | 
						|
                push @{ $mpa_hash{$mpa}{ids} },   @{ $dep_hash->{$node} }[1];
 | 
						|
            }
 | 
						|
 | 
						|
            @moreinfo = ();
 | 
						|
            $reqcopy  = {%$request};
 | 
						|
            @nodes    = ();
 | 
						|
 | 
						|
            foreach (keys %mpa_hash) {
 | 
						|
                push @nodes, @{ $mpa_hash{$_}{nodes} };
 | 
						|
                push @moreinfo, "\[$_\]\[" . join(',', @{ $mpa_hash{$_}{nodes} }) . "\]\[" . join(',', @{ $mpa_hash{$_}{ids} }) . "\]";
 | 
						|
            }
 | 
						|
            $reqcopy->{node}     = \@nodes;
 | 
						|
            $reqcopy->{moreinfo} = \@moreinfo;
 | 
						|
 | 
						|
            # clear global hash variable
 | 
						|
            %oahash = ();
 | 
						|
            process_request($reqcopy, $callback, $doreq, 1);
 | 
						|
        }
 | 
						|
 | 
						|
        # millisecond sleep
 | 
						|
        Time::HiRes::sleep($delay);
 | 
						|
    }
 | 
						|
    return 0;
 | 
						|
}
 | 
						|
 | 
						|
sub build_depend {
 | 
						|
    my $noderange = shift;
 | 
						|
    my $exargs    = shift;
 | 
						|
    my $depstab   = xCAT::Table->new('deps');
 | 
						|
    my $mptab     = xCAT::Table->new('mp');
 | 
						|
    my %dp        = ();
 | 
						|
    my %no_dp     = ();
 | 
						|
    my %mpa_hash;
 | 
						|
 | 
						|
    if (!defined($depstab)) {
 | 
						|
        return ([ \%dp ]);
 | 
						|
    }
 | 
						|
    unless ($mptab) {
 | 
						|
        return ("Cannot open mp table");
 | 
						|
    }
 | 
						|
 | 
						|
    my $depset = $depstab->getNodesAttribs($noderange, [qw(nodedep msdelay cmd)]);
 | 
						|
    foreach my $node (@$noderange) {
 | 
						|
        my $delay = 0;
 | 
						|
        my $dep;
 | 
						|
 | 
						|
        my @ent = @{ $depset->{$node} }; #$depstab->getNodeAttribs($node,[qw(nodedep msdelay cmd)]);
 | 
						|
        foreach my $h (@ent) {
 | 
						|
            if (grep(/^@$exargs[0]$/, split /,/, $h->{cmd})) {
 | 
						|
                if (exists($h->{nodedep})) { $dep   = $h->{nodedep}; }
 | 
						|
                if (exists($h->{msdelay})) { $delay = $h->{msdelay}; }
 | 
						|
                last;
 | 
						|
            }
 | 
						|
        }
 | 
						|
        if (!defined($dep)) {
 | 
						|
            $no_dp{$node} = 1;
 | 
						|
        }
 | 
						|
        else {
 | 
						|
            foreach my $n (split /,/, $dep) {
 | 
						|
                if (!grep(/^$n$/, @$noderange)) {
 | 
						|
                    return ("Missing dependency on command-line: $node -> $n");
 | 
						|
                } elsif ($n eq $node) {
 | 
						|
                    next;    # ignore multiple levels
 | 
						|
                }
 | 
						|
                $dp{$n}{$node} = $delay;
 | 
						|
            }
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    # if there are dependencies, add any non-dependent nodes
 | 
						|
    if (scalar(%dp)) {
 | 
						|
        foreach (keys %no_dp) {
 | 
						|
            if (!exists($dp{$_})) {
 | 
						|
                $dp{$_}{$_} = -1;
 | 
						|
            }
 | 
						|
        }
 | 
						|
 | 
						|
        # build hash of all nodes in preprocess_request() format
 | 
						|
        my @namelist = keys %dp;
 | 
						|
        my $mphash = $mptab->getNodesAttribs(\@namelist, [ 'mpa', 'id' ]);
 | 
						|
        while (my ($name, $h) = each(%dp)) {
 | 
						|
            my $ent = $mphash->{$name}->[0]; #$mptab->getNodeAttribs($name,['mpa', 'id']);
 | 
						|
            if (!defined($ent->{mpa})) {
 | 
						|
                return ("no mpa defined for node $name");
 | 
						|
            }
 | 
						|
            my $id = (defined($ent->{id})) ? $ent->{id} : "";
 | 
						|
            push @{ $mpa_hash{$name} }, $ent->{mpa};
 | 
						|
            push @{ $mpa_hash{$name} }, $id;
 | 
						|
 | 
						|
            @namelist = keys %$h;
 | 
						|
            my $mpsubhash = $mptab->getNodesAttribs(\@namelist, [ 'mpa', 'id' ]);
 | 
						|
            foreach (keys %$h) {
 | 
						|
                if ($h->{$_} =~ /(^\d+$)/) {
 | 
						|
                    my $ent = $mpsubhash->{$_}->[0]; #$mptab->getNodeAttribs($_,['mpa', 'id']);
 | 
						|
                    if (!defined($ent->{mpa})) {
 | 
						|
                        return ("no mpa defined for node $_");
 | 
						|
                    }
 | 
						|
                    my $id = (defined($ent->{id})) ? $ent->{id} : "";
 | 
						|
                    push @{ $mpa_hash{$_} }, $ent->{mpa};
 | 
						|
                    push @{ $mpa_hash{$_} }, $id;
 | 
						|
                }
 | 
						|
            }
 | 
						|
        }
 | 
						|
    }
 | 
						|
    return ([ \%dp, \%mpa_hash ]);
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
sub process_request {
 | 
						|
    $SIG{INT} = $SIG{TERM} = sub {
 | 
						|
        foreach (keys %mm_comm_pids) {
 | 
						|
            kill 2, $_;
 | 
						|
        }
 | 
						|
        exit 0;
 | 
						|
    };
 | 
						|
 | 
						|
    my $request   = shift;
 | 
						|
    my $callback  = shift;
 | 
						|
    my $doreq     = shift;
 | 
						|
    my $level     = shift;
 | 
						|
    my $noderange = $request->{node};
 | 
						|
    my $command   = $request->{command}->[0];
 | 
						|
    my @exargs;
 | 
						|
    unless ($command) {
 | 
						|
        return;    #Empty request
 | 
						|
    }
 | 
						|
 | 
						|
    # require SOAP::Lite for hpoa.pm so we can do it dynamically
 | 
						|
    my $soapsupport = eval { require SOAP::Lite; };
 | 
						|
    unless ($soapsupport) {    #Still no SOAP::Lite module
 | 
						|
        $callback->({ error => "SOAP::Lite perl module missing.  Install perl-SOAP-Lite before running HP blade commands.", errorcode => [42] });
 | 
						|
        return [];
 | 
						|
    }
 | 
						|
    require xCAT::hpoa;
 | 
						|
 | 
						|
    if (ref($request->{arg})) {
 | 
						|
        @exargs = @{ $request->{arg} };
 | 
						|
    } else {
 | 
						|
        @exargs = ($request->{arg});
 | 
						|
    }
 | 
						|
 | 
						|
    my $moreinfo;
 | 
						|
    if ($request->{moreinfo}) { $moreinfo = $request->{moreinfo}; }
 | 
						|
    else { $moreinfo = build_more_info($noderange, $callback); }
 | 
						|
 | 
						|
    #pdu commands will be handled in the pdu plugin
 | 
						|
    if ($command eq "rpower" and grep(/^pduon|pduoff|pdureset|pdustat$/, @exargs)) {
 | 
						|
        return;
 | 
						|
    }
 | 
						|
 | 
						|
    if ($command eq "rpower" and grep(/^on|off|boot|reset|cycle$/, @exargs)) {
 | 
						|
 | 
						|
        if (my ($index) = grep($exargs[$_] =~ /^--nodeps$/, 0 .. $#exargs)) {
 | 
						|
            splice(@exargs, $index, 1);
 | 
						|
        } else {
 | 
						|
 | 
						|
            # handles 1 level of dependencies only
 | 
						|
            if (!defined($level)) {
 | 
						|
                my $dep = build_depend($noderange, \@exargs);
 | 
						|
                if (ref($dep) ne 'ARRAY') {
 | 
						|
                    $callback->({ data => [$dep], errorcode => 1 });
 | 
						|
                    return;
 | 
						|
                }
 | 
						|
                if (scalar(%{ @$dep[0] })) {
 | 
						|
                    handle_depend($request, $callback, $doreq, $dep);
 | 
						|
                    return 0;
 | 
						|
                }
 | 
						|
            }
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    # only 1 node when changing textid to something other than '*'
 | 
						|
    if ($command eq "rspconfig" and grep(/^textid=[^*]/, @exargs)) {
 | 
						|
        if (@$noderange > 1) {
 | 
						|
            $callback->({ data => ["Single node required when changing textid"],
 | 
						|
                    errorcode => 1 });
 | 
						|
            return;
 | 
						|
        }
 | 
						|
    }
 | 
						|
    my $bladeuser = 'USERID';
 | 
						|
    my $bladepass = 'PASSW0RD';
 | 
						|
    my $blademaxp = 64;
 | 
						|
 | 
						|
    #my $sitetab = xCAT::Table->new('site');
 | 
						|
    my $mpatab = xCAT::Table->new('mpa');
 | 
						|
    my $mptab  = xCAT::Table->new('mp');
 | 
						|
    my $tmp;
 | 
						|
 | 
						|
    #if ($sitetab) {
 | 
						|
    #($tmp)=$sitetab->getAttribs({'key'=>'blademaxp'},'value');
 | 
						|
    my @entries = xCAT::TableUtils->get_site_attribute("blademaxp");
 | 
						|
    my $t_entry = $entries[0];
 | 
						|
    if (defined($t_entry)) { $blademaxp = $t_entry; }
 | 
						|
 | 
						|
    #}
 | 
						|
    my $passtab = xCAT::Table->new('passwd');
 | 
						|
    if ($passtab) {
 | 
						|
        ($tmp) = $passtab->getAttribs({ 'key' => 'blade' }, 'username', 'password');
 | 
						|
        if (defined($tmp)) {
 | 
						|
            $bladeuser = $tmp->{username};
 | 
						|
            $bladepass = $tmp->{password};
 | 
						|
        }
 | 
						|
    }
 | 
						|
    if ($request->{command}->[0] eq "findme") {
 | 
						|
        if (defined($request->{discoverymethod}) and defined($request->{discoverymethod}->[0]) and ($request->{discoverymethod}->[0] ne 'undef')) {
 | 
						|
 | 
						|
            # The findme request had been processed by other module, just return
 | 
						|
            return;
 | 
						|
        }
 | 
						|
        my $mptab = xCAT::Table->new("mp");
 | 
						|
        unless ($mptab) { return 2; }
 | 
						|
        my @bladents = $mptab->getAllNodeAttribs([qw(node)]);
 | 
						|
        my @blades;
 | 
						|
        foreach (@bladents) {
 | 
						|
            push @blades, $_->{node};
 | 
						|
        }
 | 
						|
        my %invreq;
 | 
						|
        $invreq{node}    = \@blades;
 | 
						|
        $invreq{arg}     = ['mac'];
 | 
						|
        $invreq{command} = ['rinv'];
 | 
						|
        my $mac;
 | 
						|
        my $ip = $request->{'_xcat_clientip'};
 | 
						|
        my $arptable;
 | 
						|
 | 
						|
        if (-x "/usr/sbin/arp") {
 | 
						|
            $arptable = `/usr/sbin/arp -n`;
 | 
						|
        }
 | 
						|
        else {
 | 
						|
            $arptable = `/sbin/arp -n`;
 | 
						|
        }
 | 
						|
        my @arpents = split /\n/, $arptable;
 | 
						|
        foreach (@arpents) {
 | 
						|
            if (m/^($ip)\s+\S+\s+(\S+)\s/) {
 | 
						|
                $mac = $2;
 | 
						|
                last;
 | 
						|
            }
 | 
						|
        }
 | 
						|
        unless ($mac) { return }
 | 
						|
 | 
						|
        #Only refresh the the cache when the request permits and no useful answer
 | 
						|
        if ($macmaptimestamp < (time() - 300)) { #after five minutes, invalidate cache
 | 
						|
            %macmap = ();
 | 
						|
        }
 | 
						|
 | 
						|
        unless ($request->{cacheonly}->[0] or $macmap{$mac} or $macmaptimestamp > (time() - 20)) { #do not refresh cache if requested not to, if it has an entry, or is recent
 | 
						|
            %macmap          = ();
 | 
						|
            $macmaptimestamp = time();
 | 
						|
            foreach (@{ preprocess_request(\%invreq, \&fillresps) }) {
 | 
						|
                %invreq = %$_;
 | 
						|
                process_request(\%invreq, \&fillresps);
 | 
						|
            }
 | 
						|
        }
 | 
						|
        unless ($macmap{$mac}) {
 | 
						|
            xCAT::MsgUtils->message("S", "xcat.discovery.hpblade: ($request->{_xcat_clientmac}->[0]) Warning: Could not find any nodes using hpblade-based discovery");
 | 
						|
            return 1;    #failure
 | 
						|
        }
 | 
						|
 | 
						|
        # The discovered command will update mac table, no need to update here
 | 
						|
        #my $mactab = xCAT::Table->new('mac',-create=>1);
 | 
						|
        #$mactab->setNodeAttribs($macmap{$mac},{mac=>$mac});
 | 
						|
        #$mactab->close();
 | 
						|
        #my %request = (
 | 
						|
        #  command => ['makedhcp'],
 | 
						|
        #  node => [$macmap{$mac}]
 | 
						|
        #  );
 | 
						|
        #$doreq->(\%request);
 | 
						|
        xCAT::MsgUtils->message("S", "xcat.discovery.hpblade: ($request->{_xcat_clientmac}->[0]) Found node: $macmap{$mac}");
 | 
						|
        my $req = {%$request};
 | 
						|
        $req->{command}   = ['discovered'];
 | 
						|
        $req->{noderange} = [ $macmap{$mac} ];
 | 
						|
        $doreq->($req);
 | 
						|
        %{$req} = ();    #Clear request. it is done
 | 
						|
                         #undef $mactab;
 | 
						|
        return 0;
 | 
						|
    }
 | 
						|
 | 
						|
 | 
						|
    my $children = 0;
 | 
						|
    $SIG{CHLD} = sub { my $cpid; while ($cpid = waitpid(-1, WNOHANG) > 0) { delete $mm_comm_pids{$cpid}; $children--; } };
 | 
						|
    my $inputs = new IO::Select;
 | 
						|
    foreach my $info (@$moreinfo) {
 | 
						|
        $info =~ /^\[(.*)\]\[(.*)\]\[(.*)\]/;
 | 
						|
        my $mpa   = $1;
 | 
						|
        my @nodes = split(',', $2);
 | 
						|
        my @ids   = split(',', $3);
 | 
						|
 | 
						|
        #print "mpa=$mpa, nodes=@nodes, ids=@ids\n";
 | 
						|
        my $user = $bladeuser;
 | 
						|
        my $pass = $bladepass;
 | 
						|
        my $ent;
 | 
						|
        if (defined($mpatab)) {
 | 
						|
            ($ent) = $mpatab->getAttribs({ 'mpa' => $mpa }, 'username', 'password');
 | 
						|
            if (defined($ent->{password})) { $pass = $ent->{password}; }
 | 
						|
            if (defined($ent->{username})) { $user = $ent->{username}; }
 | 
						|
        }
 | 
						|
        $oahash{$mpa}->{username} = $user;
 | 
						|
        $oahash{$mpa}->{password} = $pass;
 | 
						|
        for (my $i = 0 ; $i < @nodes ; $i++) {
 | 
						|
            my $node   = $nodes[$i];
 | 
						|
            my $nodeid = $ids[$i];
 | 
						|
            $oahash{$mpa}->{nodes}->{$node} = $nodeid;
 | 
						|
 | 
						|
 | 
						|
        }
 | 
						|
    }
 | 
						|
    my $sub_fds = new IO::Select;
 | 
						|
    foreach $oa (sort (keys %oahash)) {
 | 
						|
        while ($children > $blademaxp) { forward_data($callback, $sub_fds); }
 | 
						|
        $children++;
 | 
						|
        my $cfd;
 | 
						|
        my $pfd;
 | 
						|
        socketpair($pfd, $cfd, AF_UNIX, SOCK_STREAM, PF_UNSPEC) or die "socketpair: $!";
 | 
						|
        $cfd->autoflush(1);
 | 
						|
        $pfd->autoflush(1);
 | 
						|
        my $cpid = xCAT::Utils->xfork;
 | 
						|
        unless (defined($cpid)) { die "Fork error"; }
 | 
						|
 | 
						|
        unless ($cpid) {
 | 
						|
            close($cfd);
 | 
						|
            eval {
 | 
						|
                doblade($pfd, $oa, \%oahash, $command, -args => \@exargs);
 | 
						|
                exit(0);
 | 
						|
            };
 | 
						|
            if ($@) { die "$@"; }
 | 
						|
            die "blade plugin encountered a general error while communication with $oa";
 | 
						|
        }
 | 
						|
        $mm_comm_pids{$cpid} = 1;
 | 
						|
        close($pfd);
 | 
						|
        $sub_fds->add($cfd);
 | 
						|
    }
 | 
						|
    while ($sub_fds->count > 0 or $children > 0) {
 | 
						|
        forward_data($callback, $sub_fds);
 | 
						|
    }
 | 
						|
    while (forward_data($callback, $sub_fds)) { }
 | 
						|
}
 | 
						|
 | 
						|
my $IMPORT_SSH_KEY_HEADER = '
 | 
						|
<LOCFGVERSION="2.21"/>
 | 
						|
<RIBCL VERSION="2.0">
 | 
						|
<LOGIN USER_LOGIN="AdMiNnAmE" PASSWORD="PaSsWoRd">
 | 
						|
<RIB_INFO MODE="write">
 | 
						|
<IMPORT_SSH_KEY>
 | 
						|
-----BEGIN SSH KEY-----
 | 
						|
';
 | 
						|
 | 
						|
my $IMPORT_SSH_KEY_FOOTER = '
 | 
						|
-----END SSH KEY-----
 | 
						|
</IMPORT_SSH_KEY>
 | 
						|
</RIB_INFO>
 | 
						|
</LOGIN>
 | 
						|
</RIBCL>';
 | 
						|
 | 
						|
my $MOD_NETWORK_SETTINGS_HEADER = '
 | 
						|
<LOCFGVERSION="2.21"/>
 | 
						|
<RIBCL VERSION="2.0">
 | 
						|
<LOGIN USER_LOGIN="AdMiNnAmE" PASSWORD="PaSsWoRd">
 | 
						|
<RIB_INFO MODE="write">
 | 
						|
<MOD_NETWORK_SETTINGS>
 | 
						|
';
 | 
						|
 | 
						|
my $MOD_NETWORK_SETTINGS_FOOTER = '
 | 
						|
</MOD_NETWORK_SETTINGS>
 | 
						|
</RIB_INFO>
 | 
						|
<LOGIN>
 | 
						|
</RIBCL>';
 | 
						|
 | 
						|
my $GET_NETWORK_SETTINGS = '
 | 
						|
<LOCFGVERSION="2.21"/>
 | 
						|
<RIBCL VERSION="2.0">
 | 
						|
<LOGIN USER_LOGIN="AdMiNnAmE" PASSWORD="PaSsWoRd">
 | 
						|
<RIB_INFO MODE="read">
 | 
						|
<GET_NETWORK_SETTINGS/>
 | 
						|
</RIB_INFO>
 | 
						|
</LOGIN>
 | 
						|
</RIBCL>';
 | 
						|
 | 
						|
 | 
						|
Net::SSLeay::load_error_strings();
 | 
						|
Net::SSLeay::SSLeay_add_ssl_algorithms();
 | 
						|
Net::SSLeay::randomize();
 | 
						|
#
 | 
						|
# opens an ssl connection to port 443 of the passed host
 | 
						|
#
 | 
						|
sub openSSLconnection($)
 | 
						|
{
 | 
						|
    my $host = shift;
 | 
						|
    my ($ssl, $sin, $ip, $nip);
 | 
						|
    if (not $ip = inet_aton($host))
 | 
						|
    {
 | 
						|
        print "$host is a DNS Name, performing lookup\n" if $globalDebug;
 | 
						|
        $ip = gethostbyname($host) or die "ERROR: Host $host notfound. \n";
 | 
						|
    }
 | 
						|
    $nip = inet_ntoa($ip);
 | 
						|
 | 
						|
    #print STDERR "Connecting to $nip:443\n";
 | 
						|
    $sin = sockaddr_in(443, $ip);
 | 
						|
    socket(S, &AF_INET, &SOCK_STREAM, 0) or die "ERROR: socket: $!";
 | 
						|
    connect(S, $sin) or die "connect: $!";
 | 
						|
    $ctx = Net::SSLeay::CTX_new() or die_now("ERROR: Failed to create SSL_CTX $! ");
 | 
						|
 | 
						|
    Net::SSLeay::CTX_set_options($ctx, &Net::SSLeay::OP_ALL);
 | 
						|
    die_if_ssl_error("ERROR: ssl ctx set options");
 | 
						|
    $ssl = Net::SSLeay::new($ctx) or die_now("ERROR: Failed to create SSL $!");
 | 
						|
 | 
						|
    Net::SSLeay::set_fd($ssl, fileno(S));
 | 
						|
    Net::SSLeay::connect($ssl) and die_if_ssl_error("ERROR: ssl connect");
 | 
						|
 | 
						|
    #print STDERR 'SSL Connected ';
 | 
						|
    print 'Using Cipher: ' . Net::SSLeay::get_cipher($ssl) if $globalDebug;
 | 
						|
 | 
						|
    #print STDERR "\n\n";
 | 
						|
    return $ssl;
 | 
						|
}
 | 
						|
 | 
						|
sub closeSSLconnection($)
 | 
						|
{
 | 
						|
    my $ssl = shift;
 | 
						|
 | 
						|
    Net::SSLeay::free($ssl);    # Tear down connection
 | 
						|
    Net::SSLeay::CTX_free($ctx);
 | 
						|
    close S;
 | 
						|
}
 | 
						|
 | 
						|
# usage: sendscript(host, script)
 | 
						|
# sends the xmlscript script to host, returns reply
 | 
						|
sub sendScript($$)
 | 
						|
{
 | 
						|
    my $host   = shift;
 | 
						|
    my $script = shift;
 | 
						|
    my ($ssl, $reply, $lastreply, $res, $n);
 | 
						|
    $ssl = openSSLconnection($host);
 | 
						|
 | 
						|
    # write header
 | 
						|
    $n = Net::SSLeay::ssl_write_all($ssl, '<?xml version="1.0"?>' . "\r\n");
 | 
						|
    print "Wrote $n\n" if $globalDebug;
 | 
						|
    $n = Net::SSLeay::ssl_write_all($ssl, '<LOCFG version="2.21"/>' . "\r\n");
 | 
						|
    print "Wrote $n\n" if $globalDebug;
 | 
						|
 | 
						|
    # write script
 | 
						|
    $n = Net::SSLeay::ssl_write_all($ssl, $script);
 | 
						|
    print "Wrote $n\n$script\n" if $globalDebug;
 | 
						|
    $reply     = "";
 | 
						|
    $lastreply = "";
 | 
						|
    my $reply2return = "";
 | 
						|
  READLOOP:
 | 
						|
    while (1) {
 | 
						|
        $n++;
 | 
						|
        $lastreply = Net::SSLeay::read($ssl);
 | 
						|
        die_if_ssl_error("ERROR: ssl read");
 | 
						|
        if ($lastreply eq "") {
 | 
						|
            sleep(2);    # wait 2 sec for more text.
 | 
						|
            $lastreply = Net::SSLeay::read($ssl);
 | 
						|
            die_if_ssl_error("ERROR: ssl read");
 | 
						|
            last READLOOP if ($lastreply eq "");
 | 
						|
        }
 | 
						|
        $reply .= $lastreply;
 | 
						|
        print "lastreply  $lastreply \b" if $globalDebug;
 | 
						|
 | 
						|
        # Check response to see if a error was returned.
 | 
						|
        if ($lastreply =~ m/STATUS="(0x[0-9A-F]+)"[\s]+MESSAGE='(.*)'[\s]+\/>[\s]*(([\s]|.)*?)<\/RIBCL>/) {
 | 
						|
            if ($1 eq "0x0000") {
 | 
						|
 | 
						|
                #print STDERR "$3\n" if $3;
 | 
						|
            } else {
 | 
						|
                $reply2return = "ERROR: STATUS: $1, MESSAGE: $2";
 | 
						|
            }
 | 
						|
        }
 | 
						|
    }
 | 
						|
    print "READ: $lastreply\n" if $globalDebug;
 | 
						|
    if ($lastreply =~ m/STATUS="(0x[0-9A-F]+)"[\s]+MESSAGE='(.*)'[\s]+\/>[\s]*(([\s]|.)*?)<\/RIBCL>/) {
 | 
						|
        if ($1 eq "0x0000") {
 | 
						|
 | 
						|
            #Sprint STDERR "$3\n" if $3;
 | 
						|
        } else {
 | 
						|
            $reply2return = "ERROR: STATUS: $1, MESSAGE: $2";
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    closeSSLconnection($ssl);
 | 
						|
    return $reply2return;
 | 
						|
}
 | 
						|
 | 
						|
sub extractValue {
 | 
						|
    my $inputString = shift;
 | 
						|
    my $testString  = shift;
 | 
						|
 | 
						|
    $testString = "<" . "$testString" . " VALUE=";
 | 
						|
 | 
						|
    my $start = index($inputString, $testString) + length $testString;
 | 
						|
    my $end = index $inputString, "\"", ($start + 1);
 | 
						|
    return (substr($inputString, ($start + 1), ($end - $start - 1)));
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
 | 
						|
sub iloconfig {
 | 
						|
 | 
						|
    my $oa     = shift;
 | 
						|
    my $user   = shift;
 | 
						|
    my $pass   = shift;
 | 
						|
    my $node   = shift;
 | 
						|
    my $nodeid = shift;
 | 
						|
    my $parameter;
 | 
						|
    my $value;
 | 
						|
    my $assignment;
 | 
						|
    my $returncode = 0;
 | 
						|
    my $textid     = 0;
 | 
						|
    @cfgtext = ();
 | 
						|
 | 
						|
    # Before we get going, lets get the info on the MP (iLO)
 | 
						|
    $slot = convertSlot($nodeid);
 | 
						|
    my $mpInfoResp = $hpoa->getBladeMpInfo("bayNumber" => $slot);
 | 
						|
    if ($mpInfoResp->fault) {
 | 
						|
        my $errorText = "Error getting MP info";
 | 
						|
        next;
 | 
						|
    }
 | 
						|
    my $ipaddress = $mpInfoResp->result->{ipAddress};
 | 
						|
 | 
						|
    foreach $parameter (@_) {
 | 
						|
        $assignment = 0;
 | 
						|
        $value      = undef;
 | 
						|
        if ($parameter =~ /=/) {
 | 
						|
            $assignment = 1;
 | 
						|
            ($parameter, $value) = split /=/, $parameter, 2;
 | 
						|
        }
 | 
						|
        if ($parameter =~ /^sshcfg$/) {
 | 
						|
            my $fname = "/root/.ssh/id_dsa.pub";
 | 
						|
            if (!-s $fname) {
 | 
						|
 | 
						|
                # Key file specified does not exist. Error!
 | 
						|
                push @cfgtext, "rspconfig:key file does not exist";
 | 
						|
                next;
 | 
						|
            }
 | 
						|
            open(KEY, "$fname");
 | 
						|
            my $key = readline(KEY);
 | 
						|
            close(KEY);
 | 
						|
            my $script = "$IMPORT_SSH_KEY_HEADER" . "$key" . "$IMPORT_SSH_KEY_FOOTER";
 | 
						|
            $script =~ s/AdMiNnAmE/$user/;
 | 
						|
            $script =~ s/PaSsWoRd/$pass/;
 | 
						|
            my $reply = sendScript($ipaddress, $script);
 | 
						|
            push @cfgtext, $reply;
 | 
						|
            next;
 | 
						|
        }
 | 
						|
        if ($parameter =~ /^network$/) {
 | 
						|
            if ($value) {
 | 
						|
 | 
						|
                # If value is set, then the user wans us to set these values
 | 
						|
                my ($newip, $newhostname, $newgateway, $newmask) = split /,/, $value;
 | 
						|
                my $script = "$MOD_NETWORK_SETTINGS_HEADER";
 | 
						|
                $script = $script . "<IP_ADDRESS VALUE=\"$newip\"\/>" if ($newip);
 | 
						|
                $script = $script . "<GATEWAY_IP_ADDRESS VALUE=\"$newgateway\"\/>" if ($newgateway);
 | 
						|
                $script = $script . "<SUBNET_MASK VALUE=\"$newmask\"\/>" if ($newmask);
 | 
						|
                $script = $script . "$MOD_NETWORK_SETTINGS_FOOTER";
 | 
						|
                $script =~ s/AdMiNnAmE/$user/;
 | 
						|
                $script =~ s/PaSsWoRd/$pass/;
 | 
						|
                my $reply = sendScript($ipaddress, $script);
 | 
						|
                if ($newip)      { push @cfgtext, "iLO IP: $newip"; }
 | 
						|
                if ($newgateway) { push @cfgtext, "Gateway: $newgateway"; }
 | 
						|
                if ($newmask)    { push @cfgtext, "Subnet Mask: $newmask"; }
 | 
						|
                push @cfgtext, $reply;
 | 
						|
 | 
						|
            } else {
 | 
						|
                my $script = "$GET_NETWORK_SETTINGS";
 | 
						|
                $script =~ s/AdMiNnAmE/$user/;
 | 
						|
                $script =~ s/PaSsWoRd/$pass/;
 | 
						|
                my $reply = sendScript($ipaddress, $script);
 | 
						|
                my $readipaddress = extractValue($reply, "IP_ADDRESS");
 | 
						|
                my $gateway       = extractValue($reply, "GATEWAY_IP_ADDRESS");
 | 
						|
                my $netmask       = extractValue($reply, "SUBNET_MASK");
 | 
						|
                push @cfgtext, "iLO IP: $readipaddress";
 | 
						|
                push @cfgtext, "Gateway: $gateway";
 | 
						|
                push @cfgtext, "Subnet mask: $netmask";
 | 
						|
                push @cfgtext, $reply;
 | 
						|
            }
 | 
						|
        }
 | 
						|
    }
 | 
						|
    return 0, @cfgtext;
 | 
						|
}
 | 
						|
 | 
						|
sub getmacs
 | 
						|
{
 | 
						|
    (my $code, my @macs) = inv('mac');
 | 
						|
    my $mkey;
 | 
						|
    my $nic2Find;
 | 
						|
    my $nrtab = xCAT::Table->new('noderes');
 | 
						|
    if ($nrtab) {
 | 
						|
        my $nent = $nrtab->getNodeAttribs($curn, [ 'primarynic', 'installnic' ]);
 | 
						|
        if ($nent) {
 | 
						|
            if (defined $nent->{installnic}) {    #Prefer the install nic
 | 
						|
                $mkey = "installnic";
 | 
						|
            } elsif (defined $nent->{primarynic}) {  #see if primary nic was set
 | 
						|
                $mkey = "primarynic";
 | 
						|
            }
 | 
						|
            $nic2Find = $nent->{$mkey};
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    # We now have the nic2Find, so we need to convert this to the NIC format
 | 
						|
    # Strip away the "eth"
 | 
						|
    my $interface = $nic2Find;
 | 
						|
    $nic2Find =~ s/eth//;
 | 
						|
    my $numberPxeNic = $nic2Find + 1;
 | 
						|
    my $pxeNic       = "NIC " . $numberPxeNic;
 | 
						|
 | 
						|
    if ($code == 0) {
 | 
						|
        my $mac;
 | 
						|
        my @allmacs;
 | 
						|
        foreach my $macEntry (@macs) {
 | 
						|
            if ($macEntry =~ /MAC ADDRESS $pxeNic/) {
 | 
						|
                $mac = $macEntry;
 | 
						|
                $mac =~ s/MAC ADDRESS $pxeNic: //;
 | 
						|
                $mac = lc $mac;
 | 
						|
                last;
 | 
						|
            }
 | 
						|
        }
 | 
						|
        if (!$mac) {
 | 
						|
            return 1, "Unable to retrieve MAC address for interface $pxeNic from OnBoard Administrator";
 | 
						|
        }
 | 
						|
 | 
						|
        my $mactab = xCAT::Table->new('mac', -create => 1);
 | 
						|
        $mactab->setNodeAttribs($curn, { mac => $mac }, { interface => $interface });
 | 
						|
        $mactab->close;
 | 
						|
        return 0, ":mac.mac set to $mac";
 | 
						|
    } else {
 | 
						|
        return $code, $macs[0];
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
sub inv {
 | 
						|
    my @invitems;
 | 
						|
    my @output;
 | 
						|
    foreach (@_) {
 | 
						|
        push @invitems, split(/,/, $_);
 | 
						|
    }
 | 
						|
    my $item;
 | 
						|
    unless (scalar(@invitems)) {
 | 
						|
        @invitems = ("all");
 | 
						|
    }
 | 
						|
 | 
						|
    # Before going off to handle the items, issue a getBladeInfo, getBladeMpInfo, and getOaInfo
 | 
						|
    my $getBladeInfoResult = $hpoa->getBladeInfo("bayNumber" => $slot);
 | 
						|
    if ($getBladeInfoResult->fault) {
 | 
						|
        return (1, "getBladeInfo on node $curn failed");
 | 
						|
    }
 | 
						|
    my $getBladeMpInfoResult = $hpoa->getBladeMpInfo("bayNumber" => $slot);
 | 
						|
    if ($getBladeMpInfoResult->fault) {
 | 
						|
        return (1, "getBladeMpInfo on node $curn fault");
 | 
						|
    }
 | 
						|
    my $getOaInfoResult = $hpoa->getOaInfo("bayNumber" => $activeOABay);
 | 
						|
    if ($getOaInfoResult->fault) {
 | 
						|
        my $errHash = $getOaInfoResult->fault;
 | 
						|
        return (1, "getOaInfo failed");
 | 
						|
    }
 | 
						|
 | 
						|
    while (my $item = shift @invitems) {
 | 
						|
        if ($item =~ /^all/) {
 | 
						|
            push @invitems, (qw(mtm serial mac firm));
 | 
						|
            next;
 | 
						|
        }
 | 
						|
 | 
						|
        if ($item =~ /^firm/) {
 | 
						|
            push @invitems, (qw(bladerom mprom oarom));
 | 
						|
        }
 | 
						|
        if ($item =~ /^bladerom/) {
 | 
						|
            push @output, "BladeFW: " . $getBladeInfoResult->result->{romVersion};
 | 
						|
        }
 | 
						|
        if ($item =~ /^mprom/) {
 | 
						|
            push @output, "iLOFW: " . $getBladeMpInfoResult->result->{fwVersion};
 | 
						|
        }
 | 
						|
        if ($item =~ /~oarom/) {
 | 
						|
            push @output, "OA FW: " . $getOaInfoResult->result->{fwVersion};
 | 
						|
        }
 | 
						|
 | 
						|
        if ($item =~ /^model/ or $item =~ /^mtm/) {
 | 
						|
            push @output, "Machine Type/Model: " . $getBladeInfoResult->result->{partNumber};
 | 
						|
        }
 | 
						|
        if ($item =~ /^serial/) {
 | 
						|
            push @output, "Serial Number: " . $getBladeInfoResult->result->{serialNumber};
 | 
						|
        }
 | 
						|
        if ($item =~ /^mac/) {
 | 
						|
            my $numberOfNics = $getBladeInfoResult->result->{numberOfNics};
 | 
						|
            for (my $i = 0 ; $i < $numberOfNics ; $i++) {
 | 
						|
                my $mac = $getBladeInfoResult->result->{nics}->{bladeNicInfo}[$i]->{macAddress};
 | 
						|
                my $port = $getBladeInfoResult->result->{nics}->{bladeNicInfo}[$i]->{port};
 | 
						|
                push @output, "MAC ADDRESS " . $port . ": " . $mac;
 | 
						|
 | 
						|
                #push@output, "MAC Address ".($_+1).": ".$getBladeInfoResult->result->{nics}->{bladeNicInfo}[$i]->{macAddress};
 | 
						|
            }
 | 
						|
        }
 | 
						|
    }
 | 
						|
    return (0, @output);
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
sub CtoF {
 | 
						|
    my $Ctemp = shift;
 | 
						|
    return ((($Ctemp * 9) / 5) + 32);
 | 
						|
}
 | 
						|
 | 
						|
my %chassiswidevitals;
 | 
						|
 | 
						|
sub vitals {
 | 
						|
    my @output;
 | 
						|
    my $tmp;
 | 
						|
    my @vitems;
 | 
						|
 | 
						|
    if ($#_ == 0 && $_[0] eq '') { pop @_; push @_, "all" } #-- default is all if no argument given
 | 
						|
 | 
						|
    if (defined $slot and $slot > 0) {                      #-- blade query
 | 
						|
        foreach (@_) {
 | 
						|
            if ($_ eq 'all') {
 | 
						|
 | 
						|
                # push @vitems,qw(temp voltage wattage summary fan);
 | 
						|
                push @vitems, qw(cpu_temp memory_temp system_temp ambient_temp summary fanspeed);
 | 
						|
                push @vitems, qw(led power);
 | 
						|
            } elsif ($_ =~ '^led') {
 | 
						|
                push @vitems, qw(led);
 | 
						|
            } else {
 | 
						|
                push @vitems, split(/,/, $_);
 | 
						|
            }
 | 
						|
        }
 | 
						|
    } else {    #-- chassis query
 | 
						|
        foreach (@_) {
 | 
						|
            if ($_ eq 'all') {
 | 
						|
 | 
						|
                # push @vitems,qw(voltage wattage power summary);
 | 
						|
                push @vitems, qw(cpu_temp memory_temp system_temp ambient_temp summary fanspeed);
 | 
						|
 | 
						|
                # push @vitems,qw(errorled beaconled infoled templed);
 | 
						|
                push @vitems, qw(led power);
 | 
						|
            } elsif ($_ =~ '^led') {
 | 
						|
                push @vitems, qw(led);
 | 
						|
            } elsif ($_ =~ '^cool') {
 | 
						|
                push @vitems, qw(fanspeed);
 | 
						|
            } elsif ($_ =~ '^temp') {
 | 
						|
                push @vitems, qw(ambient_temp);
 | 
						|
            } else {
 | 
						|
                push @vitems, split(/,/, $_);
 | 
						|
            }
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    my @vitals;
 | 
						|
    if (defined $slot and $slot > 0) {    #-- querying some blade
 | 
						|
        if (grep /temp/, @vitems) {
 | 
						|
            my $tempResponse = $hpoa->getBladeThermalInfoArray("bayNumber" => $slot);
 | 
						|
 | 
						|
            if ($tempResponse->fault) {
 | 
						|
                push @output, "Request to get Temperature info on slot $slot failed";
 | 
						|
            }
 | 
						|
            elsif (!$tempResponse->result) {
 | 
						|
 | 
						|
                # If is the case then the temperature data is not yet available.
 | 
						|
                push @output, "Temperature data not available.";
 | 
						|
            } else {
 | 
						|
 | 
						|
                # We have data so go process it....
 | 
						|
                my @tempdata = $tempResponse->result->{bladeThermalInfo};
 | 
						|
                my $lastElement = $tempResponse->result->{bladeThermalInfo}[-1]->{sensorNumber};
 | 
						|
                if (grep /cpu_temp/, @vitems) {
 | 
						|
                    my $index = -1;
 | 
						|
                    do {
 | 
						|
                        $index++;
 | 
						|
                        if (grep /CPU/, $tempResponse->result->{bladeThermalInfo}[$index]->{description}) {
 | 
						|
                            my $Ctemp = $tempResponse->result->{bladeThermalInfo}[$index]->{temperatureC};
 | 
						|
                            my $desc = $tempResponse->result->{bladeThermalInfo}[$index]->{description};
 | 
						|
                            my $Ftemp = CtoF($Ctemp);
 | 
						|
                            push @output, "$desc Temperature: $Ctemp C \( $Ftemp F \)";
 | 
						|
                        }
 | 
						|
                    } until $tempResponse->result->{bladeThermalInfo}[$index]->{sensorNumber} eq $lastElement;
 | 
						|
                }
 | 
						|
                if (grep /memory_temp/, @vitems) {
 | 
						|
                    my $index = -1;
 | 
						|
                    do {
 | 
						|
                        $index++;
 | 
						|
                        if (grep /Memory/, $tempResponse->result->{bladeThermalInfo}[$index]->{description}) {
 | 
						|
                            my $Ctemp = $tempResponse->result->{bladeThermalInfo}[$index]->{temperatureC};
 | 
						|
                            my $desc = $tempResponse->result->{bladeThermalInfo}[$index]->{description};
 | 
						|
                            my $Ftemp = CtoF($Ctemp);
 | 
						|
                            push @output, "$desc Temperature: $Ctemp C \( $Ftemp F \)";
 | 
						|
                        }
 | 
						|
                    } until $tempResponse->result->{bladeThermalInfo}[$index]->{sensorNumber} eq $lastElement;
 | 
						|
                }
 | 
						|
                if (grep /system_temp/, @vitems) {
 | 
						|
                    my $index = -1;
 | 
						|
                    do {
 | 
						|
                        $index++;
 | 
						|
                        if (grep /System/, $tempResponse->result->{bladeThermalInfo}[$index]->{description}) {
 | 
						|
                            my $Ctemp = $tempResponse->result->{bladeThermalInfo}[$index]->{temperatureC};
 | 
						|
                            my $desc = $tempResponse->result->{bladeThermalInfo}[$index]->{description};
 | 
						|
                            my $Ftemp = CtoF($Ctemp);
 | 
						|
                            push @output, "$desc Temperature: $Ctemp C \( $Ftemp F \)";
 | 
						|
                        }
 | 
						|
                    } until $tempResponse->result->{bladeThermalInfo}[$index]->{sensorNumber} eq $lastElement;
 | 
						|
                }
 | 
						|
                if (grep /ambient_temp/, @vitems) {
 | 
						|
                    my $index = -1;
 | 
						|
                    do {
 | 
						|
                        $index++;
 | 
						|
                        if (grep /Ambient/, $tempResponse->result->{bladeThermalInfo}[$index]->{description}) {
 | 
						|
                            my $Ctemp = $tempResponse->result->{bladeThermalInfo}[$index]->{temperatureC};
 | 
						|
                            my $desc = $tempResponse->result->{bladeThermalInfo}[$index]->{description};
 | 
						|
                            my $Ftemp = CtoF($Ctemp);
 | 
						|
                            push @output, "$desc Temperature: $Ctemp C \( $Ftemp F \)";
 | 
						|
                        }
 | 
						|
                    } until $tempResponse->result->{bladeThermalInfo}[$index]->{sensorNumber} eq $lastElement;
 | 
						|
                }
 | 
						|
            }
 | 
						|
        }
 | 
						|
 | 
						|
        if (grep /fanspeed/, @vitems) {
 | 
						|
            my $fanInfoResponse = $hpoa->getFanInfo("bayNumber" => $slot);
 | 
						|
            if ($fanInfoResponse->fault) {
 | 
						|
                push @output, "Request to get Fan Info from slot $slot failed ";
 | 
						|
            } elsif (!$fanInfoResponse->result) {
 | 
						|
                push @output, "No Fan Information";
 | 
						|
            } else {
 | 
						|
                my $fanStatus  = $fanInfoResponse->result->{operationalStatus};
 | 
						|
                my $fanMax     = $fanInfoResponse->result->{maxFanSpeed};
 | 
						|
                my $fanCur     = $fanInfoResponse->result->{fanSpeed};
 | 
						|
                my $fanPercent = ($fanCur / $fanMax) * 100;
 | 
						|
                push @output, "Fan status: $fanStatus  Percent of max: $fanPercent\%";
 | 
						|
            }
 | 
						|
        }
 | 
						|
 | 
						|
        if (grep /led/, @vitems) {
 | 
						|
            my $currstat = $getBladeStatusResponse->result->{uid};
 | 
						|
 | 
						|
            if ($currstat eq "UID_ON") {
 | 
						|
                push @output, "Current UID Status On";
 | 
						|
            } elsif ($currstat eq "UID_OFF") {
 | 
						|
                push @output, "Current UID Status Off";
 | 
						|
            } elsif ($currstat eq "UID_BLINK") {
 | 
						|
                push @output, "Current UID Status Blinking";
 | 
						|
            }
 | 
						|
        }
 | 
						|
 | 
						|
        if (grep /power/, @vitems) {
 | 
						|
            my $currPowerStat = $getBladeStatusResponse->result->{powered};
 | 
						|
            if ($currPowerStat eq "POWER_ON") {
 | 
						|
                push @output, "Current Power Status On";
 | 
						|
            } elsif ($currPowerStat eq "POWER_OFF") {
 | 
						|
                push @output, "Current Power Status Off";
 | 
						|
            }
 | 
						|
        }
 | 
						|
    }
 | 
						|
    return (0, @output);
 | 
						|
}
 | 
						|
 | 
						|
sub buildEventHash {
 | 
						|
    my $logText       = shift;
 | 
						|
    my $eventLogFound = 0;
 | 
						|
    my $eventFound    = 0;
 | 
						|
    my $eventNumber   = 0;
 | 
						|
 | 
						|
    my @lines = split /^/, $logText;
 | 
						|
    foreach my $line (@lines) {
 | 
						|
        if (!$eventLogFound) {
 | 
						|
            if (!$line =~ m/EVENT_LOG/) {
 | 
						|
                next;
 | 
						|
            } elsif ($line =~ m/EVENT_LOG/) {
 | 
						|
                $eventLogFound = 1;
 | 
						|
                next;
 | 
						|
            }
 | 
						|
        }
 | 
						|
 | 
						|
        if (!$eventFound && $line =~ m/\<EVENT/) {
 | 
						|
            $eventFound = 1;
 | 
						|
            next;
 | 
						|
        } elsif ($eventFound && $line =~ m/\/\>/) {
 | 
						|
            $eventNumber++;
 | 
						|
            $eventFound = 0;
 | 
						|
            next;
 | 
						|
        }
 | 
						|
 | 
						|
        # We have a good line. Need to split it up and build the hash.
 | 
						|
        my ($desc, $value) = split /=/, $line;
 | 
						|
        for ($desc) {
 | 
						|
            s/^\s+//;
 | 
						|
            s/\s+$//;
 | 
						|
            s/\"//g;
 | 
						|
            s/\\n//;
 | 
						|
        }
 | 
						|
        for ($value) {
 | 
						|
            s/^\s+//;
 | 
						|
            s/\"//g;
 | 
						|
            s/\s+$//;
 | 
						|
            s/\\n//;
 | 
						|
        }
 | 
						|
        $eventHash->{event}->{$eventNumber}->{$desc} = $value;
 | 
						|
        next;
 | 
						|
    }
 | 
						|
    return $eventNumber;
 | 
						|
}
 | 
						|
 | 
						|
sub eventlog {
 | 
						|
    my $subcommand = shift;
 | 
						|
 | 
						|
    my @output;
 | 
						|
 | 
						|
    $subcommand = "all" if $subcommand eq "";
 | 
						|
 | 
						|
    if ($subcommand eq "all" or $subcommand =~ /\d+/) {
 | 
						|
        my $mpEventLogResponse = $hpoa->getBladeMpEventLog("bayNumber" => $slot, "maxsize" => 640000);
 | 
						|
        if ($mpEventLogResponse->fault) {
 | 
						|
            return (1, "Attempt to retrieve Event Log faulted");
 | 
						|
        }
 | 
						|
        my $logText   = $mpEventLogResponse->result->{logContents};
 | 
						|
        my $numEvents = buildEventHash($logText);
 | 
						|
 | 
						|
        my $recCount = 0;
 | 
						|
        $eventHash->{'event'} = {
 | 
						|
            map {
 | 
						|
                $recCount++ => $_->[1]
 | 
						|
              } sort {
 | 
						|
                $a->[0] <=> $b->[0]
 | 
						|
              } map {
 | 
						|
                (defined $_->{LAST_UPDATE} && $_->{LAST_UPDATE} ne '[NOT SET]')
 | 
						|
                  ? [ &extractDate($_->{LAST_UPDATE}), $_ ]
 | 
						|
                  : [ $_->{SELID}, $_ ]
 | 
						|
              } map {
 | 
						|
                $eventHash->{'event'}{$_}{SELID} = $_;
 | 
						|
                $eventHash->{'event'}{$_};
 | 
						|
              } grep {
 | 
						|
                defined $eventHash->{'event'}{$_}
 | 
						|
              } keys %{ $eventHash->{'event'} }
 | 
						|
        };
 | 
						|
 | 
						|
        my $limitEvents = ($subcommand eq "all" ? $recCount : $subcommand);
 | 
						|
 | 
						|
        for (my $index = 0 ; $index < $limitEvents ; $index++) {
 | 
						|
            --$recCount;
 | 
						|
 | 
						|
            my $class    = $eventHash->{event}->{$recCount}->{CLASS};
 | 
						|
            my $severity = $eventHash->{event}->{$recCount}->{SEVERITY};
 | 
						|
            my $dateTime = $eventHash->{event}->{$recCount}->{LAST_UPDATE};
 | 
						|
            my $desc     = $eventHash->{event}->{$recCount}->{DESCRIPTION};
 | 
						|
            unshift @output, "$class $severity:$dateTime $desc";
 | 
						|
        }
 | 
						|
        return (0, @output);
 | 
						|
    } elsif ($subcommand eq "clear") {
 | 
						|
        return (1, "Command not supported");
 | 
						|
    } else {
 | 
						|
        return (1, "Command '$subcommand' not supported");
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
sub rscan {
 | 
						|
    my $args = shift;
 | 
						|
    my @values;
 | 
						|
    my $result;
 | 
						|
    my %opt;
 | 
						|
 | 
						|
    @ARGV                     = @$args;
 | 
						|
    $Getopt::Long::ignorecase = 0;
 | 
						|
    Getopt::Long::Configure("bundling");
 | 
						|
 | 
						|
    local *usage = sub {
 | 
						|
        my $usage_string = xCAT::Usage->getUsage("rscan");
 | 
						|
        return (join('', ($_[0], $usage_string)));
 | 
						|
    };
 | 
						|
 | 
						|
    if (!GetOptions(\%opt, qw(V|Verbose w x z))) {
 | 
						|
        return (1, usage());
 | 
						|
    }
 | 
						|
    if (defined($ARGV[0])) {
 | 
						|
        return (1, usage("Invalid argument: @ARGV\n"));
 | 
						|
    }
 | 
						|
    if (exists($opt{x}) and exists($opt{z})) {
 | 
						|
        return (1, usage("-x and -z are mutually exclusive\n"));
 | 
						|
    }
 | 
						|
 | 
						|
    my $encInfo = $hpoa->getEnclosureInfo();
 | 
						|
    if ($encInfo->fault) {
 | 
						|
        return (1, "Attempt tp get enclosure information has failed");
 | 
						|
    }
 | 
						|
 | 
						|
    my $numBays = $encInfo->result->{bladeBays};
 | 
						|
    my $calcBladeBays = $numBays * 3;    # Need to worry aboyt casmir blades
 | 
						|
 | 
						|
    my $encName   = $encInfo->result->{enclosureName};
 | 
						|
    my $enctype   = $encInfo->result->{name};
 | 
						|
    my $encmodel  = $encInfo->result->{partNumber};
 | 
						|
    my $encserial = $encInfo->result->{serialNumber};
 | 
						|
 | 
						|
    push @values, join(",", "hpoa", $encName, 0, "$enctype-$encmodel", $encserial, $oa);
 | 
						|
    my $max = length($encName);
 | 
						|
 | 
						|
    for (my $i = 1 ; $i <= $calcBladeBays ; $i++) {
 | 
						|
        my $bayInfo = $hpoa->getBladeInfo("bayNumber" => $i);
 | 
						|
        if ($bayInfo->fault) {
 | 
						|
            return (1, "Attempt to get blade info from bay $i has failed");
 | 
						|
        }
 | 
						|
        if ($bayInfo->result->{presence} eq "ABSENT") {
 | 
						|
 | 
						|
            # no blade in the bya
 | 
						|
            next;
 | 
						|
        }
 | 
						|
 | 
						|
        my $name   = $bayInfo->result->{serverName};
 | 
						|
        my $bayNum = $i;
 | 
						|
        my $type   = $bayInfo->result->{bladeType};
 | 
						|
        my $model  = $bayInfo->result->{name};
 | 
						|
        my $serial = $bayInfo->result->{serialNumber};
 | 
						|
 | 
						|
        push @values, join(",", "hpblade", $name, $bayNum, "$type-$model", $serial, "");
 | 
						|
    }
 | 
						|
 | 
						|
    my $format = sprintf "%%-%ds", ($max + 2);
 | 
						|
    $rscan_header[1][1] = $format;
 | 
						|
 | 
						|
    if (exists($opt{x})) {
 | 
						|
        $result = rscan_xml($oa, \@values);
 | 
						|
    }
 | 
						|
    elsif (exists($opt{z})) {
 | 
						|
        $result = rscan_stanza($oa, \@values);
 | 
						|
    }
 | 
						|
    else {
 | 
						|
        foreach (@rscan_header) {
 | 
						|
            $result .= sprintf @$_[1], @$_[0];
 | 
						|
        }
 | 
						|
        foreach (@values) {
 | 
						|
            my @data = split /,/;
 | 
						|
            my $i    = 0;
 | 
						|
 | 
						|
            foreach (@rscan_header) {
 | 
						|
                $result .= sprintf @$_[1], $data[ $i++ ];
 | 
						|
            }
 | 
						|
        }
 | 
						|
    }
 | 
						|
    if (!exists($opt{w})) {
 | 
						|
        return (0, $result);
 | 
						|
    }
 | 
						|
    my @tabs = qw(mp nodehm nodelist);
 | 
						|
    my %db   = ();
 | 
						|
 | 
						|
    foreach (@tabs) {
 | 
						|
        $db{$_} = xCAT::Table->new($_, -create => 1, -autocommit => 0);
 | 
						|
        if (!$db{$_}) {
 | 
						|
            return (1, "Error opening '$_'");
 | 
						|
        }
 | 
						|
    }
 | 
						|
    foreach (@values) {
 | 
						|
        my @data = split /,/;
 | 
						|
        my $name = $data[1];
 | 
						|
 | 
						|
        my ($k1, $u1);
 | 
						|
        $k1->{node} = $name;
 | 
						|
        $u1->{mpa}  = $oa;
 | 
						|
        $u1->{id}   = $data[2];
 | 
						|
        $db{mp}->setAttribs($k1, $u1);
 | 
						|
        $db{mp}{commit} = 1;
 | 
						|
 | 
						|
        my ($k2, $u2);
 | 
						|
        $k2->{node} = $name;
 | 
						|
        $u2->{mgt}  = "hpblade";
 | 
						|
        $db{nodehm}->setAttribs($k2, $u2);
 | 
						|
        $db{nodehm}{commit} = 1;
 | 
						|
 | 
						|
        my ($k3, $u3);
 | 
						|
        $k3->{node}   = $name;
 | 
						|
        $u3->{groups} = "blade,all";
 | 
						|
        $db{nodelist}->setAttribs($k3, $u3);
 | 
						|
        $db{nodelist}{commit} = 1;
 | 
						|
    }
 | 
						|
    foreach (@tabs) {
 | 
						|
        if (exists($db{$_}{commit})) {
 | 
						|
            $db{$_}->commit;
 | 
						|
        }
 | 
						|
    }
 | 
						|
    return (0, $result);
 | 
						|
}
 | 
						|
 | 
						|
sub rscan_xml {
 | 
						|
 | 
						|
    my $mpa    = shift;
 | 
						|
    my $values = shift;
 | 
						|
    my $xml;
 | 
						|
 | 
						|
    foreach (@$values) {
 | 
						|
        my @data = split /,/;
 | 
						|
        my $i    = 0;
 | 
						|
 | 
						|
        my $href = {
 | 
						|
            Node => {}
 | 
						|
        };
 | 
						|
        foreach (@rscan_attribs) {
 | 
						|
            my $d    = $data[ $i++ ];
 | 
						|
            my $type = $data[0];
 | 
						|
 | 
						|
            if (/^name$/) {
 | 
						|
                next;
 | 
						|
            } elsif (/^nodetype$/) {
 | 
						|
                $d = $type;
 | 
						|
            } elsif (/^groups$/) {
 | 
						|
                $d = "$type,all";
 | 
						|
            } elsif (/^mgt$/) {
 | 
						|
                $d = "blade";
 | 
						|
            } elsif (/^mpa$/) {
 | 
						|
                $d = $mpa;
 | 
						|
            }
 | 
						|
            $href->{Node}->{$_} = $d;
 | 
						|
        }
 | 
						|
        $xml .= XMLout($href, NoAttr => 1, KeyAttr => [], RootName => undef);
 | 
						|
    }
 | 
						|
    return ($xml);
 | 
						|
}
 | 
						|
 | 
						|
sub rscan_stanza {
 | 
						|
 | 
						|
    my $mpa    = shift;
 | 
						|
    my $values = shift;
 | 
						|
    my $result;
 | 
						|
 | 
						|
    foreach (@$values) {
 | 
						|
        my @data = split /,/;
 | 
						|
        my $i    = 0;
 | 
						|
        my $type = $data[0];
 | 
						|
        $result .= "$data[1]:\n\tobjtype=node\n";
 | 
						|
 | 
						|
        foreach (@rscan_attribs) {
 | 
						|
            my $d = $data[ $i++ ];
 | 
						|
 | 
						|
            if (/^name$/) {
 | 
						|
                next;
 | 
						|
            } elsif (/^nodetype$/) {
 | 
						|
                $d = $type;
 | 
						|
            } elsif (/^groups$/) {
 | 
						|
                $d = "$type,all";
 | 
						|
            } elsif (/^mgt$/) {
 | 
						|
                $d = "blade";
 | 
						|
            } elsif (/^mpa$/) {
 | 
						|
                $d = $mpa;
 | 
						|
            }
 | 
						|
            $result .= "\t$_=$d\n";
 | 
						|
        }
 | 
						|
    }
 | 
						|
    return ($result);
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
 | 
						|
 | 
						|
sub beacon {
 | 
						|
    my $subcommand = shift;
 | 
						|
 | 
						|
    if ($subcommand eq "stat") {
 | 
						|
        my $currstat = $getBladeStatusResponse->result->{uid};
 | 
						|
        if ($currstat eq "UID_ON") {
 | 
						|
            return (0, "on");
 | 
						|
        } elsif ($currstat eq "UID_OFF") {
 | 
						|
            return (0, "off");
 | 
						|
        } elsif ($currstat eq "UID_BLINK") {
 | 
						|
            return (0, "blink");
 | 
						|
        }
 | 
						|
    }
 | 
						|
    my $response;
 | 
						|
    if ($subcommand eq "on") {
 | 
						|
        $response = $hpoa->setBladeUid('bayNumber' => $slot, 'uid' => "UID_CMD_ON");
 | 
						|
        if ($response->fault) {
 | 
						|
            my $errHash = $response->fault;
 | 
						|
            my $result  = $response->oaErrorText;
 | 
						|
            print "result is $result \n";
 | 
						|
            return ("1", "Uid On failed");
 | 
						|
        } else {
 | 
						|
            return ("0", "");
 | 
						|
        }
 | 
						|
    } elsif ($subcommand eq "off") {
 | 
						|
        $response = $hpoa->setBladeUid('bayNumber' => $slot, 'uid' => "UID_CMD_OFF");
 | 
						|
        if ($response->fault) {
 | 
						|
            my $errHash = $response->fault;
 | 
						|
            my $result  = $response->oaErrorText;
 | 
						|
            print "result is $result \n";
 | 
						|
            return ("1", "Uid Off failed");
 | 
						|
        } else {
 | 
						|
            return ("0", "");
 | 
						|
        }
 | 
						|
    } elsif ($subcommand eq "blink") {
 | 
						|
        $response = $hpoa->setBladeUid('bayNumber' => $slot, 'uid' => "UID_CMD_BLINK");
 | 
						|
        if ($response->fault) {
 | 
						|
            my $errHash = $response->fault;
 | 
						|
            my $result  = $response->oaErrorText;
 | 
						|
            print "result is $result \n";
 | 
						|
            return ("1", "Uid Blink failed");
 | 
						|
        } else {
 | 
						|
            return ("0", "");
 | 
						|
        }
 | 
						|
    } else {
 | 
						|
        return (1, "subcommand unsupported");
 | 
						|
    }
 | 
						|
 | 
						|
    return (1, "subcommand unsupported");
 | 
						|
}
 | 
						|
 | 
						|
sub bootseq {
 | 
						|
    my @args = @_;
 | 
						|
    my $data;
 | 
						|
    my @order = ();
 | 
						|
 | 
						|
    if ($args[0] eq "list" or $args[0] eq "stat") {
 | 
						|
 | 
						|
        # Before going off to handle the items, issue a getBladeInfo and getOaInfo
 | 
						|
        my $getBladeBootInfoResult = $hpoa->getBladeBootInfo("bayNumber" => $slot);
 | 
						|
        if ($getBladeBootInfoResult->fault) {
 | 
						|
            return (1, "getBladeBootInfo on node $curn failed");
 | 
						|
        }
 | 
						|
 | 
						|
        # Go through the the IPL Array from the last call to GetBladeStatus
 | 
						|
        my $numberOfIpls = $getBladeBootInfoResult->result->{numberOfIpls};
 | 
						|
        foreach (my $i = 0 ; $i < $numberOfIpls ; $i++) {
 | 
						|
            foreach (my $j = 0 ; $j <= 7 ; $j++) {
 | 
						|
                if ($getBladeBootInfoResult->result->{ipls}->{ipl}[$j]->{bootPriority} eq ($i + 1)) {
 | 
						|
                    push(@order, $getBladeBootInfoResult->result->{ipls}->{ipl}[$j]->{iplDevice});
 | 
						|
                    last;
 | 
						|
                }
 | 
						|
            }
 | 
						|
        }
 | 
						|
 | 
						|
        return (0, lc join(',', @order));
 | 
						|
    } else {
 | 
						|
        foreach (@args) {
 | 
						|
            my @neworder = (split /,/, $_);
 | 
						|
            push @order, @neworder;
 | 
						|
        }
 | 
						|
        my $number = @order;
 | 
						|
        if ($number > 5) {
 | 
						|
            return (1, "Only five boot sequence entries allowed");
 | 
						|
        }
 | 
						|
        my $nonespecified = 0;
 | 
						|
        my $foundnic      = 0;
 | 
						|
        foreach (@order) {
 | 
						|
            if (($bootnumbers{$_} > 4)) {
 | 
						|
                if ($foundnic == 1) {
 | 
						|
 | 
						|
                    # only one nic allowed. error out
 | 
						|
                    return (1, "Only one Eth/Nic device permitted.");
 | 
						|
                } else {
 | 
						|
                    $foundnic = 1;
 | 
						|
                }
 | 
						|
            }
 | 
						|
            unless (defined($bootnumbers{$_})) { return (1, "Unsupported device $_"); }
 | 
						|
            unless ($bootnumbers{$_}) { $nonespecified = 1; }
 | 
						|
            if ($nonespecified and $bootnumbers{$_}) { return (1, "Error: cannot specify 'none' before a device"); }
 | 
						|
        }
 | 
						|
        unless ($bootnumbers{ $order[0] }) {
 | 
						|
            return (1, "Error: cannot specify 'none' as first device");
 | 
						|
        }
 | 
						|
 | 
						|
        # Build array to be sent to the blade here
 | 
						|
        my @ipl;
 | 
						|
        my $i = 1;
 | 
						|
        foreach my $dev (@order) {
 | 
						|
            push @ipl, { "bootPriority" => "$i", "iplDevice" => "$bootdevices{$bootnumbers{$order[$i - 1]}}" };
 | 
						|
            $i++;
 | 
						|
        }
 | 
						|
 | 
						|
        my $setiplResponse = $hpoa->setBladeIplBootPriority("bladeIplArray" => [ 'ipl', \@ipl, "" ], "bayNumber" => $slot);
 | 
						|
        if ($setiplResponse->fault) {
 | 
						|
            my $errHash = $setiplResponse->fault;
 | 
						|
            my $result  = $setiplResponse->oaErrorText;
 | 
						|
            print "result is $result \n";
 | 
						|
            return (1, "Error on slot $slot setting ipl");
 | 
						|
        }
 | 
						|
 | 
						|
        return bootseq('list');
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
sub power {
 | 
						|
    my $subcommand = shift;
 | 
						|
    my $command2Send;
 | 
						|
    my $currPowerStat;
 | 
						|
    my $returnState;
 | 
						|
 | 
						|
    $returnState   = "";
 | 
						|
    $currPowerStat = $getBladeStatusResponse->result->{powered};
 | 
						|
 | 
						|
    if ($subcommand eq "stat" || $subcommand eq "state") {
 | 
						|
        if ($currPowerStat eq "POWER_ON") {
 | 
						|
            return (0, "on");
 | 
						|
        } elsif ($currPowerStat eq "POWER_OFF") {
 | 
						|
            return (0, "off");
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    if ($subcommand eq "on") {
 | 
						|
        if ($currPowerStat eq "POWER_OFF") {
 | 
						|
            $command2Send = "MOMENTARY_PRESS";
 | 
						|
            $returnState  = "on";
 | 
						|
        } else {
 | 
						|
            return (0, "on");
 | 
						|
        }
 | 
						|
    } elsif ($subcommand eq "off") {
 | 
						|
        if ($currPowerStat eq "POWER_ON") {
 | 
						|
            $command2Send = "PRESS_AND_HOLD";
 | 
						|
            $returnState  = "off";
 | 
						|
        } else {
 | 
						|
            return (0, "off");
 | 
						|
        }
 | 
						|
    } elsif ($subcommand eq "reset") {
 | 
						|
        $command2Send = "RESET";
 | 
						|
    } elsif ($subcommand eq "cycle") {
 | 
						|
        if ($currPowerStat eq "POWER_ON") {
 | 
						|
            power("off");
 | 
						|
        }
 | 
						|
        $command2Send = "MOMENTARY_PRESS";
 | 
						|
    } elsif ($subcommand eq "boot") {
 | 
						|
        if ($currPowerStat eq "POWER_OFF") {
 | 
						|
            $command2Send = "MOMENTARY_PRESS";
 | 
						|
            $returnState  = "off on";
 | 
						|
        } else {
 | 
						|
            $command2Send = "COLD_BOOT";
 | 
						|
            $returnState  = "on reset";
 | 
						|
        }
 | 
						|
    } elsif ($subcommand eq "softoff") {
 | 
						|
        if ($currPowerStat eq "POWER_ON") {
 | 
						|
            $command2Send = "MOMENTARY_PRESS";
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    #If we got here with a command to send, do it, otherwise just return
 | 
						|
    if ($command2Send) {
 | 
						|
        my $pwrResult = $hpoa->setBladePower('bayNumber' => $slot, 'power' => $command2Send);
 | 
						|
        if ($pwrResult->fault) {
 | 
						|
            return (1, "Node $curn - Power command failed");
 | 
						|
        }
 | 
						|
        return (0, $returnState);
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
 | 
						|
sub bladecmd {
 | 
						|
    my $oa   = shift;
 | 
						|
    my $node = shift;
 | 
						|
    $slot = shift;
 | 
						|
    my $user    = shift;
 | 
						|
    my $pass    = shift;
 | 
						|
    my $command = shift;
 | 
						|
    my @args    = @_;
 | 
						|
    my $error;
 | 
						|
 | 
						|
    if ($slot > 0) {
 | 
						|
        $getBladeStatusResponse = $hpoa->getBladeStatus('bayNumber' => $slot);
 | 
						|
        if ($getBladeStatusResponse->fault) {
 | 
						|
            my $errHash = $getBladeStatusResponse->fault;
 | 
						|
            my $result  = $getBladeStatusResponse->oaErrorText;
 | 
						|
        }
 | 
						|
        if ($getBladeStatusResponse->result->{presence} ne "PRESENT") {
 | 
						|
            return (1, "Target bay empty");
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    if ($command eq "rbeacon") {
 | 
						|
        return beacon(@args);
 | 
						|
    } elsif ($command eq "rpower") {
 | 
						|
        return power(@args);
 | 
						|
    } elsif ($command eq "rvitals") {
 | 
						|
        return vitals(@args);
 | 
						|
    } elsif ($command =~ /r[ms]preset/) {
 | 
						|
        return resetmp(@args);
 | 
						|
    } elsif ($command eq "rspconfig") {
 | 
						|
        return iloconfig($oa, $user, $pass, $node, $slot, @args);
 | 
						|
    } elsif ($command eq "rbootseq") {
 | 
						|
        return bootseq(@args);
 | 
						|
    } elsif ($command eq "switchblade") {
 | 
						|
        return switchblade(@args);
 | 
						|
    } elsif ($command eq "getmacs") {
 | 
						|
        return getmacs(@args);
 | 
						|
    } elsif ($command eq "rinv") {
 | 
						|
        return inv(@args);
 | 
						|
    } elsif ($command eq "reventlog") {
 | 
						|
        return eventlog(@args);
 | 
						|
    } elsif ($command eq "rscan") {
 | 
						|
        return rscan(\@args);
 | 
						|
    }
 | 
						|
 | 
						|
    return (1, "$command not a supported command by blade method");
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
sub forward_data {
 | 
						|
    my $callback  = shift;
 | 
						|
    my $fds       = shift;
 | 
						|
    my @ready_fds = $fds->can_read(1);
 | 
						|
    my $rfh;
 | 
						|
    my $rc = @ready_fds;
 | 
						|
    foreach $rfh (@ready_fds) {
 | 
						|
        my $data;
 | 
						|
        if ($data = <$rfh>) {
 | 
						|
            while ($data !~ /ENDOFFREEZE6sK4ci/) {
 | 
						|
                $data .= <$rfh>;
 | 
						|
            }
 | 
						|
            print $rfh "ACK\n";
 | 
						|
            my $responses = thaw($data);
 | 
						|
            foreach (@$responses) {
 | 
						|
                $callback->($_);
 | 
						|
            }
 | 
						|
        } else {
 | 
						|
            $fds->remove($rfh);
 | 
						|
            close($rfh);
 | 
						|
        }
 | 
						|
    }
 | 
						|
    yield;    #Try to avoid useless iterations as much as possible
 | 
						|
    return $rc;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
 | 
						|
sub doblade {
 | 
						|
    my $out = shift;
 | 
						|
    $oa = shift;
 | 
						|
    my $oahash    = shift;
 | 
						|
    my $command   = shift;
 | 
						|
    my %namedargs = @_;
 | 
						|
    my @exargs    = @{ $namedargs{-args} };
 | 
						|
    my $node;
 | 
						|
    my $args = \@exargs;
 | 
						|
 | 
						|
    $hpoa = oaLogin($oa);
 | 
						|
 | 
						|
    # We are now logged into the OA and have a pointer to the OA session. Process
 | 
						|
    # the command.
 | 
						|
 | 
						|
    #get new node status
 | 
						|
    my %nodestat = ();
 | 
						|
    my $check    = 0;
 | 
						|
    my $nsh      = {};
 | 
						|
 | 
						|
    foreach $node (sort (keys %{ $oahash->{$oa}->{nodes} })) {
 | 
						|
        $curn = $node;
 | 
						|
        my ($rc, @output) = bladecmd($oa, $node, $oahash->{$oa}->{nodes}->{$node}, $oahash->{$oa}->{username}, $oahash->{$oa}->{password}, $command, @$args);
 | 
						|
 | 
						|
        foreach (@output) {
 | 
						|
            my %output;
 | 
						|
 | 
						|
            if ($command eq "rscan") {
 | 
						|
                $output{errorcode} = $rc;
 | 
						|
                $output{data}      = [$_];
 | 
						|
            }
 | 
						|
            else {
 | 
						|
                (my $desc, my $text) = split(/:/, $_, 2);
 | 
						|
                unless ($text) {
 | 
						|
                    $text = $desc;
 | 
						|
                } else {
 | 
						|
                    $desc =~ s/^\s+//;
 | 
						|
                    $desc =~ s/\s+$//;
 | 
						|
                    if ($desc) {
 | 
						|
                        $output{node}->[0]->{data}->[0]->{desc}->[0] = $desc;
 | 
						|
                    }
 | 
						|
                }
 | 
						|
                $text =~ s/^\s+//;
 | 
						|
                $text =~ s/\s+$//;
 | 
						|
                $output{node}->[0]->{errorcode}                  = $rc;
 | 
						|
                $output{node}->[0]->{name}->[0]                  = $node;
 | 
						|
                $output{node}->[0]->{data}->[0]->{contents}->[0] = $text;
 | 
						|
            }
 | 
						|
            print $out freeze([ \%output ]);
 | 
						|
            print $out "\nENDOFFREEZE6sK4ci\n";
 | 
						|
            yield;
 | 
						|
            waitforack($out);
 | 
						|
        }
 | 
						|
        yield;
 | 
						|
    }
 | 
						|
 | 
						|
    #update the node status to the nodelist.status table
 | 
						|
    if ($check) {
 | 
						|
        my %node_status = ();
 | 
						|
 | 
						|
        #foreach (keys %nodestat) { print "node=$_,status=" . $nodestat{$_} ."\n"; } #Ling:remove
 | 
						|
 | 
						|
        foreach my $node (keys %nodestat) {
 | 
						|
            my $stat = $nodestat{$node};
 | 
						|
            if ($stat eq "no-op") { next; }
 | 
						|
            if (exists($node_status{$stat})) {
 | 
						|
                my $pa = $node_status{$stat};
 | 
						|
                push(@$pa, $node);
 | 
						|
            }
 | 
						|
            else {
 | 
						|
                $node_status{$stat} = [$node];
 | 
						|
            }
 | 
						|
        }
 | 
						|
        xCAT_monitoring::monitorctrl::setNodeStatusAttributes(\%node_status, 1);
 | 
						|
 | 
						|
    }
 | 
						|
 | 
						|
    #my $msgtoparent=freeze(\@outhashes); # = XMLout(\%output,RootName => 'xcatresponse');
 | 
						|
    #print $out $msgtoparent; #$node.": $_\n";
 | 
						|
}
 | 
						|
 | 
						|
sub extractDate {
 | 
						|
    use Time::Local;
 | 
						|
    my $date = shift;
 | 
						|
 | 
						|
    return 0 unless $date =~ m/(\d{1,2})\/(\d{1,2})\/(\d{4}) (\d{1,2}):(\d{1,2})/;
 | 
						|
 | 
						|
    return timegm(0, $5, $4, $2, $1, $3);
 | 
						|
}
 | 
						|
 | 
						|
1;
 |