mirror of
				https://github.com/xcat2/xcat-core.git
				synced 2025-11-03 21:02:34 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			6249 lines
		
	
	
		
			223 KiB
		
	
	
	
		
			Perl
		
	
	
	
	
	
			
		
		
	
	
			6249 lines
		
	
	
		
			223 KiB
		
	
	
	
		
			Perl
		
	
	
	
	
	
#!/usr/bin/env perl
 | 
						|
# IBM(c) 2007 EPL license http://www.eclipse.org/legal/epl-v10.html
 | 
						|
package xCAT_plugin::blade;
 | 
						|
 | 
						|
BEGIN
 | 
						|
{
 | 
						|
    $::XCATROOT = $ENV{'XCATROOT'} ? $ENV{'XCATROOT'} : '/opt/xcat';
 | 
						|
 | 
						|
    if (defined $ENV{ENABLE_TRACE_CODE}) {
 | 
						|
        use xCAT::Enabletrace qw(loadtrace filter);
 | 
						|
        loadtrace();
 | 
						|
    }
 | 
						|
 | 
						|
}
 | 
						|
 | 
						|
use lib "$::XCATROOT/lib/perl";
 | 
						|
 | 
						|
#use Net::SNMP qw(:snmp INTEGER);
 | 
						|
use xCAT::Table;
 | 
						|
use Thread qw(yield);
 | 
						|
use xCAT::Utils;
 | 
						|
use xCAT::TableUtils;
 | 
						|
use xCAT::NetworkUtils;
 | 
						|
use xCAT::ServiceNodeUtils;
 | 
						|
use xCAT::PasswordUtils;
 | 
						|
use xCAT::IMMUtils;
 | 
						|
use xCAT::Usage;
 | 
						|
use IO::Socket;
 | 
						|
use IO::Pty;    #needed for ssh password login
 | 
						|
use xCAT::GlobalDef;
 | 
						|
use xCAT_monitoring::monitorctrl;
 | 
						|
use strict;
 | 
						|
use LWP;
 | 
						|
require xCAT::data::ibmhwtypes;
 | 
						|
 | 
						|
#use warnings;
 | 
						|
my %mm_comm_pids;
 | 
						|
 | 
						|
#a 'browser' for http actions
 | 
						|
my $browser;
 | 
						|
use XML::Simple;
 | 
						|
$XML::Simple::PREFERRED_PARSER = 'XML::Parser';
 | 
						|
 | 
						|
#use Data::Dumper;
 | 
						|
use POSIX "WNOHANG";
 | 
						|
use Storable qw(freeze thaw store_fd fd_retrieve);
 | 
						|
use IO::Select;
 | 
						|
use IO::Handle;
 | 
						|
use Time::HiRes qw(gettimeofday sleep);
 | 
						|
use xCAT::DBobjUtils;
 | 
						|
use Getopt::Long;
 | 
						|
use xCAT::SvrUtils;
 | 
						|
use xCAT::FSPUtils;
 | 
						|
my $indiscover  = 0;
 | 
						|
my $CALLBACK    = undef;
 | 
						|
my $verbose_cmd = undef;
 | 
						|
my $vitals_info = undef; #used by 'rvitals <node> all' to show lcds info for Firebird blade
 | 
						|
my %x222_info   = ();    #used to collect x222 infomations
 | 
						|
my $has_x222    = undef;
 | 
						|
my %newnodestatus = ();
 | 
						|
 | 
						|
sub handled_commands {
 | 
						|
    return {
 | 
						|
        findme       => 'blade',
 | 
						|
        getmacs      => 'nodehm:getmac,mgt',
 | 
						|
        rscan        => 'nodehm:mgt',
 | 
						|
        rpower       => 'nodehm:power,mgt',
 | 
						|
        getbladecons => 'blade',
 | 
						|
        getrvidparms => 'nodehm:mgt',
 | 
						|
        rvitals      => 'nodehm:mgt=blade|fsp',
 | 
						|
        rinv         => 'nodehm:mgt',
 | 
						|
        rbeacon      => 'nodehm:mgt=blade|fsp',
 | 
						|
        rspreset     => 'nodehm:mgt',
 | 
						|
        rspconfig => 'nodehm:mgt=blade|fsp|ipmi', # Get into blade.pm for rspconfig if mgt equals blade or fsp
 | 
						|
        rbootseq  => 'nodehm:mgt',
 | 
						|
        reventlog   => 'nodehm:mgt=blade|fsp',
 | 
						|
        switchblade => 'nodehm:mgt',
 | 
						|
        renergy     => 'nodehm:mgt=blade|fsp|ipmi',
 | 
						|
        lsflexnode  => 'blade',
 | 
						|
        mkflexnode  => 'blade',
 | 
						|
        rmflexnode  => 'blade',
 | 
						|
    };
 | 
						|
}
 | 
						|
 | 
						|
my %macmap;             #Store responses from rinv for discovery
 | 
						|
my %uuidmap;
 | 
						|
my $macmaptimestamp;    #reflect freshness of cache
 | 
						|
my $mmprimoid       = '1.3.6.1.4.1.2.3.51.2.22.5.1.1.4';      #mmPrimary
 | 
						|
my $beaconoid       = '1.3.6.1.4.1.2.3.51.2.2.8.2.1.1.11';    #ledBladeIdentity
 | 
						|
my $erroroid        = '1.3.6.1.4.1.2.3.51.2.2.8.2.1.1.7';     #ledBladeError
 | 
						|
my $infooid         = '1.3.6.1.4.1.2.3.51.2.2.8.2.1.1.8';     #ledBladeInfo
 | 
						|
my $kvmoid          = '1.3.6.1.4.1.2.3.51.2.2.8.2.1.1.9';     #ledBladeKVM
 | 
						|
my $mtoid           = '1.3.6.1.4.1.2.3.51.2.2.8.2.1.1.10';    #ledBladeMT
 | 
						|
my $chassiserroroid = '1.3.6.1.4.1.2.3.51.2.2.8.1.1.0';       #ChassisLedError
 | 
						|
my $chassisinfooid  = '1.3.6.1.4.1.2.3.51.2.2.8.1.2.0';       #ChassisLedInfo
 | 
						|
my $chassistempledoid = '1.3.6.1.4.1.2.3.51.2.2.8.1.3.0'; #ChassisLedTemperature
 | 
						|
my $chassisbeaconoid  = '1.3.6.1.4.1.2.3.51.2.2.8.1.4.0'; #ChassisLedIdentity
 | 
						|
my $powerstatoid   = '1.3.6.1.4.1.2.3.51.2.22.1.5.1.1.4'; #bladePowerState
 | 
						|
my $powerchangeoid = '1.3.6.1.4.1.2.3.51.2.22.1.6.1.1.7'; #powerOnOffBlade
 | 
						|
my $powerresetoid  = '1.3.6.1.4.1.2.3.51.2.22.1.6.1.1.8'; #restartBlade
 | 
						|
my $mpresetoid     = '1.3.6.1.4.1.2.3.51.2.22.1.6.1.1.9'; #restartBladeSMP
 | 
						|
my $bladexistsoid  = '1.3.6.1.4.1.2.3.51.2.22.1.5.1.1.3'; #bladeExists
 | 
						|
my $bladeserialoid = '1.3.6.1.4.1.2.3.51.2.2.21.4.1.1.6'; #bladeHardwareVpdSerialNumber
 | 
						|
my $blademtmoid = '1.3.6.1.4.1.2.3.51.2.2.21.4.1.1.7'; #bladeHardwareVpdMachineType
 | 
						|
my $bladeuuidoid = '1.3.6.1.4.1.2.3.51.2.2.21.4.1.1.8';    #bladeHardwareVpdUuid
 | 
						|
my $componentuuidoid = '.1.3.6.1.4.1.2.3.51.2.2.23.1.1.1.13'; #componentInventoryUUID
 | 
						|
my $bladempveroid = '1.3.6.1.4.1.2.3.51.2.2.21.5.3.1.7'; #bladeSysMgmtProcVpdRevision
 | 
						|
my $bladempaveroid = '1.3.6.1.4.1.2.3.51.2.2.21.3.1.1.4'; #mmMainApplVpdRevisonNumber
 | 
						|
my $bladempabuildidoid = '1.3.6.1.4.1.2.3.51.2.2.21.3.1.1.3'; #mmMainApplVpdBuildId
 | 
						|
my $bladempadateoid = '1.3.6.1.4.1.2.3.51.2.2.21.3.1.1.6'; #mmMainApplVpdBuildDate
 | 
						|
my $bladempbuildidoid = '1.3.6.1.4.1.2.3.51.2.2.21.5.3.1.6'; #bladeSysMgmtProcVpdBuildId
 | 
						|
my $bladebiosveroid = '1.3.6.1.4.1.2.3.51.2.2.21.5.1.1.7'; #bladeBiosVpdRevision
 | 
						|
my $bladebiosbuildidoid = '1.3.6.1.4.1.2.3.51.2.2.21.5.1.1.6'; #bladeBiosVpdBuildId
 | 
						|
my $bladebiosdateoid = '1.3.6.1.4.1.2.3.51.2.2.21.5.1.1.8';    #bladeBiosVpdDate
 | 
						|
my $bladediagveroid = '1.3.6.1.4.1.2.3.51.2.2.21.5.2.1.7'; #bladeDiagsVpdRevision
 | 
						|
my $bladediagbuildidoid = '1.3.6.1.4.1.2.3.51.2.2.21.5.2.1.6'; #bladeDiagsVpdBuildId
 | 
						|
my $bladediagdateoid = '1.3.6.1.4.1.2.3.51.2.2.21.5.2.1.8';  #bladeDiagsVpdDate
 | 
						|
my $eventlogoid      = '1.3.6.1.4.1.2.3.51.2.3.4.2.1.2';     #readEventLogString
 | 
						|
my $clearlogoid      = '.1.3.6.1.4.1.2.3.51.2.3.4.3';        #clearEventLog
 | 
						|
my $chassisfanbase   = '.1.3.6.1.4.1.2.3.51.2.2.3.50.1.';
 | 
						|
my $blower1speedoid  = '.1.3.6.1.4.1.2.3.51.2.2.3.1';        #blower2speed
 | 
						|
my $blower2speedoid  = '.1.3.6.1.4.1.2.3.51.2.2.3.2';        #blower2speed
 | 
						|
my $blower3speedoid  = '.1.3.6.1.4.1.2.3.51.2.2.3.3';        #blower2speed
 | 
						|
my $blower4speedoid  = '.1.3.6.1.4.1.2.3.51.2.2.3.4';        #blower2speed
 | 
						|
my $blower1stateoid  = '.1.3.6.1.4.1.2.3.51.2.2.3.10';       #blower1State
 | 
						|
my $blower2stateoid  = '.1.3.6.1.4.1.2.3.51.2.2.3.11';       #blower2State
 | 
						|
my $blower3stateoid  = '.1.3.6.1.4.1.2.3.51.2.2.3.12';       #blower2State
 | 
						|
my $blower4stateoid  = '.1.3.6.1.4.1.2.3.51.2.2.3.13';       #blower2State
 | 
						|
my $blower1rpmoid    = '.1.3.6.1.4.1.2.3.51.2.2.3.20';       #blower1SpeedRPM
 | 
						|
my $blower2rpmoid    = '.1.3.6.1.4.1.2.3.51.2.2.3.21';       #blower2SpeedRPM
 | 
						|
my $blower3rpmoid    = '.1.3.6.1.4.1.2.3.51.2.2.3.22';       #blower3SpeedRPM
 | 
						|
my $blower4rpmoid    = '.1.3.6.1.4.1.2.3.51.2.2.3.23';       #blower4SpeedRPM
 | 
						|
my $blower1contstateoid = '.1.3.6.1.4.1.2.3.51.2.2.3.30'; #blower1Controllerstote
 | 
						|
my $blower2contstateoid = '.1.3.6.1.4.1.2.3.51.2.2.3.31'; #blower2''
 | 
						|
my $blower3contstateoid = '.1.3.6.1.4.1.2.3.51.2.2.3.32'; #blower3''
 | 
						|
my $blower4contstateoid = '.1.3.6.1.4.1.2.3.51.2.2.3.33'; #blower4''
 | 
						|
my $mmoname =                                             #chassisName
 | 
						|
  { 'mm' => '1.3.6.1.4.1.2.3.51.2.22.4.3',
 | 
						|
    'cmm' => '.1.3.6.1.4.1.2.3.51.2.4.5.1' };
 | 
						|
my $mmotype   = '1.3.6.1.4.1.2.3.51.2.2.21.1.1.1';   #bladeCenterVpdMachineType
 | 
						|
my $mmomodel  = '1.3.6.1.4.1.2.3.51.2.2.21.1.1.2';   #bladeCenterVpdMachineModel
 | 
						|
my $mmoserial = '1.3.6.1.4.1.2.3.51.2.2.21.1.1.3';   #bladeCenterSerialNumber
 | 
						|
my $bladeoname  = '1.3.6.1.4.1.2.3.51.2.22.1.5.1.1.6';     #bladeName
 | 
						|
my $bladeomodel = '1.3.6.1.4.1.2.3.51.2.2.21.4.1.1.12';    #bladeModel
 | 
						|
 | 
						|
my @macoids = (
 | 
						|
    '1.3.6.1.4.1.2.3.51.2.2.21.4.2.1.2',                   #bladeMACAddress1Vpd
 | 
						|
    '1.3.6.1.4.1.2.3.51.2.2.21.4.2.1.3',                   #bladeMACAddress2Vpd
 | 
						|
    '1.3.6.1.4.1.2.3.51.2.2.21.4.2.1.4',                   #bladeMACAddress3Vpd
 | 
						|
    '1.3.6.1.4.1.2.3.51.2.2.21.4.2.1.5',                   #bladeMACAddress4Vpd
 | 
						|
);
 | 
						|
my @dcmacoids = (
 | 
						|
    '1.3.6.1.4.1.2.3.51.2.2.21.4.2.1.10',    #bladeDaughterCard1MACAddress1Vpd
 | 
						|
    '1.3.6.1.4.1.2.3.51.2.2.21.4.2.1.11',    #bladeDaughterCard1MACAddress2Vpd
 | 
						|
    '1.3.6.1.4.1.2.3.51.2.2.21.4.2.1.12',    #bladeDaughterCard1MACAddress3Vpd
 | 
						|
    '1.3.6.1.4.1.2.3.51.2.2.21.4.2.1.13',    #bladeDaughterCard1MACAddress4Vpd
 | 
						|
);
 | 
						|
my @hsdcmacoids = (
 | 
						|
    '1.3.6.1.4.1.2.3.51.2.2.21.4.2.1.100',   #bladeHSDaughterCard1MACAddress1Vpd
 | 
						|
    '1.3.6.1.4.1.2.3.51.2.2.21.4.2.1.101',   #bladeHSDaughterCard1MACAddress2Vpd
 | 
						|
    '1.3.6.1.4.1.2.3.51.2.2.21.4.2.1.102',   #bladeHSDaughterCard1MACAddress3Vpd
 | 
						|
    '1.3.6.1.4.1.2.3.51.2.2.21.4.2.1.103',   #bladeHSDaughterCard1MACAddress4Vpd
 | 
						|
);
 | 
						|
my @sidecardoids = (
 | 
						|
    '1.3.6.1.4.1.2.3.51.2.2.21.4.2.1.164',    #bladeSideCardMACAddress1Vpd
 | 
						|
    '1.3.6.1.4.1.2.3.51.2.2.21.4.2.1.165',    #bladeSideCardMACAddress2Vpd
 | 
						|
    '1.3.6.1.4.1.2.3.51.2.2.21.4.2.1.166',    #bladeSideCardMACAddress3Vpd
 | 
						|
    '1.3.6.1.4.1.2.3.51.2.2.21.4.2.1.167',    #bladeSideCardMACAddress4Vpd
 | 
						|
);
 | 
						|
my @bootseqoids = (
 | 
						|
    '1.3.6.1.4.1.2.3.51.2.22.1.3.1.7',        #bootSequence1
 | 
						|
    '1.3.6.1.4.1.2.3.51.2.22.1.3.1.8',        #bootSequence2
 | 
						|
    '1.3.6.1.4.1.2.3.51.2.22.1.3.1.9',        #bootSequence3
 | 
						|
    '1.3.6.1.4.1.2.3.51.2.22.1.3.1.10',       #bootSequence4
 | 
						|
);
 | 
						|
my %bootdevices = (
 | 
						|
    0  => 'none',
 | 
						|
    1  => 'floppy',
 | 
						|
    2  => 'cdrom',
 | 
						|
    3  => 'hd0',
 | 
						|
    4  => 'hd1',
 | 
						|
    5  => 'hd2',
 | 
						|
    6  => 'hd3',
 | 
						|
    7  => 'net',
 | 
						|
    8  => 'iscsi',
 | 
						|
    9  => 'iscsicrit',
 | 
						|
    10 => 'hd4',
 | 
						|
    11 => 'usbflash',
 | 
						|
    12 => 'hypervisor',
 | 
						|
    13 => 'uefi',
 | 
						|
    14 => 'legacy'
 | 
						|
);
 | 
						|
my %bootnumbers = (
 | 
						|
    'none'       => 0,
 | 
						|
    'f'          => 1,
 | 
						|
    'floppy'     => 1,
 | 
						|
    'c'          => 2,
 | 
						|
    'cd'         => 2,
 | 
						|
    'dvd'        => 2,
 | 
						|
    'cdrom'      => 2,
 | 
						|
    'dvdrom'     => 2,
 | 
						|
    'h'          => 3,    #in absence of an index, presuming hd0 intended
 | 
						|
    'hd'         => 3,
 | 
						|
    'hardisk'    => 3,
 | 
						|
    'hd0'        => 3,
 | 
						|
    'harddisk0'  => 3,
 | 
						|
    'hd1'        => 4,
 | 
						|
    'harddisk1'  => 4,
 | 
						|
    'hd2'        => 5,
 | 
						|
    'harddisk2'  => 5,
 | 
						|
    'hd3'        => 6,
 | 
						|
    'harddisk3'  => 6,
 | 
						|
    'n'          => 7,
 | 
						|
    'network'    => 7,
 | 
						|
    'net'        => 7,
 | 
						|
    'iscsi'      => 8,
 | 
						|
    'iscsicrit'  => 9,
 | 
						|
    'hd4'        => 10,
 | 
						|
    'harddisk4'  => 10,
 | 
						|
    'usbflash'   => 11,
 | 
						|
    'hypervisor' => 12,
 | 
						|
    'flash'      => 11,
 | 
						|
    'uefi'       => 13,
 | 
						|
    'legacy'     => 14,
 | 
						|
    'usb'        => 11
 | 
						|
);
 | 
						|
 | 
						|
my @rscan_attribs = qw(nodetype name id mtm serial mpa hcp groups mgt cons hwtype);
 | 
						|
my @rscan_header = (
 | 
						|
    [ "type",          "%-8s" ],
 | 
						|
    [ "name",          "" ],
 | 
						|
    [ "id",            "%-8s" ],
 | 
						|
    [ "type-model",    "%-12s" ],
 | 
						|
    [ "serial-number", "%-15s" ],
 | 
						|
    [ "mpa",           "" ],
 | 
						|
    [ "address",       "%s\n" ]);
 | 
						|
 | 
						|
my $session;
 | 
						|
my $slot;
 | 
						|
my @moreslots;
 | 
						|
my $didchassis     = 0;
 | 
						|
my @eventlog_array = ();
 | 
						|
my $activemm;
 | 
						|
my %mpahash;
 | 
						|
my $currnode;
 | 
						|
my $mpa;
 | 
						|
my $mptype;     # The type of mp node. For cmm, it's 'cmm'
 | 
						|
my $mpatype;    # The type of node's mpa. Used for SNMP OIDs.
 | 
						|
my $mpauser;
 | 
						|
my $mpapass;
 | 
						|
my $allinchassis = 0;
 | 
						|
my $curn;
 | 
						|
my @cfgtext;
 | 
						|
my $status_noop = "XXXno-opXXX";
 | 
						|
 | 
						|
my %telnetrscan;    # Store the rscan result by telnet command line
 | 
						|
 | 
						|
sub fillresps {
 | 
						|
    my $response = shift;
 | 
						|
    my $mac      = $response->{node}->[0]->{data}->[0]->{contents}->[0];
 | 
						|
    my $node     = $response->{node}->[0]->{name}->[0];
 | 
						|
    unless ($mac) { return; }  #The event that a bay is empty should not confuse
 | 
						|
 | 
						|
    #xcat into having an odd mapping
 | 
						|
    $mac = uc($mac); #Make sure it is uppercase, the MM people seem to change their mind on this..
 | 
						|
    if ($mac =~ /........-....-....-....-............/) {    #a uuid
 | 
						|
        $uuidmap{$mac} = $node;
 | 
						|
    } elsif ($mac =~ /->/) {    #The new and 'improved' syntax for pBlades
 | 
						|
 | 
						|
        $mac =~ /(\w+):(\w+):(\w+):(\w+):(\w+):(\w+)\s*->\s*(\w+):(\w+):(\w+):(\w+):(\w+):(\w+)/;
 | 
						|
        my $fmac = hex($3 . $4 . $5 . $6);
 | 
						|
        my $lmac = hex($9 . $10 . $11 . $12);
 | 
						|
        my $pfx  = $1 . $2;
 | 
						|
        foreach ($fmac .. $lmac) {
 | 
						|
            my $key = $pfx . sprintf("%08x", $_);
 | 
						|
            $key =~ s/(\w{2})/$1:/g;
 | 
						|
            chop($key);
 | 
						|
            $key = uc($key);
 | 
						|
            $macmap{$key} = $node;
 | 
						|
        }
 | 
						|
    } else {
 | 
						|
        $macmap{$mac} = $node;
 | 
						|
    }
 | 
						|
 | 
						|
    #$macmap{$response->{node}->[0]->{data}->{contents}->[0]}=$response->{node}->[0]->{name};
 | 
						|
}
 | 
						|
 | 
						|
sub isallchassis {
 | 
						|
    my $bladesinchassis = 0;
 | 
						|
    if ($allinchassis) {
 | 
						|
        return 1;
 | 
						|
    }
 | 
						|
    foreach (1 .. 14) {
 | 
						|
        my $tmp = $session->get([ $bladexistsoid . ".$_" ]);
 | 
						|
        if ($tmp == 1) { $bladesinchassis++ }
 | 
						|
    }
 | 
						|
    my $count = keys %{ $mpahash{$mpa}->{nodes} };
 | 
						|
    if ($count >= $bladesinchassis) { $allinchassis++; return 1 }; #commands that affect entire are okayed, i.e eventlog clear
 | 
						|
    return 0;
 | 
						|
}
 | 
						|
 | 
						|
sub resetmp {
 | 
						|
    my $data;
 | 
						|
    my $stat;
 | 
						|
    my $rc;
 | 
						|
 | 
						|
    #$data = $session->set($mpresetoid.".$slot", 1);
 | 
						|
    $data = $session->set(new SNMP::Varbind([ "." . $mpresetoid, $slot, 1, 'INTEGER' ]));
 | 
						|
    unless ($data) { return (1, $session->{ErrorStr}); }
 | 
						|
    return (0, "mpreset");
 | 
						|
 | 
						|
    #if ($session->{ErrorStr}) { return (1,$session->{ErrorStr}); }
 | 
						|
    #if ($session->{ErrorStr}) { return (1,$session->{ErrorStr}); }
 | 
						|
    #if ($data->{$mpresetoid.".$slot"} == 1) {
 | 
						|
    #  return (0, "mpreset");
 | 
						|
    #} else {
 | 
						|
    #  return (1,"error");
 | 
						|
    #}
 | 
						|
}
 | 
						|
 | 
						|
sub waitforack {
 | 
						|
    my $sock   = shift;
 | 
						|
    my $select = new IO::Select;
 | 
						|
    $select->add($sock);
 | 
						|
    my $str;
 | 
						|
    if ($select->can_read(60)) { # Continue after 60 seconds, even if not acked...
 | 
						|
        if ($str = <$sock>) {
 | 
						|
        } else {
 | 
						|
            $select->remove($sock);    #Block until parent acks data
 | 
						|
        }
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
sub walkelog {
 | 
						|
    my $session = shift;
 | 
						|
    my $oid     = shift;
 | 
						|
    unless ($oid =~ /^\./) {
 | 
						|
        $oid = '.' . $oid;
 | 
						|
    }
 | 
						|
    my $retmap  = undef;
 | 
						|
    my $current = 1;
 | 
						|
    my @bindlist;
 | 
						|
    my $varbind;
 | 
						|
    do {
 | 
						|
        foreach ($current .. $current + 31) { #Attempt to retrive 32 ents at a time, seems to be working...
 | 
						|
            push @bindlist, [ $oid, $_ ];
 | 
						|
        }
 | 
						|
        $current += 32;
 | 
						|
        $varbind = new SNMP::VarList(
 | 
						|
            @bindlist
 | 
						|
        );
 | 
						|
        $session->get($varbind);
 | 
						|
        foreach (@$varbind) {
 | 
						|
            unless (${_}->[2]) { last; }
 | 
						|
            if (${_}->[2] =~ /NOSUCHINSTANCE/) { last; }
 | 
						|
            $retmap->{ $_->[1] } = $_->[2];
 | 
						|
        }
 | 
						|
        @bindlist = ();
 | 
						|
    } while ($varbind->[31] and $varbind->[31]->[2] ne 'NOSUCHINSTANCE' and ($current < 2000));
 | 
						|
 | 
						|
    return $retmap;
 | 
						|
    return undef;
 | 
						|
    my $count = 0;
 | 
						|
    while ($varbind->[0] =~ /^$oid\.?(.*)/) {
 | 
						|
        $count++;
 | 
						|
        if ($1) {
 | 
						|
            $retmap->{ $1 . "." . $varbind->[1] } = $varbind->[2]; #If $1 is set, means key should
 | 
						|
        } else {
 | 
						|
            $retmap->{ $varbind->[1] } = $varbind->[2]; #If $1 is set, means key should
 | 
						|
        }
 | 
						|
        $session->getnext($varbind);
 | 
						|
    }
 | 
						|
    return $retmap;
 | 
						|
}
 | 
						|
 | 
						|
sub eventlog { #Tried various optimizations, but MM seems not to do bulk-request
 | 
						|
     #TODO: retrieval of non blade events, what should be syntax?
 | 
						|
     #TODO: try retrieving 5 at a time, then 1 at a time when that stops working
 | 
						|
    @ARGV = @_;
 | 
						|
    my $force;
 | 
						|
 | 
						|
    #GetOptions(
 | 
						|
    #	"f" => \$force,
 | 
						|
    #	);
 | 
						|
    my $cmd   = undef;
 | 
						|
    my $order = undef;
 | 
						|
    my $arg   = shift @ARGV;
 | 
						|
    while ($arg) {
 | 
						|
        if ($arg eq "all" or $arg eq "clear" or $arg =~ /^\d+$/) {
 | 
						|
            if (defined($cmd)) {
 | 
						|
                return (1, "reventlog $cmd $arg invalid");
 | 
						|
            }
 | 
						|
            $cmd = $arg;
 | 
						|
        } elsif ($arg =~ /^-s$/) {
 | 
						|
            $order = 1;
 | 
						|
        } elsif ($arg =~ /^-f$/) {
 | 
						|
            $force = 1;
 | 
						|
        } else {
 | 
						|
            return (1, "unsupported command reventlog $arg");
 | 
						|
        }
 | 
						|
        $arg = shift @ARGV;
 | 
						|
    }
 | 
						|
 | 
						|
    my $data;
 | 
						|
    my @output;
 | 
						|
    my $oid = $eventlogoid;
 | 
						|
    unless ($cmd) {
 | 
						|
        $cmd = 'all';
 | 
						|
    }
 | 
						|
    if (defined($force) and $cmd ne "clear") {
 | 
						|
        return (1, "option \"-f\" can only work with \"clear\"");
 | 
						|
    }
 | 
						|
    if ($cmd eq 'all') {
 | 
						|
        $cmd = 65535; #no MM has this many logs possible, should be a good number
 | 
						|
    }
 | 
						|
    if ($cmd =~ /^(\d+)$/) {
 | 
						|
        my $requestednumber = $1;
 | 
						|
        unless (@eventlog_array) {
 | 
						|
 | 
						|
            #my $varbind=new SNMP::Varbind([$oid,0]);
 | 
						|
            #while ($data=$session->getnext($varbind)) {
 | 
						|
            #  print Dumper($data);
 | 
						|
            #  if ($session->{ErrorStr}) { printf $session->{ErrorStr}."\n"; }
 | 
						|
            #  foreach (keys %$data) {
 | 
						|
            #    $oid=$_;
 | 
						|
            #  }
 | 
						|
            #  unless (oid_base_match($eventlogoid,$oid)) {
 | 
						|
            #    last;
 | 
						|
            #  }
 | 
						|
            my $logents = walkelog($session, $oid);
 | 
						|
            foreach (sort { $a <=> $b } (keys %$logents)) {
 | 
						|
                push @eventlog_array, $logents->{$_} . "\n";
 | 
						|
            }
 | 
						|
 | 
						|
            #push @eventlog_array,$data->{$oid}; #TODO: filter against slot number, check for $allchassis for non-blade
 | 
						|
            #}
 | 
						|
        }
 | 
						|
        my $numentries = 0;
 | 
						|
 | 
						|
        #my $allchassis = isallchassis;
 | 
						|
        foreach (@eventlog_array) {
 | 
						|
m/Severity:(\S+)\s+Source:(\S+)\s+Name:\S*\s+Date:(\S+)\s+Time:(\S+)\s+Text:(.+)/;
 | 
						|
            my $sev    = $1;
 | 
						|
            my $source = $2;
 | 
						|
            my $date   = $3;
 | 
						|
            my $time   = $4;
 | 
						|
            my $text   = $5;
 | 
						|
            my $matchstring;
 | 
						|
            if ($slot > 0) {
 | 
						|
 | 
						|
                #$matchstring=sprintf("BLADE_%02d",$slot);
 | 
						|
                $matchstring = sprintf("(NODE_%02d|BLADE_%02d)", $slot, $slot);
 | 
						|
            } else {
 | 
						|
 | 
						|
                #$matchstring="^(?!BLADE).*";
 | 
						|
                $matchstring = "^(?!(NODE|BLADE)).*";
 | 
						|
            }
 | 
						|
            if ($source =~ m/$matchstring$/i) { #MM guys changed their minds on capitalization
 | 
						|
                if (defined($order)) {
 | 
						|
                    $numentries++;
 | 
						|
                    push @output, "$sev:$date $time $text";
 | 
						|
                } else {
 | 
						|
                    unshift @output, "$sev:$date $time $text"; #unshift to get it in a sane order
 | 
						|
                    if ($#output >= $requestednumber) {
 | 
						|
                        pop @output;
 | 
						|
                    }
 | 
						|
                }
 | 
						|
            } else {
 | 
						|
                foreach (@moreslots) {
 | 
						|
 | 
						|
                    #$matchstring=sprintf("BLADE_%02d",$_);
 | 
						|
                    $matchstring = sprintf("(NODE_%02d|BLADE_%02d)", $_, $_);
 | 
						|
                    if ($source =~ m/$matchstring$/i) { #MM guys changed their minds on capitalization
 | 
						|
                        if (defined($order)) {
 | 
						|
                            $numentries++;
 | 
						|
                            push @output, "$sev:$date $time $text";
 | 
						|
                        } else {
 | 
						|
                            unshift @output, "$sev:$date $time $text"; #unshift to get it in a sane order
 | 
						|
                            if ($#output >= $requestednumber) {
 | 
						|
                                pop @output;
 | 
						|
                            }
 | 
						|
                        }
 | 
						|
                    }
 | 
						|
                }
 | 
						|
            }
 | 
						|
            if ($numentries >= $requestednumber) {
 | 
						|
                last;
 | 
						|
            }
 | 
						|
        }
 | 
						|
        return (0, @output);
 | 
						|
    }
 | 
						|
    if ($cmd eq "clear") {
 | 
						|
        unless ($force or isallchassis) {
 | 
						|
            return (1, "Cannot clear eventlogs except for entire chassis");
 | 
						|
        }
 | 
						|
        if ($didchassis) { return 0, "eventlog cleared" }
 | 
						|
        my $varbind = new SNMP::Varbind([ $clearlogoid, 0, 1, 'INTEGER' ]);
 | 
						|
        $data = $session->set($varbind);
 | 
						|
        if ($session->{ErrorStr}) { return (1, $session->{ErrorStr}); }
 | 
						|
        $didchassis = 1;
 | 
						|
        if ($varbind->[2] == 1) {
 | 
						|
            return 0, "eventlog cleared";
 | 
						|
        }
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
sub setoid {
 | 
						|
    my $oid    = shift;
 | 
						|
    my $offset = shift;
 | 
						|
    my $value  = shift;
 | 
						|
    my $type   = shift;
 | 
						|
    unless ($type) { $type = 'INTEGER'; }
 | 
						|
    my $varbind = new SNMP::Varbind([ $oid, $offset, $value, $type ]);
 | 
						|
    my $data = $session->set($varbind);
 | 
						|
    if ($session->{ErrorStr}) { return (1, $session->{ErrorStr}); }
 | 
						|
    return 0, $varbind;
 | 
						|
}
 | 
						|
 | 
						|
sub enabledefaultalerts {
 | 
						|
 | 
						|
    #Customizers: most oids are listed, and some commented out. uncomment if you want to get them
 | 
						|
    #deprecated options are in, but commented, will elect to use what the MM official strategy suggests
 | 
						|
    my @enabledalerts = (
 | 
						|
 | 
						|
        #Deprecated '1.3.6.1.4.1.2.3.51.2.4.2.1.1', #critical temperature
 | 
						|
        #deprecated '1.3.6.1.4.1.2.3.51.2.4.2.1.2', #critical voltage
 | 
						|
        #deprecated '1.3.6.1.4.1.2.3.51.2.4.2.1.4', #critical blower
 | 
						|
        '1.3.6.1.4.1.2.3.51.2.4.2.1.5',    #critical power
 | 
						|
            #deprecated '1.3.6.1.4.1.2.3.51.2.4.2.1.6', #critical Hard drive
 | 
						|
            #deprecated '1.3.6.1.4.1.2.3.51.2.4.2.1.7', #critical VRM
 | 
						|
            #deprecated '1.3.6.1.4.1.2.3.51.2.4.2.1.8', #critical switch module
 | 
						|
            #deprecated '1.3.6.1.4.1.2.3.51.2.4.2.1.9', #critical config
 | 
						|
        '1.3.6.1.4.1.2.3.51.2.4.2.1.10',    #critical blade
 | 
						|
        '1.3.6.1.4.1.2.3.51.2.4.2.1.11',    #critical IO
 | 
						|
        '1.3.6.1.4.1.2.3.51.2.4.2.1.12',    #critical storage
 | 
						|
        '1.3.6.1.4.1.2.3.51.2.4.2.1.13',    #critical chassis
 | 
						|
        '1.3.6.1.4.1.2.3.51.2.4.2.1.14',    #critical fan
 | 
						|
          #deprecated '1.3.6.1.4.1.2.3.51.2.4.2.2.2', #warn single blower
 | 
						|
          #deprecated '1.3.6.1.4.1.2.3.51.2.4.2.2.3', #warn temp
 | 
						|
          #deprecated '1.3.6.1.4.1.2.3.51.2.4.2.2.4', #warn volt
 | 
						|
          #deprecated '1.3.6.1.4.1.2.3.51.2.4.2.2.6', #warn backup MM
 | 
						|
          #deprecated '1.3.6.1.4.1.2.3.51.2.4.2.2.7', #warn tray/KVM switch prob
 | 
						|
        '1.3.6.1.4.1.2.3.51.2.4.2.2.10',    #warn log full
 | 
						|
        '1.3.6.1.4.1.2.3.51.2.4.2.2.15',    #warn blade warning
 | 
						|
        '1.3.6.1.4.1.2.3.51.2.4.2.2.16',    #warn io warning
 | 
						|
        '1.3.6.1.4.1.2.3.51.2.4.2.2.17',    #warn storage warning
 | 
						|
        '1.3.6.1.4.1.2.3.51.2.4.2.2.18',    #warn power module
 | 
						|
        '1.3.6.1.4.1.2.3.51.2.4.2.2.19',    #warn chassis
 | 
						|
        '1.3.6.1.4.1.2.3.51.2.4.2.2.20',    #warn cooling
 | 
						|
            #deprecated '1.3.6.1.4.1.2.3.51.2.4.2.3.4', #info power off
 | 
						|
            #deprecated '1.3.6.1.4.1.2.3.51.2.4.2.3.5', #info power on
 | 
						|
            #deprecated '1.3.6.1.4.1.2.3.51.2.4.2.3.8', #info PFA
 | 
						|
        '1.3.6.1.4.1.2.3.51.2.4.2.3.10',    #info inventory (insert/remove)
 | 
						|
        '1.3.6.1.4.1.2.3.51.2.4.2.3.11',    #info 75% events
 | 
						|
        '1.3.6.1.4.1.2.3.51.2.4.2.3.12',    #info net reconfig
 | 
						|
            #deprecated '1.3.6.1.4.1.2.3.51.2.4.2.3.13', #info throttling
 | 
						|
            #deprecated '1.3.6.1.4.1.2.3.51.2.4.2.3.14', #info power management
 | 
						|
            #annoying '1.3.6.1.4.1.2.3.51.2.4.2.3.15', #info login events
 | 
						|
        '1.3.6.1.4.1.2.3.51.2.4.2.3.16',    #info blade events
 | 
						|
        '1.3.6.1.4.1.2.3.51.2.4.2.3.17',    #info IO events
 | 
						|
        '1.3.6.1.4.1.2.3.51.2.4.2.3.18',    #info storage events
 | 
						|
        '1.3.6.1.4.1.2.3.51.2.4.2.3.19',    #info power module events
 | 
						|
        '1.3.6.1.4.1.2.3.51.2.4.2.3.20',    #info  chassis events
 | 
						|
        '1.3.6.1.4.1.2.3.51.2.4.2.3.21',    #info  blower event
 | 
						|
        '1.3.6.1.4.1.2.3.51.2.4.2.3.22',    #info  power on/off
 | 
						|
    );
 | 
						|
    setoid('1.3.6.1.4.1.2.3.51.2.4.2.4', 0, 1);
 | 
						|
    foreach (@enabledalerts) {
 | 
						|
        setoid($_, 0, 1);
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
sub mpaconfig {
 | 
						|
 | 
						|
    #OIDs of interest:
 | 
						|
    #1.3.6.1.4.1.2.3.51.2.4.9.3.1.4.1.1.4 snmpCommunityEntryCommunityIpAddress2
 | 
						|
    #snmpCommunityEntryCommunityName 1.3.6.1.4.1.2.3.51.2.4.9.3.1.4.1.1.2
 | 
						|
    #remoteAlerts 1.3.6.1.4.1.2.3.51.2.4.2
 | 
						|
    #remoteAlertIdEntryTextDescription 1.3.6.1.4.1.2.3.51.2.4.1.3.1.1.4
 | 
						|
    #remoteAlertIdEntryStatus 1.3.6.1.4.1.2.3.51.2.4.1.3.1.1.2 (0 invalid, 2 enable)
 | 
						|
 | 
						|
    my $mpa    = shift;
 | 
						|
    my $user   = shift;
 | 
						|
    my $pass   = shift;
 | 
						|
    my $node   = shift;
 | 
						|
    my $nodeid = shift;
 | 
						|
    my @morenodeids;
 | 
						|
    if ($nodeid =~ /-(.*)/) {
 | 
						|
        my $highid = $1;
 | 
						|
        $nodeid =~ s/-.*//;
 | 
						|
        @morenodeids = ($nodeid + 1 .. $highid);
 | 
						|
    }
 | 
						|
    if (scalar @moreslots) {
 | 
						|
        push @morenodeids, @moreslots;
 | 
						|
    }
 | 
						|
 | 
						|
 | 
						|
    my $parameter;
 | 
						|
    my $value;
 | 
						|
    my $assignment;
 | 
						|
    my $returncode = 0;
 | 
						|
    my $textid     = 0;
 | 
						|
    if ($didchassis) { return 0, @cfgtext } #"Chassis already configured for this command" }
 | 
						|
    @cfgtext = ();
 | 
						|
 | 
						|
    foreach $parameter (@_) {
 | 
						|
        $assignment = 0;
 | 
						|
        $value      = undef;
 | 
						|
        if ($parameter =~ /=/) {
 | 
						|
            $assignment = 1;
 | 
						|
            ($parameter, $value) = split /=/, $parameter, 2;
 | 
						|
        }
 | 
						|
        if ($parameter =~ /^ntp$/) {
 | 
						|
            my $result = ntp($value);
 | 
						|
            $returncode |= shift(@$result);
 | 
						|
            push @cfgtext, @$result;
 | 
						|
            next;
 | 
						|
        }
 | 
						|
        elsif ($parameter =~ /^network$/) {
 | 
						|
            my $data = $session->get([ '1.3.6.1.4.1.2.3.51.2.4.9.1.1.4', 0 ]);
 | 
						|
            push @cfgtext, "MM IP: $data";
 | 
						|
            $data = $session->get([ '1.3.6.1.4.1.2.3.51.2.4.9.1.1.3', 0 ]);
 | 
						|
            push @cfgtext, "MM Hostname: $data";
 | 
						|
            $data = $session->get([ '1.3.6.1.4.1.2.3.51.2.4.9.1.1.9', 0 ]);
 | 
						|
            push @cfgtext, "Gateway: $data";
 | 
						|
            $data = $session->get([ '1.3.6.1.4.1.2.3.51.2.4.9.1.1.14', 0 ]);
 | 
						|
            push @cfgtext, "Subnet Mask: $data";
 | 
						|
            next;
 | 
						|
        }
 | 
						|
        elsif ($parameter eq "textid") {
 | 
						|
            $textid = 1;
 | 
						|
            if ($assignment) {
 | 
						|
                my $txtid = ($value =~ /^\*/) ? $node : $value;
 | 
						|
                setoid("1.3.6.1.4.1.2.3.51.2.22.1.7.1.1.5", $nodeid, $txtid, 'OCTET');
 | 
						|
                my $extrabay = 2;
 | 
						|
                foreach (@morenodeids) {
 | 
						|
                    setoid("1.3.6.1.4.1.2.3.51.2.22.1.7.1.1.5", $_, $txtid . ", slot $extrabay", 'OCTET');
 | 
						|
                    $extrabay += 1;
 | 
						|
                }
 | 
						|
            } else {
 | 
						|
                my $data;
 | 
						|
                if ($slot > 0) {
 | 
						|
                    $data = $session->get([ $bladeoname, $nodeid ]);
 | 
						|
                }
 | 
						|
                else {
 | 
						|
                    $data = $session->get([ $mmoname->{$mptype}, 0 ]);
 | 
						|
                }
 | 
						|
                push @cfgtext, "textid: $data";
 | 
						|
                foreach (@morenodeids) {
 | 
						|
                    $data = $session->get([ $bladeoname, $_ ]);
 | 
						|
                    push @cfgtext, "textid: $data";
 | 
						|
                }
 | 
						|
            }
 | 
						|
        }
 | 
						|
        elsif ($parameter =~ /^snmpcfg$/i) {
 | 
						|
            my $data = $session->get([ '1.3.6.1.4.1.2.3.51.2.4.9.3.1.6', 0 ]);
 | 
						|
            if ($data) {
 | 
						|
                push @cfgtext, "SNMP: enabled";
 | 
						|
            }
 | 
						|
            else {
 | 
						|
                push @cfgtext, "SNMP: disabled";
 | 
						|
            }
 | 
						|
            next;
 | 
						|
        }
 | 
						|
        elsif ($parameter =~ /^snmpdest/ or $parameter eq "snmpdest") {
 | 
						|
            if ($parameter eq "snmpdest") {
 | 
						|
                $parameter = "snmpdest1";
 | 
						|
            }
 | 
						|
            $parameter =~ /snmpdest(\d+)/;
 | 
						|
            if ($1 > 3) {
 | 
						|
                $returncode |= 1;
 | 
						|
                push(@cfgtext, "Only up to three snmp destinations may be defined");
 | 
						|
                next;
 | 
						|
            }
 | 
						|
            my $dstindex = $1;
 | 
						|
            if ($assignment) {
 | 
						|
                my $restorev1agent = 0;
 | 
						|
                if (($session->get([ '1.3.6.1.4.1.2.3.51.2.4.9.3.1.5', 0 ])) == 1) { #per the BLADE MIB, this *must* be zero in order to change SNMP IPs
 | 
						|
                    $restorev1agent = 1;
 | 
						|
                    setoid('1.3.6.1.4.1.2.3.51.2.4.9.3.1.5', 0, 0, 'INTEGER');
 | 
						|
                }
 | 
						|
                setoid("1.3.6.1.4.1.2.3.51.2.4.9.3.1.4.1.1." . (2 + $dstindex), 1, $value, 'OCTET');
 | 
						|
                setoid("1.3.6.1.4.1.2.3.51.2.4.9.3.1.4.1.1.6.1", 1, 1, 'INTEGER'); #access type: read-traps, don't give full write access to the community
 | 
						|
                if ($restorev1agent) { #If we had to transiently disable the v1 agent, put it back the way it was
 | 
						|
                    setoid('1.3.6.1.4.1.2.3.51.2.4.9.3.1.5', 0, 1, 'INTEGER');
 | 
						|
                }
 | 
						|
 | 
						|
            }
 | 
						|
            my $data = $session->get([ "1.3.6.1.4.1.2.3.51.2.4.9.3.1.4.1.1." . (2 + $dstindex) . ".1" ]);
 | 
						|
            push @cfgtext, "SP SNMP Destination $1: $data";
 | 
						|
            next;
 | 
						|
        }
 | 
						|
        elsif ($parameter =~ /^community/i) {
 | 
						|
            if ($assignment) {
 | 
						|
                setoid("1.3.6.1.4.1.2.3.51.2.4.9.3.1.4.1.1.2.1", 0, $value, 'OCTET');
 | 
						|
            }
 | 
						|
            my $data = $session->get(["1.3.6.1.4.1.2.3.51.2.4.9.3.1.4.1.1.2.1"]);
 | 
						|
            push @cfgtext, "SP SNMP Community: $data";
 | 
						|
            next;
 | 
						|
        }
 | 
						|
        elsif ($parameter =~ /^alert/i) {
 | 
						|
            if ($assignment) {
 | 
						|
                if ($value =~ /^enable/i or $value =~ /^en/i or $value =~ /^on$/i) {
 | 
						|
                    setoid('1.3.6.1.4.1.2.3.51.2.4.1.3.1.1.4', 12, 'xCAT configured SNMP', 'OCTET'); #Set a description so the MM doesn't flip out
 | 
						|
                    setoid('1.3.6.1.4.1.2.3.51.2.4.1.3.1.1.5', 12, 4); #Set Dest12 to SNMP
 | 
						|
                    setoid('1.3.6.1.4.1.2.3.51.2.4.1.3.1.1.2', 12, 2); #enable dest12
 | 
						|
                    setoid('1.3.6.1.4.1.2.3.51.2.4.9.3.1.3', 0, 0); #Enable SNMP traps
 | 
						|
                    enabledefaultalerts();
 | 
						|
                } elsif ($value =~ /^disable/i or $value =~ /^dis/i or $value =~ /^off$/i) {
 | 
						|
                    setoid('1.3.6.1.4.1.2.3.51.2.4.1.3.1.1.2', 12, 0); #Disable alert dest 12
 | 
						|
                    setoid('1.3.6.1.4.1.2.3.51.2.4.9.3.1.3', 0, 1); #Disable SNMP traps period
 | 
						|
                }
 | 
						|
            }
 | 
						|
            my $data = $session->get(['1.3.6.1.4.1.2.3.51.2.4.1.3.1.1.2.12']);
 | 
						|
            if ($data == 2) {
 | 
						|
                push @cfgtext, "SP Alerting: enabled";
 | 
						|
                next;
 | 
						|
            } elsif (defined $data and $data == 0) {
 | 
						|
                push @cfgtext, "SP Alerting: disabled";
 | 
						|
                next;
 | 
						|
            } else {
 | 
						|
                $returncode |= 1;
 | 
						|
                push @cfgtext, "Unable to get alert configuration (is SNMP enabled?)";
 | 
						|
                next;
 | 
						|
            }
 | 
						|
        } elsif ($parameter =~ /^solcfg/i) {
 | 
						|
            my $data = $session->get([ '.1.3.6.1.4.1.2.3.51.2.4.10.1.1', 0 ]);
 | 
						|
            if ($data) {
 | 
						|
                push @cfgtext, "solcfg: enabled on mm";
 | 
						|
            } else {
 | 
						|
                push @cfgtext, "solcfg: disabled on mm";
 | 
						|
            }
 | 
						|
        } else {
 | 
						|
            $returncode |= 1;
 | 
						|
            push(@cfgtext, "Unrecognized argument $parameter");
 | 
						|
        }
 | 
						|
 | 
						|
    }
 | 
						|
    unless ($textid) {
 | 
						|
        $didchassis = 1;
 | 
						|
    }
 | 
						|
    return $returncode, @cfgtext;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
sub switchblade {
 | 
						|
 | 
						|
    #OIDS of interest:
 | 
						|
    #1.3.6.1.4.1.2.3.51.2.22.1.1 media tray ownership
 | 
						|
    #1.3.6.1.4.1.2.3.51.2.22.1.2 kvm ownership
 | 
						|
    my @args = @_;
 | 
						|
    my $data;
 | 
						|
    my @rettext;
 | 
						|
    my $domt    = 0;
 | 
						|
    my $dokvm   = 0;
 | 
						|
    my $targnum = $slot;
 | 
						|
    if ($args[1] =~ /^\d+$/) {
 | 
						|
        $targnum = $args[1];
 | 
						|
    }
 | 
						|
    if ($args[0] eq "list" or $args[0] eq "stat") {
 | 
						|
        $data = $session->get(["1.3.6.1.4.1.2.3.51.2.22.1.1.0"]);
 | 
						|
        push @rettext, "Media Tray slot: $data";
 | 
						|
        $data = $session->get(["1.3.6.1.4.1.2.3.51.2.22.1.2.0"]);
 | 
						|
        push @rettext, "KVM slot: $data";
 | 
						|
    } elsif ($args[0] eq "both") {
 | 
						|
        $domt  = 1;
 | 
						|
        $dokvm = 1;
 | 
						|
    } elsif ($args[0] eq "mt" or $args[0] eq "media") {
 | 
						|
        $domt = 1;
 | 
						|
    } elsif ($args[0] eq "kvm" or $args[0] eq "video") {
 | 
						|
        $dokvm = 1;
 | 
						|
    }
 | 
						|
    if ($domt) {
 | 
						|
        setoid("1.3.6.1.4.1.2.3.51.2.22.1.1", 0, $targnum);
 | 
						|
        $data = $session->get(["1.3.6.1.4.1.2.3.51.2.22.1.1.0"]);
 | 
						|
        push @rettext, "Media Tray slot: $data";
 | 
						|
    }
 | 
						|
    if ($dokvm) {
 | 
						|
        setoid("1.3.6.1.4.1.2.3.51.2.22.1.2", 0, $targnum);
 | 
						|
        $data = $session->get(["1.3.6.1.4.1.2.3.51.2.22.1.2.0"]);
 | 
						|
        push @rettext, "KVM slot: $data";
 | 
						|
    }
 | 
						|
 | 
						|
    return 0, @rettext;
 | 
						|
}
 | 
						|
 | 
						|
sub bootseq {
 | 
						|
    my @args = @_;
 | 
						|
    my $data;
 | 
						|
    my @order = ();
 | 
						|
    if ($args[0] eq "list" or $args[0] eq "stat") {
 | 
						|
        foreach my $oid (@bootseqoids) {
 | 
						|
            $data = $session->get([ $oid, $slot ]);
 | 
						|
            if ($session->{ErrorStr}) { return (1, $session->{ErrorStr}); }
 | 
						|
            push @order, $bootdevices{$data};
 | 
						|
        }
 | 
						|
        return (0, join(',', @order));
 | 
						|
    } else {
 | 
						|
        foreach (@args) {
 | 
						|
            my @neworder = (split /,/, $_);
 | 
						|
            push @order, @neworder;
 | 
						|
        }
 | 
						|
        my $number = @order;
 | 
						|
        if ($number > 4) {
 | 
						|
            return (1, "Only four boot sequence entries allowed");
 | 
						|
        }
 | 
						|
        my $nonespecified = 0;
 | 
						|
        foreach (@order) {
 | 
						|
            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");
 | 
						|
        }
 | 
						|
        foreach (3, 2, 1, 0) {
 | 
						|
            my $param = $bootnumbers{ $order[$_] };
 | 
						|
            unless ($param) {
 | 
						|
                $param = 0;
 | 
						|
                my $varbind = new SNMP::Varbind([ $bootseqoids[$_], $slot, $param, 'INTEGER' ]);
 | 
						|
                $data = $session->set($varbind);
 | 
						|
 | 
						|
                #$session->set($bootseqoids[$_].".$slot",$param);
 | 
						|
                if ($session->{ErrorStr}) { return (1, $session->{ErrorStr}); }
 | 
						|
            }
 | 
						|
        }
 | 
						|
        foreach (0, 1, 2, 3) {
 | 
						|
            my $param = $bootnumbers{ $order[$_] };
 | 
						|
            if ($param) {
 | 
						|
                my $varbind = new SNMP::Varbind([ $bootseqoids[$_], $slot, $param, 'INTEGER' ]);
 | 
						|
                $data = $session->set($varbind);
 | 
						|
 | 
						|
                #$session->set($bootseqoids[$_].".$slot",$param);
 | 
						|
                if ($session->{ErrorStr}) { return (1, $session->{ErrorStr}); }
 | 
						|
            }
 | 
						|
        }
 | 
						|
        return bootseq('list');
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
sub cleantemp {
 | 
						|
 | 
						|
    #Taken a bladecenter string, reformat/convert to be consistent with ipmi presentation choices
 | 
						|
    my $temp = shift;
 | 
						|
    my $tnum;
 | 
						|
    $temp =~ /(\d+\.\d+) Centigrade/;
 | 
						|
    $tnum = $1;
 | 
						|
    $temp =~ s/ = /:/;
 | 
						|
    $temp =~ s/\+(\d+)/$1/;   #remove + sign from temperature readings if put in
 | 
						|
    $temp =~ s/Centigrade/C/; #remove controversial use of Centigrade
 | 
						|
    if ($tnum) {
 | 
						|
        $temp .= " (" . sprintf("%.2f", $tnum * (9 / 5) + 32) . " F)";
 | 
						|
    }
 | 
						|
    return $temp;
 | 
						|
}
 | 
						|
 | 
						|
sub collect_health_summary {    #extracts the health summary table
 | 
						|
    my %summarymap;
 | 
						|
    my %idmap;
 | 
						|
    my $varbind = new SNMP::VarList(
 | 
						|
        [ '.1.3.6.1.4.1.2.3.51.2.22.1.5.2.1.2', '1' ],
 | 
						|
    );
 | 
						|
    $session->get($varbind);
 | 
						|
    while ($varbind->[0]->[0] eq '.1.3.6.1.4.1.2.3.51.2.22.1.5.2.1.2') {
 | 
						|
        $idmap{ $varbind->[0]->[1] } = $varbind->[0]->[2];
 | 
						|
        $session->getnext($varbind);
 | 
						|
    }
 | 
						|
    my $numentries = scalar(keys %idmap);
 | 
						|
    my @bindlist;
 | 
						|
    foreach (1 .. $numentries) {
 | 
						|
        push @bindlist, [ '.1.3.6.1.4.1.2.3.51.2.22.1.5.2.1.3', $_ ];
 | 
						|
    }
 | 
						|
    my $sevbind = new SNMP::VarList(@bindlist);
 | 
						|
    $session->get($sevbind);
 | 
						|
    my $id;
 | 
						|
    my $bladeid;
 | 
						|
    foreach (@$sevbind) {
 | 
						|
        $id                                      = $_->[1];
 | 
						|
        $bladeid                                 = $idmap{$id};
 | 
						|
        $summarymap{$bladeid}->{$id}->{severity} = $_->[2];
 | 
						|
    }
 | 
						|
    @bindlist = ();
 | 
						|
    foreach (1 .. $numentries) {
 | 
						|
        push @bindlist, [ '.1.3.6.1.4.1.2.3.51.2.22.1.5.2.1.4', $_ ];
 | 
						|
    }
 | 
						|
    my $detailbind = new SNMP::VarList(@bindlist);
 | 
						|
    $session->get($detailbind);
 | 
						|
    foreach (@$detailbind) {
 | 
						|
        $id                                    = $_->[1];
 | 
						|
        $bladeid                               = $idmap{$id};
 | 
						|
        $summarymap{$bladeid}->{$id}->{detail} = $_->[2];
 | 
						|
    }
 | 
						|
    return \%summarymap;
 | 
						|
}
 | 
						|
 | 
						|
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(errorled beaconled infoled kvmled mtled);
 | 
						|
            } elsif ($_ =~ '^led') {
 | 
						|
                push @vitems, qw(errorled beaconled infoled kvmled mtled);
 | 
						|
            } else {
 | 
						|
                push @vitems, split(/,/, $_);
 | 
						|
            }
 | 
						|
        }
 | 
						|
        verbose_message("slotid:$slot, options:@vitems.");
 | 
						|
    } else {                                                #-- chassis query
 | 
						|
        foreach (@_) {
 | 
						|
            if ($_ eq 'all') {
 | 
						|
                push @vitems, qw(voltage wattage power summary);
 | 
						|
                push @vitems, qw(errorled beaconled infoled templed);
 | 
						|
                push @vitems, qw(fan blower);
 | 
						|
                push @vitems, qw(ammtemp ambient);
 | 
						|
            } elsif ($_ =~ '^led') {
 | 
						|
                push @vitems, qw(errorled beaconled infoled templed);
 | 
						|
            } elsif ($_ =~ '^cool') {
 | 
						|
                push @vitems, qw(fan blower);
 | 
						|
            } elsif ($_ =~ '^temp') {
 | 
						|
                push @vitems, qw(ammtemp ambient);
 | 
						|
            } else {
 | 
						|
                push @vitems, split(/,/, $_);
 | 
						|
            }
 | 
						|
        }
 | 
						|
        verbose_message("for chassis, options:@vitems.");
 | 
						|
    }
 | 
						|
    if (grep /fan/, @vitems or grep /blower/, @vitems) { #We'll lump blowers and fans together for blades, besides, BCS fans
 | 
						|
            #use the 'blower' OIDs anyway
 | 
						|
        unless (defined $chassiswidevitals{blower}) {
 | 
						|
            populateblowervitals();
 | 
						|
        }
 | 
						|
    }
 | 
						|
    if (grep /fan/, @vitems) { #Only put in fans if fan requested, use of word 'blower' would indicate omitting the 'fans'
 | 
						|
         #For those wondering why 'power supply' fans are considered relevant to a particular blade,
 | 
						|
         #note that blades capable of taking high speed daughtercards have holes along the edges.
 | 
						|
         #Those holes are air intakes fed by the PSU exhaust, to get cooler air into the expansion area
 | 
						|
        unless (defined $chassiswidevitals{fan}) {
 | 
						|
            populatefanvitals();
 | 
						|
        }
 | 
						|
    }
 | 
						|
    my $tmp;
 | 
						|
 | 
						|
    if (defined $slot and $slot > 0) {    #-- querying some blade
 | 
						|
 | 
						|
        if (grep /watt/, @vitems) {
 | 
						|
            my $tmp_oid = "1.3.6.1.4.1.2.3.51.2.2.10.2.1.1.7.";
 | 
						|
            if ($mpatype eq 'cmm') {
 | 
						|
                $tmp_oid .= ($slot + 24);
 | 
						|
            } else {
 | 
						|
                if ($slot < 8) {
 | 
						|
                    $tmp_oid .= ($slot + 16);
 | 
						|
 | 
						|
                    #$tmp = $session->get(["1.3.6.1.4.1.2.3.51.2.2.10.2.1.1.7.".($slot+16)]);
 | 
						|
                } else {
 | 
						|
                    $tmp_oid = "1.3.6.1.4.1.2.3.51.2.2.10.3.1.1.7." . ($slot + 9);
 | 
						|
 | 
						|
                    #$tmp = $session->get(["1.3.6.1.4.1.2.3.51.2.2.10.3.1.1.7.".($slot+9)]);
 | 
						|
                }
 | 
						|
            }
 | 
						|
            $tmp = $session->get([$tmp_oid]);
 | 
						|
            unless ($tmp =~ /Not Readable/) {
 | 
						|
                if ($tmp =~ /(\d+)W/) {
 | 
						|
                    $tmp = "$1 Watts (" . int($tmp * 3.413 + 0.5) . " BTUs/hr)";
 | 
						|
                }
 | 
						|
                $tmp =~ s/^/Power Usage:/;
 | 
						|
                push @output, "$tmp";
 | 
						|
            } else {
 | 
						|
                verbose_message("OID:$tmp_oid, value:$tmp.");
 | 
						|
            }
 | 
						|
        }
 | 
						|
 | 
						|
        my @bindlist;
 | 
						|
        my $bindobj;
 | 
						|
        if (grep /voltage/, @vitems) {
 | 
						|
 | 
						|
            for my $idx (15 .. 40) {
 | 
						|
                push @bindlist, [ ".1.3.6.1.4.1.2.3.51.2.22.1.5.5.1.$idx", $slot ];
 | 
						|
            }
 | 
						|
            $bindobj = new SNMP::VarList(@bindlist);
 | 
						|
            $session->get($bindobj); #[".1.3.6.1.4.1.2.3.51.2.22.1.5.5.1.$idx.$slot"]);
 | 
						|
            for my $tmp (@$bindobj) {
 | 
						|
                if ($tmp and defined $tmp->[2] and $tmp->[2] !~ /Not Readable/ and $tmp->[2] ne "") {
 | 
						|
                    $tmp->[2] =~ s/ = /:/;
 | 
						|
                    push @output, $tmp->[2];
 | 
						|
                } else {
 | 
						|
                    verbose_message("OID:$tmp->[0].$tmp->[1], value:$tmp->[2].");
 | 
						|
                }
 | 
						|
            }
 | 
						|
            @bindlist = ();
 | 
						|
        }
 | 
						|
 | 
						|
        if (grep /temp/, @vitems) {
 | 
						|
            for my $idx (6 .. 20) {
 | 
						|
                if ($idx == 11) {
 | 
						|
                    next;
 | 
						|
                }
 | 
						|
                push @bindlist, [ ".1.3.6.1.4.1.2.3.51.2.22.1.5.3.1.$idx", $slot ];
 | 
						|
            }
 | 
						|
            $bindobj = new SNMP::VarList(@bindlist);
 | 
						|
            $session->get($bindobj);
 | 
						|
            my $tnum;
 | 
						|
            for my $tmp (@$bindobj) {
 | 
						|
                if ($tmp and defined $tmp->[2] and $tmp->[2] !~ /Not Readable/ and $tmp->[2] ne "") {
 | 
						|
                    my $restype = $tmp->[0];
 | 
						|
                    $restype =~ s/^.*\.(\d*)$/$1/;
 | 
						|
                    if ($restype =~ /^([6789])$/) {
 | 
						|
                        $tmp->[2] = "CPU " . ($1 - 5) . " Temp: " . $tmp->[2];
 | 
						|
                    }
 | 
						|
                    push @output, cleantemp($tmp->[2]);
 | 
						|
                } else {
 | 
						|
                    verbose_message("OID:$tmp->[0].$tmp->[1], value:$tmp->[2].");
 | 
						|
                }
 | 
						|
            }
 | 
						|
            unless (defined $chassiswidevitals{ambient}) {
 | 
						|
                $chassiswidevitals{ambient} = [];
 | 
						|
                my @ambientbind = ([ ".1.3.6.1.4.1.2.3.51.2.2.1.5.1", "0" ],
 | 
						|
                    [ ".1.3.6.1.4.1.2.3.51.2.2.1.5.2", "0" ]);
 | 
						|
                if ($mpatype eq 'cmm') {
 | 
						|
                    pop @ambientbind;
 | 
						|
                }
 | 
						|
                my $targ    = new SNMP::VarList(@ambientbind);
 | 
						|
                my $tempidx = 1;
 | 
						|
                $session->get($targ);
 | 
						|
                for my $result (@$targ) {
 | 
						|
 | 
						|
                    #if ($result->[2] eq "NOSUCHINSTANCE") {
 | 
						|
                    if ($result->[2] =~ /NOSUCH/) {
 | 
						|
                        verbose_message("OID:$result->[0].$result->[1], value:$result->[2].");
 | 
						|
                        next;
 | 
						|
                    }
 | 
						|
                    push @{ $chassiswidevitals{ambient} }, "Ambient " . $tempidx++ . " :" . cleantemp($result->[2]);
 | 
						|
                }
 | 
						|
            }
 | 
						|
            foreach (@{ $chassiswidevitals{ambient} }) {
 | 
						|
 | 
						|
                push @output, $_;
 | 
						|
            }
 | 
						|
        }
 | 
						|
 | 
						|
        if (grep /blower/, @vitems) { #We'll lump blowers and fans together for blades, besides, BCS fans
 | 
						|
                                      #use the 'blower' OIDs anyway
 | 
						|
            foreach (@{ $chassiswidevitals{blower} }) {
 | 
						|
                push @output, $_;
 | 
						|
            }
 | 
						|
        } elsif (grep /fan/, @vitems) {
 | 
						|
            foreach (@{ $chassiswidevitals{blower} }) {
 | 
						|
                push @output, $_;
 | 
						|
            }
 | 
						|
            foreach (@{ $chassiswidevitals{fan} }) {
 | 
						|
                push @output, $_;
 | 
						|
            }
 | 
						|
        }
 | 
						|
 | 
						|
 | 
						|
        if (grep /summary/, @vitems) {
 | 
						|
            unless ($chassiswidevitals{healthsummary}) {
 | 
						|
                $chassiswidevitals{healthsummary} = collect_health_summary();
 | 
						|
            }
 | 
						|
            foreach (values %{ $chassiswidevitals{healthsummary}->{$slot} }) {
 | 
						|
                push @output, "Status: " . $_->{severity} . ", " . $_->{detail};
 | 
						|
            }
 | 
						|
            foreach (@moreslots) {
 | 
						|
                foreach (values %{ $chassiswidevitals{healthsummary}->{$_} }) {
 | 
						|
                    push @output, "Status: " . $_->{severity} . ", " . $_->{detail};
 | 
						|
                }
 | 
						|
            }
 | 
						|
        }
 | 
						|
 | 
						|
        my %ledresults = ();
 | 
						|
        my $ledstring  = "";
 | 
						|
        if (grep /led/, @vitems) {
 | 
						|
            $session = new SNMP::Session(
 | 
						|
                DestHost   => $mpa,
 | 
						|
                Version    => '3',
 | 
						|
                SecName    => $mpauser,
 | 
						|
                AuthProto  => 'SHA',
 | 
						|
                AuthPass   => $mpapass,
 | 
						|
                PrivProto  => 'DES',
 | 
						|
                SecLevel   => 'authPriv',
 | 
						|
                UseNumeric => 1,
 | 
						|
                Retries => 1,    # Give up sooner to make commands go smoother
 | 
						|
                Timeout => 300000000, #Beacon, for one, takes a bit over a second to return
 | 
						|
                PrivPass => $mpapass);
 | 
						|
            my @bindset = (
 | 
						|
                [ $erroroid,  $slot ],
 | 
						|
                [ $beaconoid, $slot ],
 | 
						|
                [ $infooid,   $slot ],
 | 
						|
                [ $kvmoid,    $slot ],
 | 
						|
                [ $mtoid,     $slot ],
 | 
						|
            );
 | 
						|
            my $bindlist = new SNMP::VarList(@bindset);
 | 
						|
            $session->get($bindlist);
 | 
						|
            foreach (@$bindlist) {
 | 
						|
                $ledresults{ $_->[0] . "." . $_->[1] } = $_->[2];
 | 
						|
            }
 | 
						|
        }
 | 
						|
        if (grep /errorled/, @vitems) {
 | 
						|
            my $stat = $ledresults{ "." . $erroroid . "." . $slot }; #$session->get([$erroroid.".".$slot]);
 | 
						|
            if ($stat == 1) {
 | 
						|
                $ledstring = 1;
 | 
						|
                push @output, "Error LED: on";
 | 
						|
            }
 | 
						|
 | 
						|
            #$tmp="Error led: ".$stat;
 | 
						|
        }
 | 
						|
 | 
						|
        if (grep /beaconled/, @vitems) {
 | 
						|
            my $stat = $ledresults{ "." . $beaconoid . "." . $slot }; #$session->get([$beaconoid.".".$slot]);
 | 
						|
            if    ($stat == 1) { $stat = "on"; }
 | 
						|
            elsif ($stat == 2) { $stat = "blinking"; }
 | 
						|
            if    ($stat) {
 | 
						|
                $ledstring = 1;
 | 
						|
                $tmp       = "Beacon led: " . $stat;
 | 
						|
                push @output, "$tmp";
 | 
						|
            }
 | 
						|
        }
 | 
						|
 | 
						|
        if (grep /infoled/, @vitems) {
 | 
						|
            my $stat = $ledresults{ "." . $infooid . "." . $slot }; #$session->get([$infooid.".".$slot]);
 | 
						|
            if ($stat == 1) {
 | 
						|
                $ledstring = 1;
 | 
						|
                push @output, "Info led: on";
 | 
						|
            }
 | 
						|
        }
 | 
						|
 | 
						|
        if (grep /kvmled/, @vitems) {
 | 
						|
            my $stat = $ledresults{ "." . $kvmoid . "." . $slot }; #$session->get([$kvmoid.".".$slot]);
 | 
						|
            if    ($stat == 1) { $stat = "on"; }
 | 
						|
            elsif ($stat == 2) { $stat = "blinking"; }
 | 
						|
            if    ($stat) {
 | 
						|
                $ledstring = 1;
 | 
						|
                $tmp       = "KVM led: " . $stat;
 | 
						|
                push @output, $tmp;
 | 
						|
            }
 | 
						|
        }
 | 
						|
 | 
						|
        if (grep /mtled/, @vitems) {
 | 
						|
            my $stat = $ledresults{ "." . $mtoid . "." . $slot }; #$session->get([$mtoid.".".$slot]);
 | 
						|
            if    ($stat == 1) { $stat = "on"; }
 | 
						|
            elsif ($stat == 2) { $stat = "blinking"; }
 | 
						|
            if    ($stat) {
 | 
						|
                $ledstring = 1;
 | 
						|
                $tmp       = "MT led: " . $stat;
 | 
						|
                push @output, "$tmp";
 | 
						|
            }
 | 
						|
        }
 | 
						|
        if (grep /led/, @vitems and not $ledstring) {
 | 
						|
            push @output, "No active LEDS";
 | 
						|
        }
 | 
						|
 | 
						|
    } else {    #-- chassis query
 | 
						|
 | 
						|
        if (grep /blower/, @vitems) {
 | 
						|
            foreach (@{ $chassiswidevitals{blower} }) {
 | 
						|
                push @output, $_;
 | 
						|
            }
 | 
						|
        } elsif (grep /fan/, @vitems) {
 | 
						|
            foreach (@{ $chassiswidevitals{blower} }) {
 | 
						|
                push @output, $_;
 | 
						|
            }
 | 
						|
            foreach (@{ $chassiswidevitals{fan} }) {
 | 
						|
                push @output, $_;
 | 
						|
            }
 | 
						|
        }
 | 
						|
 | 
						|
 | 
						|
        if ((grep /volt/, @vitems) and ($mpatype ne 'cmm')) {
 | 
						|
            my $voltbase = "1.3.6.1.4.1.2.3.51.2.2.2.1";
 | 
						|
            my %voltlabels = (1 => "+5V", 2 => "+3.3V", 3 => "+12V", 5 => "-5V", 6 => "+2.5V", 8 => "+1.8V");
 | 
						|
            foreach my $idx (keys %voltlabels) {
 | 
						|
                $tmp = $session->get(["$voltbase.$idx.0"]);
 | 
						|
                unless ((not $tmp) or $tmp =~ /Not Readable/) {
 | 
						|
                    push @output, sprintf("Voltage %s: %s", $voltlabels{$idx}, $tmp);
 | 
						|
                }
 | 
						|
                if ($tmp =~ /^NOSUCH/) {
 | 
						|
                    verbose_message("OID:$voltbase.$idx.0, value:$tmp.");
 | 
						|
                }
 | 
						|
            }
 | 
						|
        }
 | 
						|
 | 
						|
        if (grep /ammtemp/, @vitems) {
 | 
						|
            $tmp = $session->get([".1.3.6.1.4.1.2.3.51.2.2.1.1.2.0"]);
 | 
						|
 | 
						|
            #push @output,sprintf("AMM temp: %s",$tmp) if $tmp !~ /NOSUCHINSTANCE/;
 | 
						|
            push @output, sprintf("AMM temp: %s", $tmp) if $tmp !~ /^NOSUCH/;
 | 
						|
            if ($tmp =~ /^NOSUCH/) {
 | 
						|
                verbose_message("OID:.1.3.6.1.4.1.2.3.51.2.2.1.1.2.0, value:$tmp.");
 | 
						|
            }
 | 
						|
        }
 | 
						|
 | 
						|
        if (grep /ambient/, @vitems) {
 | 
						|
            my %oids = ();
 | 
						|
            if ($mpatype ne 'cmm') {
 | 
						|
                %oids = (
 | 
						|
                    "Ambient 1", ".1.3.6.1.4.1.2.3.51.2.2.1.5.1.0",
 | 
						|
                    "Ambient 2", ".1.3.6.1.4.1.2.3.51.2.2.1.5.2",
 | 
						|
                );
 | 
						|
            } else {
 | 
						|
                %oids = ("Ambient 1", ".1.3.6.1.4.1.2.3.51.2.2.1.5.1.0");
 | 
						|
            }
 | 
						|
            foreach my $oid (keys %oids) {
 | 
						|
                $tmp = $session->get([ $oids{$oid} ]);
 | 
						|
 | 
						|
                #push @output,sprintf("%s: %s",$oid,$tmp) if $tmp !~ /NOSUCHINSTANCE/;
 | 
						|
                push @output, sprintf("%s: %s", $oid, $tmp) if $tmp !~ /^NOSUCH/;
 | 
						|
                if ($tmp =~ /^NOSUCH/) {
 | 
						|
                    verbose_message("OID:$oids{$oid}, value:$tmp.");
 | 
						|
                }
 | 
						|
            }
 | 
						|
        }
 | 
						|
 | 
						|
        if (grep /watt/, @vitems) {
 | 
						|
            $tmp = $session->get([".1.3.6.1.4.1.2.3.51.2.2.10.5.1.2.0"]);
 | 
						|
 | 
						|
            #push @output,sprintf("Total power used: %s (%d BTUs/hr)",$tmp,int($tmp * 3.412+0.5)) if $tmp !~ /NOSUCHINSTANCE/;
 | 
						|
            push @output, sprintf("Total power used: %s (%d BTUs/hr)", $tmp, int($tmp * 3.412 + 0.5)) if $tmp !~ /^NOSUCH/;
 | 
						|
            if ($tmp =~ /^NOSUCH/) {
 | 
						|
                verbose_message("OID:.1.3.6.1.4.1.2.3.51.2.2.10.5.1.2.0, value:$tmp.");
 | 
						|
            }
 | 
						|
        }
 | 
						|
 | 
						|
 | 
						|
        if (grep /power/, @vitems) {
 | 
						|
            my %oids = ();
 | 
						|
            if ($mpatype ne 'cmm') {
 | 
						|
                %oids = (
 | 
						|
                    "PD1", ".1.3.6.1.4.1.2.3.51.2.2.10.1.1.1.3.1",
 | 
						|
                    "PD2", ".1.3.6.1.4.1.2.3.51.2.2.10.1.1.1.3.2",
 | 
						|
                  ); }
 | 
						|
            else {
 | 
						|
                %oids = ("PD1", ".1.3.6.1.4.1.2.3.51.2.2.10.1.1.1.3.1");
 | 
						|
            }
 | 
						|
            foreach my $oid (keys %oids) {
 | 
						|
                $tmp = $session->get([ $oids{$oid} ]);
 | 
						|
 | 
						|
                #push @output,sprintf("%s: %s",$oid,$tmp) if $tmp !~ /NOSUCHINSTANCE/;
 | 
						|
                push @output, sprintf("%s: %s", $oid, $tmp) if $tmp !~ /^NOSUCH/;
 | 
						|
                if ($tmp =~ /^NOSUCH/) {
 | 
						|
                    verbose_message("OID:$oids{$oid}, value:$tmp.");
 | 
						|
                }
 | 
						|
            }
 | 
						|
        }
 | 
						|
 | 
						|
 | 
						|
        if (grep /errorled/, @vitems) {
 | 
						|
            my $stat = $session->get([$chassiserroroid]);
 | 
						|
            if ($stat == 0) { $stat = "off"; } elsif ($stat == 1) { $stat = "on"; }
 | 
						|
            $tmp = "Error led: " . $stat;
 | 
						|
            push @output, "$tmp";
 | 
						|
        }
 | 
						|
 | 
						|
        if (grep /infoled/, @vitems) {
 | 
						|
            my $stat = $session->get([$chassisinfooid]);
 | 
						|
            if ($stat == 0) { $stat = "off"; } elsif ($stat == 1) { $stat = "on"; }
 | 
						|
            $tmp = "Info led: " . $stat;
 | 
						|
            push @output, "$tmp";
 | 
						|
        }
 | 
						|
 | 
						|
        if (grep /templed/, @vitems) {
 | 
						|
            my $stat = $session->get([$chassistempledoid]);
 | 
						|
            if ($stat == 0) { $stat = "off"; } elsif ($stat == 1) { $stat = "on"; }
 | 
						|
            $tmp = "Temp led: " . $stat;
 | 
						|
            push @output, "$tmp";
 | 
						|
        }
 | 
						|
 | 
						|
        if (grep /beaconled/, @vitems) {
 | 
						|
            my $stat = $session->get([$chassisbeaconoid]);
 | 
						|
            if ($stat == 0) { $stat = "off"; } elsif ($stat == 1) { $stat = "on"; }
 | 
						|
            elsif ($stat == 2) { $stat = "blinking"; } elsif ($stat == 3) { $stat = "not available"; }
 | 
						|
            $tmp = "Beacon led: " . $stat;
 | 
						|
            push @output, "$tmp";
 | 
						|
        }
 | 
						|
 | 
						|
        if (grep /summary/, @vitems) {
 | 
						|
            $tmp = $session->get([".1.3.6.1.4.1.2.3.51.2.2.7.1.0"]);
 | 
						|
            if ($tmp == 0) { $tmp = "critical"; } elsif ($tmp == 2) { $tmp = "nonCritical"; }
 | 
						|
            elsif ($tmp == 4) { $tmp = "systemLevel"; } elsif ($tmp == 255) { $tmp = "normal"; }
 | 
						|
            push @output, "Status: $tmp";
 | 
						|
        }
 | 
						|
    }
 | 
						|
    return (0, @output);
 | 
						|
}
 | 
						|
 | 
						|
sub populatefanvitals {
 | 
						|
 | 
						|
    #This function populates the fan section of the chassis wide vitals hash
 | 
						|
    $chassiswidevitals{fan} = [];
 | 
						|
    my @bindlist = (
 | 
						|
        [ "1.3.6.1.4.1.2.3.51.2.2.6.1.1.3", 1 ],
 | 
						|
        [ "1.3.6.1.4.1.2.3.51.2.2.6.1.1.3", 2 ],
 | 
						|
        [ "1.3.6.1.4.1.2.3.51.2.2.6.1.1.3", 3 ],
 | 
						|
        [ "1.3.6.1.4.1.2.3.51.2.2.6.1.1.3", 4 ],
 | 
						|
        [ "1.3.6.1.4.1.2.3.51.2.2.6.1.1.5", 1 ],
 | 
						|
        [ "1.3.6.1.4.1.2.3.51.2.2.6.1.1.5", 2 ],
 | 
						|
        [ "1.3.6.1.4.1.2.3.51.2.2.6.1.1.5", 3 ],
 | 
						|
        [ "1.3.6.1.4.1.2.3.51.2.2.6.1.1.5", 4 ],
 | 
						|
        [ "1.3.6.1.4.1.2.3.51.2.2.6.1.1.6", 1 ],
 | 
						|
        [ "1.3.6.1.4.1.2.3.51.2.2.6.1.1.6", 2 ],
 | 
						|
        [ "1.3.6.1.4.1.2.3.51.2.2.6.1.1.6", 3 ],
 | 
						|
        [ "1.3.6.1.4.1.2.3.51.2.2.6.1.1.6", 4 ],
 | 
						|
        [ "1.3.6.1.4.1.2.3.51.2.2.6.1.1.7", 1 ],
 | 
						|
        [ "1.3.6.1.4.1.2.3.51.2.2.6.1.1.7", 2 ],
 | 
						|
        [ "1.3.6.1.4.1.2.3.51.2.2.6.1.1.7", 3 ],
 | 
						|
        [ "1.3.6.1.4.1.2.3.51.2.2.6.1.1.7", 4 ],
 | 
						|
    );
 | 
						|
    my $bind = new SNMP::VarList(@bindlist);
 | 
						|
    my %faninfo;
 | 
						|
    $session->get($bind);
 | 
						|
    foreach (@$bind) {
 | 
						|
 | 
						|
        #if ($_->[2] eq "NOSUCHINSTANCE") {
 | 
						|
        if ($_->[2] =~ /^NOSUCH/) {
 | 
						|
            verbose_message("OID:$_->[0].$_->[1], value:$_->[2].");
 | 
						|
            next;
 | 
						|
        }
 | 
						|
        my $restype = $_->[0];
 | 
						|
        $restype =~ s/^.*\.(\d*)$/$1/;
 | 
						|
        my $idx = $_->[1];
 | 
						|
        if ($restype eq "3") {
 | 
						|
            $faninfo{$idx}->{state} = $_->[2];
 | 
						|
        } elsif ($restype eq "5") {
 | 
						|
            $faninfo{$idx}->{percentage} = $_->[2];
 | 
						|
        } elsif ($restype eq "6") {
 | 
						|
            $faninfo{$idx}->{rpm} = $_->[2];
 | 
						|
        } elsif ($restype eq "7") {
 | 
						|
            $faninfo{$idx}->{cstate} = $_->[2];
 | 
						|
        }
 | 
						|
    }
 | 
						|
    foreach (sort keys %faninfo) {
 | 
						|
        my $text = "Fan pack $_:";
 | 
						|
        if (defined $faninfo{$_}->{rpm}) {
 | 
						|
            $text .= " " . $faninfo{$_}->{rpm};
 | 
						|
            if (defined $faninfo{$_}->{percentage}) {
 | 
						|
                $text .= " (" . $faninfo{$_}->{percentage} . "%)";
 | 
						|
            }
 | 
						|
            $text .= " RPM";
 | 
						|
        } elsif (defined $faninfo{$_}->{percentage}) {
 | 
						|
            $text .= " " . $faninfo{$_}->{percentage} . "% RPM";
 | 
						|
        }
 | 
						|
        if ($faninfo{$_}->{state} eq "2") {
 | 
						|
            $text .= " Warning";
 | 
						|
        } elsif ($faninfo{$_}->{state} eq "3") {
 | 
						|
            $text .= " Error";
 | 
						|
        }
 | 
						|
        if ($faninfo{$_}->{cstate} eq "1") {
 | 
						|
            $text .= " (firmware update in progress)";
 | 
						|
        } elsif ($faninfo{$_}->{cstate} eq "2") {
 | 
						|
            $text .= " (not present)";
 | 
						|
        } elsif ($faninfo{$_}->{cstate} eq "3") {
 | 
						|
            $text .= " (communication failure";
 | 
						|
        }
 | 
						|
        push @{ $chassiswidevitals{fan} }, $text;
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
sub by_number {
 | 
						|
    if ($a < $b) {
 | 
						|
        -1;
 | 
						|
    } elsif ($a > $b) {
 | 
						|
        1;
 | 
						|
    } else {
 | 
						|
        0;
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
sub populateblowervitals {
 | 
						|
    $chassiswidevitals{blower} = [];
 | 
						|
    my %blowerstats = ();
 | 
						|
    my @bindoid     = ();
 | 
						|
    if ($mpatype ne 'cmm') {
 | 
						|
        @bindoid = (
 | 
						|
            [ $blower1speedoid,     "0" ],
 | 
						|
            [ $blower2speedoid,     "0" ],
 | 
						|
            [ $blower3speedoid,     "0" ],
 | 
						|
            [ $blower4speedoid,     "0" ],
 | 
						|
            [ $blower1stateoid,     "0" ],
 | 
						|
            [ $blower2stateoid,     "0" ],
 | 
						|
            [ $blower3stateoid,     "0" ],
 | 
						|
            [ $blower4stateoid,     "0" ],
 | 
						|
            [ $blower1rpmoid,       "0" ],
 | 
						|
            [ $blower2rpmoid,       "0" ],
 | 
						|
            [ $blower3rpmoid,       "0" ],
 | 
						|
            [ $blower4rpmoid,       "0" ],
 | 
						|
            [ $blower1contstateoid, "0" ],
 | 
						|
            [ $blower2contstateoid, "0" ],
 | 
						|
            [ $blower3contstateoid, "0" ],
 | 
						|
            [ $blower4contstateoid, "0" ],
 | 
						|
        );
 | 
						|
    } else {
 | 
						|
        foreach my $fanentry (3 .. 6) {
 | 
						|
            foreach (1 .. 10) {
 | 
						|
                push @bindoid, [ $chassisfanbase . $fanentry, "$_" ];
 | 
						|
            }
 | 
						|
        }
 | 
						|
    }
 | 
						|
    my $bind = new SNMP::VarList(@bindoid);
 | 
						|
    $session->get($bind);
 | 
						|
    foreach (@$bind) {
 | 
						|
 | 
						|
        #if ($_->[2] eq "NOSUCHINSTANCE") {
 | 
						|
        if ($_->[2] =~ /^NOSUCH/) {
 | 
						|
            verbose_message("OID:$_->[0].$_->[1], value:$_->[2].");
 | 
						|
            next;
 | 
						|
        }
 | 
						|
        if ($mpatype ne 'cmm') {
 | 
						|
            my $idx = $_->[0];
 | 
						|
            $idx =~ s/^.*\.(\d*)$/$1/;
 | 
						|
            if ($idx < 10) {
 | 
						|
                $blowerstats{$idx}->{percentage} = $_->[2];
 | 
						|
                $blowerstats{$idx}->{percentage} =~ s/^[^\d]*(\d*)[^\d].*$/$1/;
 | 
						|
            } elsif ($idx < 20) {
 | 
						|
                $blowerstats{ $idx - 9 }->{state} = $_->[2];
 | 
						|
            } elsif ($idx < 30) {
 | 
						|
                $blowerstats{ $idx - 19 }->{rpm} = $_->[2];
 | 
						|
            } elsif ($idx < 40) {
 | 
						|
                $blowerstats{ $idx - 29 }->{cstate} = $_->[2];
 | 
						|
            }
 | 
						|
        } else {
 | 
						|
            my $idx      = $_->[1];
 | 
						|
            my $tmp_type = $_->[0];
 | 
						|
            $tmp_type =~ s/^.*\.(\d*)$/$1/;
 | 
						|
            if ($tmp_type == 3) {
 | 
						|
                $blowerstats{$idx}->{percentage} = $_->[2];
 | 
						|
                $blowerstats{$idx}->{percentage} =~ s/^(\d*)%.*$/$1/;
 | 
						|
            } elsif ($tmp_type == 4) {
 | 
						|
                $blowerstats{$idx}->{state} = $_->[2];
 | 
						|
            } elsif ($tmp_type == 5) {
 | 
						|
                $blowerstats{$idx}->{rpm} = $_->[2];
 | 
						|
            } elsif ($tmp_type == 6) {
 | 
						|
                $blowerstats{$idx}->{cstate} = $_->[2];
 | 
						|
            }
 | 
						|
        }
 | 
						|
    }
 | 
						|
    foreach my $blowidx (sort by_number keys %blowerstats) {
 | 
						|
        my $bdata = $blowerstats{$blowidx};
 | 
						|
        my $text  = "Blower/Fan $blowidx:";
 | 
						|
        if (defined $bdata->{rpm}) {
 | 
						|
            $text .= $bdata->{rpm} . " RPM (" . $bdata->{percentage} . "%)";
 | 
						|
        } else {
 | 
						|
            $text .= $bdata->{percentage} . "% RPM";
 | 
						|
        }
 | 
						|
        if ($bdata->{state} == 2) {
 | 
						|
            $text .= " Warning state";
 | 
						|
        } elsif ($bdata->{state} == 3) {
 | 
						|
            $text .= " Bad state";
 | 
						|
        } elsif ($bdata->{state} == 0) {
 | 
						|
            $text .= " Unknown state";
 | 
						|
        } elsif ($bdata->{state} == 1) {
 | 
						|
            $text .= " Good state";
 | 
						|
        }
 | 
						|
        if ($bdata->{cstate} == 1) {
 | 
						|
            $text .= " Controller flashing";
 | 
						|
        } elsif ($bdata->{cstate} == 2) {
 | 
						|
            $text .= " Not present";
 | 
						|
        } elsif ($bdata->{cstate} == 3) {
 | 
						|
            $text .= " Communication failure to controller";
 | 
						|
        }
 | 
						|
        push @{ $chassiswidevitals{blower} }, $text;
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
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 u))) {
 | 
						|
        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"));
 | 
						|
    }
 | 
						|
 | 
						|
    # Get the mm type from the telnet cli
 | 
						|
    my $mmtypestr;
 | 
						|
    if (defined($telnetrscan{'mm'}) && defined($telnetrscan{'mm'}{'type'})) {
 | 
						|
        $mmtypestr = $telnetrscan{'mm'}{'type'};
 | 
						|
    } else {
 | 
						|
        $mmtypestr = "mm";
 | 
						|
    }
 | 
						|
 | 
						|
    my $mmname = $session->get([ $mmoname->{$mptype}, 0 ]);
 | 
						|
    if ($session->{ErrorStr}) {
 | 
						|
        return (1, $session->{ErrorStr});
 | 
						|
    }
 | 
						|
    my $mmtype = $session->get([ $mmotype, 0 ]);
 | 
						|
    if ($session->{ErrorStr}) {
 | 
						|
        return (1, $session->{ErrorStr});
 | 
						|
    }
 | 
						|
    my $mmmodel = $session->get([ $mmomodel, 0 ]);
 | 
						|
    if ($session->{ErrorStr}) {
 | 
						|
        return (1, $session->{ErrorStr});
 | 
						|
    }
 | 
						|
    my $mmserial = $session->get([ $mmoserial, 0 ]);
 | 
						|
    if ($session->{ErrorStr}) {
 | 
						|
        return (1, $session->{ErrorStr});
 | 
						|
    }
 | 
						|
    push @values, join(",", $mmtypestr, $mmname, 0, "$mmtype$mmmodel", $mmserial, $mpa, $mpa);
 | 
						|
    my $namemax = length($mmname);
 | 
						|
    my $mpamax  = length($mpa);
 | 
						|
 | 
						|
    foreach (1 .. 14) {
 | 
						|
        my $tmp = $session->get([ $bladexistsoid . ".$_" ]);
 | 
						|
        if ($tmp == 1) {
 | 
						|
            my $type = $session->get([ $blademtmoid, $_ ]);
 | 
						|
            if ($session->{ErrorStr}) {
 | 
						|
                return (1, $session->{ErrorStr});
 | 
						|
            }
 | 
						|
            $type =~ s/Not available/null/i;
 | 
						|
 | 
						|
            my $model = $session->get([ $bladeomodel, $_ ]);
 | 
						|
            if ($session->{ErrorStr}) {
 | 
						|
                return (1, $session->{ErrorStr});
 | 
						|
            }
 | 
						|
            $model =~ s/Not available/null/i;
 | 
						|
 | 
						|
            my $serial = $session->get([ $bladeserialoid, $_ ]);
 | 
						|
            if ($session->{ErrorStr}) {
 | 
						|
                return (1, $session->{ErrorStr});
 | 
						|
            }
 | 
						|
            $serial =~ s/Not available/null/i;
 | 
						|
 | 
						|
            my $name = $session->get([ $bladeoname, $_ ]);
 | 
						|
            if ($session->{ErrorStr}) {
 | 
						|
                return (1, $session->{ErrorStr});
 | 
						|
            }
 | 
						|
 | 
						|
            # The %telnetrscan has the entires for the fsp. For NGP ppc blade, set the ip of fsp.
 | 
						|
            if (defined($telnetrscan{$_}{'0'}) && $telnetrscan{$_}{'0'}{'type'} eq "fsp") {
 | 
						|
 | 
						|
                # give the NGP ppc blade an internal specific name to identify
 | 
						|
                push @values, join(",", "ppcblade", $name, $_, "$type$model", $serial, $mpa, $telnetrscan{$_}{'0'}{'ip'});
 | 
						|
            } elsif (defined($telnetrscan{$_}{'1'}) && $telnetrscan{$_}{'1'}{'type'} eq "fsp") {
 | 
						|
 | 
						|
                # give the NGP ppc blade an internal specific name to identify
 | 
						|
                push @values, join(",", "ppcblade", $name, $_, "$type$model", $serial, $mpa, $telnetrscan{$_}{'1'}{'ip'});
 | 
						|
            } elsif (defined($telnetrscan{$_}{'0'}) && $telnetrscan{$_}{'0'}{'type'} eq "bmc") {
 | 
						|
 | 
						|
                # give the NGP x blade an internal specific name to identify
 | 
						|
                push @values, join(",", "xblade", $name, $_, "$type$model", $serial, $mpa, $telnetrscan{$_}{'0'}{'ip'});
 | 
						|
            } else {
 | 
						|
                push @values, join(",", "blade", $name, $_, "$type$model", $serial, $mpa, "");
 | 
						|
            }
 | 
						|
 | 
						|
            my $namelength = length($name);
 | 
						|
            $namemax = ($namelength > $namemax) ? $namelength : $namemax;
 | 
						|
            my $mpalength = length($mpa);
 | 
						|
            $mpamax = ($mpalength > $mpamax) ? $mpalength : $mpamax;
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
 | 
						|
    if (defined($has_x222)) {
 | 
						|
        foreach (sort (keys %x222_info)) {
 | 
						|
            my $name       = $x222_info{$_}{node_name};
 | 
						|
            my $namelength = length($name);
 | 
						|
            my $type       = $x222_info{$_}{type};
 | 
						|
            my $mtm        = $x222_info{$_}{mtm};
 | 
						|
            my $serial     = $x222_info{$_}{serial};
 | 
						|
            my $slotid     = $x222_info{$_}{slotid};
 | 
						|
            my $ip = (defined($x222_info{$_}{'0'})) ? ($x222_info{$_}{'0'}{'ip'}) : ($x222_info{$_}{'1'}{'ip'});
 | 
						|
            $namemax = ($namemax > $namelength) ? $namemax : $namelength;
 | 
						|
 | 
						|
            if (defined $type) {
 | 
						|
                push @values, join(",", $type, $name, $slotid, $mtm, $serial, $mpa, $ip);
 | 
						|
            }
 | 
						|
        }
 | 
						|
    }
 | 
						|
    my $format = sprintf "%%-%ds", ($namemax + 2);
 | 
						|
    $rscan_header[1][1] = $format;
 | 
						|
    $format = sprintf "%%-%ds", ($mpamax + 2);
 | 
						|
    $rscan_header[5][1] = $format;
 | 
						|
 | 
						|
    if (exists($opt{x})) {
 | 
						|
        $result = rscan_xml($mpa, \@values);
 | 
						|
    }
 | 
						|
    elsif (exists($opt{z})) {
 | 
						|
        $result = rscan_stanza($mpa, \@values);
 | 
						|
    }
 | 
						|
    else {
 | 
						|
        foreach (@rscan_header) {
 | 
						|
            $result .= sprintf @$_[1], @$_[0];
 | 
						|
        }
 | 
						|
        foreach (@values) {
 | 
						|
            my @data = split /,/;
 | 
						|
            if ($data[0] eq "ppcblade" or $data[0] eq "xblade") {
 | 
						|
                $data[0] = "blade";
 | 
						|
            }
 | 
						|
            my $i = 0;
 | 
						|
 | 
						|
            foreach (@rscan_header) {
 | 
						|
                $result .= sprintf @$_[1], $data[ $i++ ];
 | 
						|
            }
 | 
						|
        }
 | 
						|
    }
 | 
						|
    if (!exists($opt{w}) && !exists($opt{u})) {
 | 
						|
        return (0, $result);
 | 
						|
    }
 | 
						|
    my @tabs = qw(mp nodehm nodelist nodetype vpd ppc ipmi);
 | 
						|
    my %db   = ();
 | 
						|
 | 
						|
    foreach (@tabs) {
 | 
						|
        $db{$_} = xCAT::Table->new($_, -create => 1, -autocommit => 0);
 | 
						|
        if (!$db{$_}) {
 | 
						|
            return (1, "Error opening '$_'");
 | 
						|
        }
 | 
						|
    }
 | 
						|
    my @msg4update;
 | 
						|
    foreach (@values) {
 | 
						|
        my @data   = split /,/;
 | 
						|
        my $type   = $data[0];
 | 
						|
        my $name   = $data[1];
 | 
						|
        my $id     = $data[2];
 | 
						|
        my $mtm    = $data[3];
 | 
						|
        my $serial = $data[4];
 | 
						|
        my $ip     = $data[6];
 | 
						|
 | 
						|
        # ignore the blade server which status is 'Comm Error'
 | 
						|
        if ($name =~ /Comm Error/) {
 | 
						|
            next;
 | 
						|
        }
 | 
						|
        if ($data[1] =~ /\(\s*([^\s]*)\s*\)/) {
 | 
						|
            $name = $1;
 | 
						|
        } elsif ($data[1] =~ /^\s*([^s]*)\s*$/) {
 | 
						|
            $name = $1;
 | 
						|
            $name =~ s/ /_/;
 | 
						|
            $name =~ tr/A-Z/a-z/;
 | 
						|
        }
 | 
						|
        if (exists($opt{u})) {
 | 
						|
            ## TRACE_LINE print "Rscan: orig_name [$name]\n";
 | 
						|
 | 
						|
            # search the existed node for updating
 | 
						|
            # for the cmm, using the type-serial number to match
 | 
						|
            my $matched = 0;
 | 
						|
            if ($type eq "cmm") {
 | 
						|
                my @vpdlist = $db{vpd}->getAllNodeAttribs([ 'node', 'serial', 'mtm' ]);
 | 
						|
                foreach (@vpdlist) {
 | 
						|
                    if ($_->{'mtm'} eq $mtm && $_->{'serial'} eq $serial) {
 | 
						|
                        push @msg4update, sprintf("%-7s$format Matched To =>$format", $type, '[' . $name . ']', '[' . $_->{'node'} . ']');
 | 
						|
                        $name    = $_->{'node'};
 | 
						|
                        $matched = 1;
 | 
						|
                        last;
 | 
						|
                    }
 | 
						|
                }
 | 
						|
            } elsif ($type eq "blade" || $type eq "ppcblade" || $type eq "xblade") {
 | 
						|
 | 
						|
                # for the blade server, using the mp.mpa and mp.id to match
 | 
						|
                my @mplist = $db{mp}->getAllNodeAttribs([ 'node', 'mpa', 'id' ]);
 | 
						|
                foreach (@mplist) {
 | 
						|
                    if ($_->{'mpa'} eq $mpa && $_->{'id'} eq $id) {
 | 
						|
                        push @msg4update, sprintf("%-7s$format Matched To =>$format", "blade", '[' . $name . ']', '[' . $_->{'node'} . ']');
 | 
						|
                        $name    = $_->{'node'};
 | 
						|
                        $matched = 1;
 | 
						|
                        last;
 | 
						|
                    }
 | 
						|
                }
 | 
						|
            }
 | 
						|
 | 
						|
            ## TRACE_LINE print "Rscan: matched_name[$name]\n";
 | 
						|
            if (!$matched) {
 | 
						|
                my $displaytype = ($type eq "ppcblade") ? "blade" : $type;
 | 
						|
                push @msg4update, sprintf("%-7s$format NOT Matched. MM [%s]: Slot ID [%s]", $displaytype, '[' . $name . ']', $mpa, $id);
 | 
						|
                next;
 | 
						|
            }
 | 
						|
        }
 | 
						|
 | 
						|
        # Update the ppc table for the fsp and ppcblade
 | 
						|
        my ($k1, $u1);
 | 
						|
        $k1->{node} = $name;
 | 
						|
        if ($type eq "ppcblade") {
 | 
						|
 | 
						|
            #$u1->{hcp} = $ip;
 | 
						|
            $u1->{nodetype} = "blade";
 | 
						|
            $u1->{id}       = "1";
 | 
						|
            $u1->{parent}   = $mpa;
 | 
						|
            $db{ppc}->setAttribs($k1, $u1);
 | 
						|
            $db{ppc}{commit} = 1;
 | 
						|
        }
 | 
						|
 | 
						|
        # Update the entry in mp table for ppcblade and general blade
 | 
						|
        my ($k11, $u11);
 | 
						|
        $k11->{node} = $name;
 | 
						|
        $u11->{mpa}  = $mpa;
 | 
						|
        $u11->{id}   = $id;
 | 
						|
        if ($type eq "ppcblade") {
 | 
						|
            $u11->{nodetype} = "blade";
 | 
						|
        } elsif ($type eq "xblade") {
 | 
						|
            $u11->{nodetype} = "blade";
 | 
						|
        } else {
 | 
						|
            $u11->{nodetype} = $type;
 | 
						|
        }
 | 
						|
        $db{mp}->setAttribs($k11, $u11);
 | 
						|
        $db{mp}{commit} = 1;
 | 
						|
 | 
						|
        # Update the entry in nodehm table
 | 
						|
        my ($k2, $u2);
 | 
						|
        $k2->{node} = $name;
 | 
						|
        if ($type eq "ppcblade") {
 | 
						|
            $u2->{mgt}  = "fsp";
 | 
						|
            $u2->{cons} = "fsp";
 | 
						|
        } elsif ($type eq "xblade") {
 | 
						|
            $u2->{mgt}  = "ipmi";
 | 
						|
            $u2->{cons} = "ipmi";
 | 
						|
        } else {
 | 
						|
            $u2->{mgt} = "blade";
 | 
						|
            if ($type eq "blade") {
 | 
						|
                $u2->{cons} = "blade";
 | 
						|
            }
 | 
						|
        }
 | 
						|
        $db{nodehm}->setAttribs($k2, $u2);
 | 
						|
        $db{nodehm}{commit} = 1;
 | 
						|
 | 
						|
        # Update the entry in nodelist table
 | 
						|
        my ($k3, $u3);
 | 
						|
        $k3->{node} = $name;
 | 
						|
        my $append;
 | 
						|
        if (($type eq "ppcblade") or ($type eq "xblade")) {
 | 
						|
            $append = "blade";
 | 
						|
        } else {
 | 
						|
            $append = $type;
 | 
						|
        }
 | 
						|
        $u3->{groups} = $append . ",all";
 | 
						|
        my $tmp_groups = $db{nodelist}->getNodeAttribs($name, ['groups']);
 | 
						|
        if (defined($tmp_groups) and defined($tmp_groups->{groups})) {
 | 
						|
            $u3->{groups} = $tmp_groups->{groups};
 | 
						|
            my @groups_array = split /,/, $tmp_groups->{groups};
 | 
						|
            if (!grep(/^$append$/, @groups_array)) {
 | 
						|
                $u3->{groups} .= ",$append";
 | 
						|
            }
 | 
						|
            if (!grep(/^all$/, @groups_array)) {
 | 
						|
                $u3->{groups} .= ",all";
 | 
						|
            }
 | 
						|
        }
 | 
						|
        $db{nodelist}->setAttribs($k3, $u3);
 | 
						|
        $db{nodelist}{commit} = 1;
 | 
						|
 | 
						|
        # Update the entry in nodetype table
 | 
						|
        my ($k4, $u4);
 | 
						|
        $k4->{node} = $name;
 | 
						|
        if ($type eq "ppcblade") {
 | 
						|
            $u4->{nodetype} = "ppc,osi";
 | 
						|
        } elsif ($type eq "blade") {
 | 
						|
            $u4->{nodetype} = "mp,osi";
 | 
						|
        } elsif ($type eq "mm" || $type eq "cmm" || $type eq "xblade") {
 | 
						|
            $u4->{nodetype} = "mp";
 | 
						|
        }
 | 
						|
        $db{nodetype}->setAttribs($k4, $u4);
 | 
						|
        $db{nodetype}{commit} = 1;
 | 
						|
 | 
						|
        # Update the entry in vpd table
 | 
						|
        my ($k5, $u5);
 | 
						|
        $k5->{node}   = $name;
 | 
						|
        $u5->{mtm}    = $data[3];
 | 
						|
        $u5->{serial} = $data[4];
 | 
						|
        $db{vpd}->setAttribs($k5, $u5);
 | 
						|
        $db{vpd}{commit} = 1;
 | 
						|
 | 
						|
        # Update the entry in ipmi table for x blade
 | 
						|
        if ($type eq "xblade") {
 | 
						|
            my ($k6, $u6);
 | 
						|
            $k6->{node} = $name;
 | 
						|
            $u6->{bmc}  = $ip;
 | 
						|
            $db{ipmi}->setAttribs($k6, $u6);
 | 
						|
            $db{ipmi}{commit} = 1;
 | 
						|
        }
 | 
						|
    }
 | 
						|
    foreach (@tabs) {
 | 
						|
        if (exists($db{$_}{commit})) {
 | 
						|
            $db{$_}->commit;
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    if (exists($opt{u})) {
 | 
						|
        $result = join("\n", @msg4update);
 | 
						|
    }
 | 
						|
    return (0, $result);
 | 
						|
}
 | 
						|
 | 
						|
sub rscan_xml {
 | 
						|
 | 
						|
    my $mpa    = shift;
 | 
						|
    my $values = shift;
 | 
						|
    my $xml;
 | 
						|
 | 
						|
    foreach (@$values) {
 | 
						|
        my @data     = split /,/;
 | 
						|
        my $i        = 0;
 | 
						|
        my $type     = $data[0];
 | 
						|
        my $origtype = $type;
 | 
						|
        if ($type eq "ppcblade" or $type eq "xblade") {
 | 
						|
            $type = "blade";
 | 
						|
        }
 | 
						|
 | 
						|
        # ignore the blade server which status is 'Comm Error'
 | 
						|
        if ($data[1] =~ /Comm Error/) {
 | 
						|
            next;
 | 
						|
        }
 | 
						|
 | 
						|
        my $href = {
 | 
						|
            Node => {}
 | 
						|
        };
 | 
						|
        my $mtm = undef;
 | 
						|
        foreach (@rscan_attribs) {
 | 
						|
            my $d = $data[ $i++ ];
 | 
						|
 | 
						|
            my $ignore;
 | 
						|
            if (/^name$/) {
 | 
						|
                next;
 | 
						|
            } elsif (/^nodetype$/) {
 | 
						|
                if ($origtype eq "ppcblade") {
 | 
						|
                    $d = "ppc,osi";
 | 
						|
                } elsif ($origtype eq "blade") {
 | 
						|
                    $d = "mp,osi";
 | 
						|
                } else {
 | 
						|
                    $d = "mp";
 | 
						|
                }
 | 
						|
            } elsif (/^groups$/) {
 | 
						|
                $d      = "$type,all";
 | 
						|
                $ignore = 1;
 | 
						|
            } elsif (/^mgt$/) {
 | 
						|
                if ($origtype eq "ppcblade") {
 | 
						|
                    $d = "fsp";
 | 
						|
                } elsif ($origtype eq "xblade") {
 | 
						|
                    $d = "ipmi";
 | 
						|
                } else {
 | 
						|
                    $d = "blade";
 | 
						|
                }
 | 
						|
            } elsif (/^cons$/) {
 | 
						|
                if ($origtype eq "blade") {
 | 
						|
                    $d = "blade";
 | 
						|
                } elsif ($origtype eq "ppcblade") {
 | 
						|
                    $d = "fsp";
 | 
						|
                } elsif ($origtype eq "xblade") {
 | 
						|
                    $d = "ipmi";
 | 
						|
                } else {
 | 
						|
                    $ignore = 1;
 | 
						|
                }
 | 
						|
            } elsif (/^mpa$/) {
 | 
						|
                $d = $mpa;
 | 
						|
            } elsif (/^hwtype$/) {
 | 
						|
                if ($origtype eq "ppcblade" or $origtype eq "xblade") {
 | 
						|
                    $d = "blade";
 | 
						|
                } else {
 | 
						|
                    $d = $type;
 | 
						|
                }
 | 
						|
            } elsif (/^id$/) {
 | 
						|
 | 
						|
                # for the NGP ppc blade, add the slotid to mp.id
 | 
						|
                if ($origtype eq "ppcblade") {
 | 
						|
                    $href->{Node}->{slotid} = $d;
 | 
						|
                    $d = "1";
 | 
						|
                }
 | 
						|
                elsif ($origtype eq "xblade") {
 | 
						|
                    $href->{Node}->{slotid} = $d;
 | 
						|
                    $ignore = 1;
 | 
						|
                }
 | 
						|
            } elsif (/^hcp/) {
 | 
						|
                if ($origtype eq "ppcblade") {
 | 
						|
                    $href->{Node}->{parent} = $mpa;
 | 
						|
                } else {
 | 
						|
                    $ignore = 1;
 | 
						|
                }
 | 
						|
            } elsif (/^mtm$/) {
 | 
						|
                $d =~ /^(\w{4})/;
 | 
						|
                $mtm = $1;
 | 
						|
            }
 | 
						|
 | 
						|
            if (!$ignore) {
 | 
						|
                $href->{Node}->{$_} = $d;
 | 
						|
            }
 | 
						|
        }
 | 
						|
        my $tmp_groups = "$type,all";
 | 
						|
        if (defined($mtm)) {
 | 
						|
            my $tmp_pre = xCAT::data::ibmhwtypes::parse_group($mtm);
 | 
						|
            if (defined($tmp_pre)) {
 | 
						|
                $tmp_groups .= ",$tmp_pre";
 | 
						|
            }
 | 
						|
        }
 | 
						|
        $href->{Node}->{groups} = $tmp_groups;
 | 
						|
        $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];
 | 
						|
        my $origtype = $type;
 | 
						|
        if ($type eq "ppcblade" or $type eq "xblade") {
 | 
						|
            $type = "blade";
 | 
						|
        }
 | 
						|
 | 
						|
        # ignore the blade server which status is 'Comm Error'
 | 
						|
        if ($data[1] =~ /Comm Error/) {
 | 
						|
            next;
 | 
						|
        }
 | 
						|
        my $objname;
 | 
						|
        if ($data[1] =~ /\(\s*([^\s]*)\s*\)/) {
 | 
						|
            $objname = $1;
 | 
						|
        } elsif ($data[1] =~ /^\s*([^s]*)\s*$/) {
 | 
						|
            $objname = $1;
 | 
						|
            $objname =~ s/ /_/;
 | 
						|
            $objname =~ tr/A-Z/a-z/;
 | 
						|
        } else {
 | 
						|
            $objname = $data[1];
 | 
						|
        }
 | 
						|
        $result .= "$objname:\n\tobjtype=node\n";
 | 
						|
        my $mtm = undef;
 | 
						|
        foreach (@rscan_attribs) {
 | 
						|
            my $d = $data[ $i++ ];
 | 
						|
 | 
						|
            my $ignore;
 | 
						|
            if (/^name$/) {
 | 
						|
                next;
 | 
						|
            } elsif (/^nodetype$/) {
 | 
						|
                if ($origtype eq "ppcblade") {
 | 
						|
                    $d = "ppc,osi";
 | 
						|
                } elsif ($origtype eq "blade") {
 | 
						|
                    $d = "mp,osi";
 | 
						|
                } else {
 | 
						|
                    $d = "mp";
 | 
						|
                }
 | 
						|
            } elsif (/^groups$/) {
 | 
						|
                $d      = "$type,all";
 | 
						|
                $ignore = 1;
 | 
						|
            } elsif (/^mgt$/) {
 | 
						|
                if ($origtype eq "ppcblade") {
 | 
						|
                    $d = "fsp";
 | 
						|
                } elsif ($origtype eq "xblade") {
 | 
						|
                    $d = "ipmi";
 | 
						|
                } else {
 | 
						|
                    $d = "blade";
 | 
						|
                }
 | 
						|
            } elsif (/^cons$/) {
 | 
						|
                if ($origtype eq "blade") {
 | 
						|
                    $d = "blade";
 | 
						|
                } elsif ($origtype eq "ppcblade") {
 | 
						|
                    $d = "fsp";
 | 
						|
                } elsif ($origtype eq "xblade") {
 | 
						|
                    $d = "ipmi";
 | 
						|
                } else {
 | 
						|
                    $ignore = 1;
 | 
						|
                }
 | 
						|
            } elsif (/^mpa$/) {
 | 
						|
                $d = $mpa;
 | 
						|
            } elsif (/^hwtype$/) {
 | 
						|
                if ($origtype eq "ppcblade" or $origtype eq "xblade") {
 | 
						|
                    $d = "blade";
 | 
						|
                } else {
 | 
						|
                    $d = $type;
 | 
						|
                }
 | 
						|
            } elsif (/^id$/) {
 | 
						|
 | 
						|
                # for the NGP ppc blade, add the attirbute 'slotid' that match to mp.id
 | 
						|
                if ($origtype eq "ppcblade") {
 | 
						|
                    $result .= "\tslotid=$d\n";
 | 
						|
                    $d = "1";
 | 
						|
                }
 | 
						|
                elsif ($origtype eq "xblade") {
 | 
						|
                    $result .= "\tslotid=$d\n";
 | 
						|
                    $ignore = 1;
 | 
						|
                }
 | 
						|
            } elsif (/^hcp/) {
 | 
						|
                if ($origtype eq "ppcblade") {
 | 
						|
                    $result .= "\tparent=$mpa\n";
 | 
						|
                } else {
 | 
						|
                    $ignore = 1;
 | 
						|
                }
 | 
						|
            } elsif (/^mtm$/) {
 | 
						|
                $d =~ /^(\w{4})/;
 | 
						|
                $mtm = $1;
 | 
						|
            }
 | 
						|
 | 
						|
            if (!$ignore) {
 | 
						|
                $result .= "\t$_=$d\n";
 | 
						|
            }
 | 
						|
        }
 | 
						|
        my $tmp_groups = "$type,all";
 | 
						|
        if (defined($mtm)) {
 | 
						|
            my $tmp_pre = xCAT::data::ibmhwtypes::parse_group($mtm);
 | 
						|
            if (defined($tmp_pre)) {
 | 
						|
                $tmp_groups .= ",$tmp_pre";
 | 
						|
            }
 | 
						|
        }
 | 
						|
        $result .= "\tgroups=$tmp_groups\n";
 | 
						|
    }
 | 
						|
    return ($result);
 | 
						|
}
 | 
						|
 | 
						|
sub getmacs {
 | 
						|
    my ($node, @args) = @_;
 | 
						|
 | 
						|
    my $display    = ();
 | 
						|
    my $byarp      = ();
 | 
						|
    my $installnic = undef;
 | 
						|
 | 
						|
    #foreach my $arg (@args) {
 | 
						|
    #   if ($arg eq "-d") {
 | 
						|
    #      $display = "yes";
 | 
						|
    #   } elsif ($arg eq "--arp") {
 | 
						|
    #      $byarp = "yes";
 | 
						|
    #   }
 | 
						|
    #}
 | 
						|
    while (@args) {
 | 
						|
        my $arg = shift @args;
 | 
						|
        if ($arg eq "-d") {
 | 
						|
            $display = "yes";
 | 
						|
        } elsif ($arg eq "--arp") {
 | 
						|
            $byarp = "yes";
 | 
						|
        } elsif ($arg eq "-i") {
 | 
						|
            $installnic = shift @args;
 | 
						|
            $installnic =~ s/eth|en//;
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    if ($byarp eq "yes") {
 | 
						|
        my $output = xCAT::SvrUtils->get_mac_by_arp([$node], $display);
 | 
						|
        my @ret = ();
 | 
						|
        foreach my $n (keys %$output) {
 | 
						|
            if ($n ne $node) {
 | 
						|
                next;
 | 
						|
            }
 | 
						|
            push @ret, $output->{$n};
 | 
						|
        }
 | 
						|
        return (0, @ret);
 | 
						|
    }
 | 
						|
 | 
						|
    my @macs = ();
 | 
						|
    (my $code, my @orig_macs) = inv($node, 'mac');
 | 
						|
    my $ignore_gen_mac = 0;
 | 
						|
    foreach my $mac (@orig_macs) {
 | 
						|
        if ($mac =~ /(.*) -> (.*)/) {
 | 
						|
 | 
						|
            #Convert JS style mac ranges to pretend to be simple
 | 
						|
            #this is not a guarantee of how the macs work, but
 | 
						|
            #this is as complex as this function can reasonably accomodate
 | 
						|
            #if you need more complexity, the auto-discovery process
 | 
						|
            #can actually cope
 | 
						|
 | 
						|
            my $basemac = $1;
 | 
						|
            my $lastmac = $2;
 | 
						|
            push @macs, $basemac;
 | 
						|
            $basemac =~ s/mac address \d: //i;
 | 
						|
            $lastmac =~ s/mac address \d: //i;
 | 
						|
 | 
						|
            while ($basemac ne $lastmac) {
 | 
						|
                $basemac =~ s/://g;
 | 
						|
 | 
						|
                # Since 32bit Operating System can only handle 32bit integer,
 | 
						|
                # split the mac address as high 24bit and low 24bit
 | 
						|
                $basemac =~ /(......)(......)/;
 | 
						|
                my ($basemac_h6, $basemac_l6) = ($1, $2);
 | 
						|
                my $macnum_l6 = hex($basemac_l6);
 | 
						|
                my $macnum_h6 = hex($basemac_h6);
 | 
						|
                $macnum_l6 += 1;
 | 
						|
                if ($macnum_l6 > 0xFFFFFF) {
 | 
						|
                    $macnum_h6 += 1;
 | 
						|
                }
 | 
						|
                my $newmac_l6 = sprintf("%06X", $macnum_l6);
 | 
						|
                $newmac_l6 =~ /(......)$/;
 | 
						|
                $newmac_l6 = $1;
 | 
						|
                my $newmac_h6 = sprintf("%06X", $macnum_h6);
 | 
						|
                my $newmac = $newmac_h6 . $newmac_l6;
 | 
						|
                $newmac =~ s/(..)(..)(..)(..)(..)(..)/$1:$2:$3:$4:$5:$6/;
 | 
						|
                my $newidx = scalar(@macs) + 1;
 | 
						|
                push @macs, "MAC Address $newidx: " . $newmac;
 | 
						|
 | 
						|
                $basemac = $newmac;
 | 
						|
            }
 | 
						|
 | 
						|
            # If one mac address has -> as a range, this must be a system P blade.
 | 
						|
            # Then ignore the following mac with prefix "mac address"
 | 
						|
            $ignore_gen_mac = 1;
 | 
						|
        } elsif (!$ignore_gen_mac || $mac =~ /\w+ mac address \d:/i) {
 | 
						|
            push @macs, $mac;
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    my $midx = 0;
 | 
						|
    my @midxary;
 | 
						|
    if (defined($installnic)) {
 | 
						|
        push @midxary, $installnic;
 | 
						|
    } else {
 | 
						|
        my $nrtab = xCAT::Table->new('noderes');
 | 
						|
        if ($nrtab) {
 | 
						|
            my $nent = $nrtab->getNodeAttribs($curn, [ 'primarynic', 'installnic' ]);
 | 
						|
            if ($nent) {
 | 
						|
                my $mkey;
 | 
						|
                if (defined $nent->{installnic}) {    #Prefer the install nic
 | 
						|
                    $mkey = "installnic";
 | 
						|
                } elsif (defined $nent->{primarynic}) { #see if primary nic was set
 | 
						|
                    $mkey = "primarynic";
 | 
						|
                }
 | 
						|
                if ($mkey) {
 | 
						|
                    while ($nent->{$mkey} =~ /[en|eth](\d+)/g) {
 | 
						|
                        push @midxary, $1;
 | 
						|
                    }
 | 
						|
                }
 | 
						|
 | 
						|
                #} elsif ($display !~ /yes/){
 | 
						|
                #   return -1, "please set noderes.installnic or noderes.primarynic";
 | 
						|
            }
 | 
						|
            $nrtab->close;
 | 
						|
        }
 | 
						|
    }
 | 
						|
    if ($code == 0) {
 | 
						|
        if ($display =~ /yes/) {
 | 
						|
            my $allmac = join("\n", @macs);
 | 
						|
            return 0, ":The mac address is:\n$allmac";
 | 
						|
        }
 | 
						|
        if (!@midxary) {
 | 
						|
            push @midxary, '0';
 | 
						|
        }
 | 
						|
        my @allmacs;
 | 
						|
        foreach my $midx (@midxary) {
 | 
						|
            (my $macd, my $mac) = split(/:/, $macs[$midx], 2);
 | 
						|
            $mac =~ s/\s+//g;
 | 
						|
            $mac =~ s/(.*)/\L$1/g;
 | 
						|
            if ($macd !~ /mac address \d/i) {
 | 
						|
                return 1, "Unable to retrieve MAC address for interface $midx from Management Module";
 | 
						|
            }
 | 
						|
 | 
						|
            if ($#midxary == 0) { #-- backward compatibility mode - do not add host name to mac.mac if only one iface is used
 | 
						|
                push @allmacs, $mac;
 | 
						|
            } else {
 | 
						|
                push @allmacs, $mac . "!" . $curn . "e" . $midx;
 | 
						|
            }
 | 
						|
        }
 | 
						|
 | 
						|
        my $macstring = join("|", @allmacs);
 | 
						|
        my $mactab = xCAT::Table->new('mac', -create => 1);
 | 
						|
        $mactab->setNodeAttribs($curn, { mac => $macstring });
 | 
						|
        $mactab->close;
 | 
						|
        return 0, ":mac.mac set to $macstring";
 | 
						|
    } else {
 | 
						|
        return $code, $macs[0];
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
sub inv {
 | 
						|
    my $node = shift;
 | 
						|
    my @invitems;
 | 
						|
    my $data;
 | 
						|
    my @output;
 | 
						|
    @ARGV = @_;
 | 
						|
    my $updatetable;
 | 
						|
    GetOptions(
 | 
						|
        "t|table" => \$updatetable,
 | 
						|
    );
 | 
						|
    foreach (@ARGV) {
 | 
						|
        push @invitems, split(/,/, $_);
 | 
						|
    }
 | 
						|
    my $item;
 | 
						|
    unless (scalar(@invitems)) {
 | 
						|
        @invitems = ("all");
 | 
						|
    }
 | 
						|
    my %updatehash;
 | 
						|
    while (my $item = shift @invitems) {
 | 
						|
        if ($item =~ /^all/) {
 | 
						|
            push @invitems, (qw(mtm serial mac firm));
 | 
						|
            next;
 | 
						|
        }
 | 
						|
        if ($item =~ /^firm/) {
 | 
						|
            push @invitems, (qw(bios diag mprom mparom));
 | 
						|
            next;
 | 
						|
        }
 | 
						|
        if ($item =~ /^bios/ and $mptype !~ /mm/) {
 | 
						|
            my $biosver;
 | 
						|
            my $biosbuild;
 | 
						|
            my $biosdate;
 | 
						|
            $biosver = $session->get([ $bladebiosveroid . ".$slot" ]);
 | 
						|
            if ($session->{ErrorStr}) { return (1, $session->{ErrorStr}); }
 | 
						|
            $biosbuild = $session->get([ $bladebiosbuildidoid . ".$slot" ]);
 | 
						|
            if ($session->{ErrorStr}) { return (1, $session->{ErrorStr}); }
 | 
						|
            $biosdate = $session->get([ $bladebiosdateoid . ".$slot" ]);
 | 
						|
            if ($session->{ErrorStr}) { return (1, $session->{ErrorStr}); }
 | 
						|
            push @output, "BIOS: $biosver ($biosbuild $biosdate)";
 | 
						|
        }
 | 
						|
        if ($item =~ /^diag/ and $mptype !~ /mm/) {
 | 
						|
            my $diagver;
 | 
						|
            my $diagdate;
 | 
						|
            my $diagbuild;
 | 
						|
            $data = $session->get([ $bladediagveroid, $slot ]);
 | 
						|
            if ($session->{ErrorStr}) { return (1, $session->{ErrorStr}); }
 | 
						|
            $diagver = $data;
 | 
						|
            $data = $session->get([ $bladediagbuildidoid, $slot ]);
 | 
						|
            if ($session->{ErrorStr}) { return (1, $session->{ErrorStr}); }
 | 
						|
            $diagbuild = $data;
 | 
						|
            $data = $session->get([ $bladediagdateoid, $slot ]);
 | 
						|
            if ($session->{ErrorStr}) { return (1, $session->{ErrorStr}); }
 | 
						|
            $diagdate = $data;
 | 
						|
            push @output, "Diagnostics:  $diagver ($diagbuild $diagdate)";
 | 
						|
        }
 | 
						|
        if ($item =~ /^[sm]prom/ and $mptype !~ /mm/) {
 | 
						|
            my $spver;
 | 
						|
            my $spbuild;
 | 
						|
            $data = $session->get([ $bladempveroid, $slot ]);
 | 
						|
            if ($session->{ErrorStr}) { return (1, $session->{ErrorStr}); }
 | 
						|
            $spver = $data;
 | 
						|
            $data = $session->get([ $bladempbuildidoid, $slot ]);
 | 
						|
            if ($session->{ErrorStr}) { return (1, $session->{ErrorStr}); }
 | 
						|
            $spbuild = $data;
 | 
						|
            push @output, "BMC/Mgt processor:  $spver ($spbuild)";
 | 
						|
        }
 | 
						|
        if ($item =~ /^mparom/) {
 | 
						|
            my $mpabuild;
 | 
						|
            my $mpaver;
 | 
						|
            my $mpadate;
 | 
						|
            $data = $session->get([ $bladempaveroid, $activemm ]);
 | 
						|
            if ($session->{ErrorStr}) { return (1, $session->{ErrorStr}); }
 | 
						|
            $mpaver = $data;
 | 
						|
            $data = $session->get([ $bladempabuildidoid, $activemm ]);
 | 
						|
            if ($session->{ErrorStr}) { return (1, $session->{ErrorStr}); }
 | 
						|
            $mpabuild = $data;
 | 
						|
            $data = $session->get([ $bladempadateoid, $activemm ]);
 | 
						|
            if ($session->{ErrorStr}) { return (1, $session->{ErrorStr}); }
 | 
						|
            $mpadate = $data;
 | 
						|
            push @output, "Management Module firmware: $mpaver ($mpabuild $mpadate)";
 | 
						|
        }
 | 
						|
        if ($item =~ /^model/ or $item =~ /^mtm/) {
 | 
						|
            if ($mptype eq 'cmm') {
 | 
						|
                my $type = $session->get([ '1.3.6.1.4.1.2.3.51.2.2.21.1.1.1', '0' ]);
 | 
						|
                if ($session->{ErrorStr}) { return (1, $session->{ErrorStr}); }
 | 
						|
                my $model = $session->get([ '1.3.6.1.4.1.2.3.51.2.2.21.1.1.2', '0' ]);
 | 
						|
                if ($session->{ErrorStr}) { return (1, $session->{ErrorStr}); }
 | 
						|
                push @output, "Machine Type/Model: " . $type . $model;
 | 
						|
                $updatehash{mtm} = $type . $model;
 | 
						|
            } else {
 | 
						|
                my $type = $session->get([ $blademtmoid, $slot ]);
 | 
						|
                if ($session->{ErrorStr}) { return (1, $session->{ErrorStr}); }
 | 
						|
                my $model = $session->get([ $bladeomodel, $slot ]);
 | 
						|
                if ($session->{ErrorStr}) { return (1, $session->{ErrorStr}); }
 | 
						|
                push @output, "Machine Type/Model: " . $type . $model;
 | 
						|
                $updatehash{mtm} = $type . $model;
 | 
						|
            }
 | 
						|
        }
 | 
						|
        if ($item =~ /^uuid/ or $item =~ /^guid/) {
 | 
						|
            if ($mptype eq 'cmm') {
 | 
						|
                $data = $session->get([ '.1.3.6.1.4.1.2.3.51.2.2.21.2.1.1.6', '1' ]);
 | 
						|
            } elsif ($slot =~ /^(.*):(.*)\z/) {
 | 
						|
                my $idx = "1.1.3.$1.3.$2"; #1.1 means chassis 1, 3.<bay> means blade <bay>, 3.<index> is the offset into the slot
 | 
						|
                $data = $session->get([ $componentuuidoid, $idx ]);
 | 
						|
            } else {
 | 
						|
                $data = $session->get([ $bladeuuidoid, $slot ]);
 | 
						|
            }
 | 
						|
            if ($session->{ErrorStr}) { return (1, $session->{ErrorStr}); }
 | 
						|
            $data =~ s/ //;
 | 
						|
            $data =~ s/ /-/;
 | 
						|
            $data =~ s/ /-/;
 | 
						|
            $data =~ s/ /-/;
 | 
						|
            $data =~ s/ /-/;
 | 
						|
            $data =~ s/ //g;
 | 
						|
            push @output, "UUID/GUID: " . $data;
 | 
						|
            $updatehash{uuid} = $data;
 | 
						|
        }
 | 
						|
        if ($item =~ /^serial/) {
 | 
						|
            if ($mptype eq 'cmm') {
 | 
						|
 | 
						|
                #chassisInfoVpd->chassisVpd->chassisSerialNumber
 | 
						|
                $data = $session->get([ '1.3.6.1.4.1.2.3.51.2.2.21.1.1.3', '0' ]);
 | 
						|
            } else {
 | 
						|
                $data = $session->get([ $bladeserialoid, $slot ]);
 | 
						|
            }
 | 
						|
            if ($session->{ErrorStr}) { return (1, $session->{ErrorStr}); }
 | 
						|
            push @output, "Serial Number: " . $data;
 | 
						|
            $updatehash{serial} = $data;
 | 
						|
        }
 | 
						|
 | 
						|
        #print "item=$item, slot=$slot\n";
 | 
						|
 | 
						|
        if ($item =~ /^mac/) {
 | 
						|
            if ($slot !~ /:/) {
 | 
						|
                foreach (0 .. 3) {
 | 
						|
                    $data = $session->get([ $macoids[$_], $slot ]);
 | 
						|
                    if ($session->{ErrorStr}) { return (1, $session->{ErrorStr}); }
 | 
						|
                    if ($data =~ /:/) {
 | 
						|
                        push @output, "MAC Address " . ($_ + 1) . ": " . $data;
 | 
						|
                    }
 | 
						|
                }
 | 
						|
                foreach (0 .. 3) {
 | 
						|
                    my $oid = $hsdcmacoids[$_] . ".$slot";
 | 
						|
                    $data = $session->get([ $hsdcmacoids[$_], $slot ]);
 | 
						|
 | 
						|
                    if ($session->{ErrorStr}) { return (1, $session->{ErrorStr}); }
 | 
						|
                    if ($data =~ /:/) {
 | 
						|
                        push @output, "HS Daughter card MAC Address " . ($_ + 1) . ": " . $data;
 | 
						|
                    }
 | 
						|
                }
 | 
						|
                foreach (0 .. 3) {
 | 
						|
                    $data = $session->get([ $dcmacoids[$_], $slot ]);
 | 
						|
                    if ($session->{ErrorStr}) { return (1, $session->{ErrorStr}); }
 | 
						|
                    if ($data =~ /:/) {
 | 
						|
                        push @output, "Daughter card 1 MAC Address " . ($_ + 1) . ": " . $data;
 | 
						|
                    }
 | 
						|
                }
 | 
						|
                foreach (0 .. 3) {
 | 
						|
                    $data = $session->get([ $sidecardoids[$_], $slot ]);
 | 
						|
                    if ($session->{ErrorStr}) { return (1, $session->{ErrorStr}); }
 | 
						|
                    if ($data =~ /:/) {
 | 
						|
                        push @output, "Side card MAC Address " . ($_ + 1) . ": " . $data;
 | 
						|
                    }
 | 
						|
                }
 | 
						|
            } else {
 | 
						|
                my $cmd = "pasu $node show PXE |grep NicPortMacAddress";
 | 
						|
                my $mac_list = xCAT::Utils->runcmd($cmd, 0, 1);
 | 
						|
 | 
						|
                #print "mac_list=$mac_list\n";
 | 
						|
                if (@$mac_list > 0) {
 | 
						|
                    foreach my $mac (@$mac_list) {
 | 
						|
 | 
						|
                        #print "mac=$mac\n";
 | 
						|
                        $mac =~ s/^.*PXE.NicPortMacAddress.*(\d+)=(.*)$/"MAC Address $1: $2/;
 | 
						|
 | 
						|
                        #print "mac=$mac\n";
 | 
						|
                        push @output, $mac;
 | 
						|
                    }
 | 
						|
                }
 | 
						|
            }
 | 
						|
        }
 | 
						|
    }
 | 
						|
    if ($updatetable and $updatehash{mtm}) {
 | 
						|
 | 
						|
        #updatenodegroups
 | 
						|
        my $tmp_pre = xCAT::data::ibmhwtypes::parse_group($updatehash{mtm});
 | 
						|
        if (defined($tmp_pre)) {
 | 
						|
            xCAT::TableUtils->updatenodegroups($currnode, $tmp_pre);
 | 
						|
        }
 | 
						|
    }
 | 
						|
    if ($updatetable and keys %updatehash) {
 | 
						|
        my $vpdtab = xCAT::Table->new('vpd');
 | 
						|
        $vpdtab->setNodeAttribs($currnode, \%updatehash);
 | 
						|
    }
 | 
						|
    return (0, @output);
 | 
						|
}
 | 
						|
 | 
						|
sub power {
 | 
						|
    my $subcommand = shift;
 | 
						|
    my $data;
 | 
						|
    my $stat;
 | 
						|
    my $validsub = 0;
 | 
						|
    unless ($slot > 0) {
 | 
						|
        if ($subcommand eq "reset" or $subcommand eq "boot") {
 | 
						|
            $data = $session->set(new SNMP::Varbind([ ".1.3.6.1.4.1.2.3.51.2.7.4", 0, 1, 'INTEGER' ]));
 | 
						|
            unless ($data) { return (1, $session->{ErrorStr}); }
 | 
						|
            return (0, "reset");
 | 
						|
        } else {
 | 
						|
            return (1, "$subcommand unsupported on the management module");
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    #get stat first
 | 
						|
    $validsub = 1;
 | 
						|
    $data     = $session->get([ $powerstatoid . "." . $slot ]);
 | 
						|
    if ($data == 1) {
 | 
						|
        $stat = "on";
 | 
						|
    } elsif ($data == 0) {
 | 
						|
        $stat = "off";
 | 
						|
    } else {
 | 
						|
        $stat = "error";
 | 
						|
    }
 | 
						|
 | 
						|
    my $old_stat = $stat;
 | 
						|
    my $newstat;
 | 
						|
    if ($subcommand eq "softoff") {
 | 
						|
        $validsub = 1;
 | 
						|
        $data = $session->set(new SNMP::Varbind([ "." . $powerchangeoid, $slot, 2, 'INTEGER' ]));
 | 
						|
        unless ($data) { return (1, $session->{ErrorStr}); }
 | 
						|
        $newstat = $::STATUS_POWERING_OFF;
 | 
						|
        $stat    = "softoff";
 | 
						|
        if ($old_stat eq "off") { $stat .= " $status_noop"; }
 | 
						|
    }
 | 
						|
    if ($subcommand eq "off") {
 | 
						|
        $validsub = 1;
 | 
						|
        $data = $session->set(new SNMP::Varbind([ "." . $powerchangeoid, $slot, 0, 'INTEGER' ]));
 | 
						|
        unless ($data) { return (1, $session->{ErrorStr}); }
 | 
						|
        $newstat = $::STATUS_POWERING_OFF;
 | 
						|
        $stat    = "off";
 | 
						|
        if ($old_stat eq "off") { $stat .= " $status_noop"; }
 | 
						|
    }
 | 
						|
    if ($subcommand eq "on" or ($subcommand eq "boot" and $stat eq "off")) {
 | 
						|
        $data = $session->set(new SNMP::Varbind([ "." . $powerchangeoid, $slot, 1, 'INTEGER' ]));
 | 
						|
        unless ($data) { return (1, $session->{ErrorStr}); }
 | 
						|
        $newstat = $::STATUS_POWERING_ON;
 | 
						|
        if ($subcommand eq "boot") { $stat .= " " . ($data ? "on" : "off"); }
 | 
						|
        if ($subcommand eq "on") {
 | 
						|
            $stat = ($data ? "on" : "off");
 | 
						|
            if ($old_stat eq "on") { $stat .= " $status_noop"; }
 | 
						|
        }
 | 
						|
    } elsif ($subcommand eq "reset" or ($subcommand eq "boot" and $stat eq "on")) {
 | 
						|
        $data = $session->set(new SNMP::Varbind([ "." . $powerresetoid, $slot, 1, 'INTEGER' ]));
 | 
						|
        unless ($data) { return (1, $session->{ErrorStr}); }
 | 
						|
        $newstat = $::STATUS_POWERING_ON;
 | 
						|
        if ($subcommand eq "boot") { $stat = "on reset"; } else { $stat = "reset"; }
 | 
						|
    } elsif (not $validsub) {
 | 
						|
        return 1, "Unknown/Unsupported power command $subcommand";
 | 
						|
    }
 | 
						|
    if ($session->{ErrorStr}) { return (1, $session->{ErrorStr}); }
 | 
						|
    if ($newstat) {
 | 
						|
        push @{ $newnodestatus{$newstat} }, $currnode;
 | 
						|
    }
 | 
						|
 | 
						|
    if ($stat) { return (0, $stat); }
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
sub beacon {
 | 
						|
    my $subcommand = shift;
 | 
						|
    my $data;
 | 
						|
    unless ($subcommand) { $subcommand = "stat"; }
 | 
						|
    if ($subcommand eq "stat") {
 | 
						|
    } elsif ($subcommand eq "on") {
 | 
						|
        $data = $session->set(new SNMP::Varbind([ $beaconoid, $slot, 1, 'INTEGER' ]));
 | 
						|
    } elsif ($subcommand eq "off") {
 | 
						|
        $data = $session->set(new SNMP::Varbind([ $beaconoid, $slot, 0, 'INTEGER' ]));
 | 
						|
    } elsif ($subcommand eq "blink") {
 | 
						|
        $data = $session->set(new SNMP::Varbind([ $beaconoid, $slot, 2, 'INTEGER' ]));
 | 
						|
    } else {
 | 
						|
        return (1, "$subcommand unsupported");
 | 
						|
    }
 | 
						|
    $session = new SNMP::Session(
 | 
						|
        DestHost   => $mpa,
 | 
						|
        Version    => '3',
 | 
						|
        SecName    => $mpauser,
 | 
						|
        AuthProto  => 'SHA',
 | 
						|
        AuthPass   => $mpapass,
 | 
						|
        PrivProto  => 'DES',
 | 
						|
        SecLevel   => 'authPriv',
 | 
						|
        UseNumeric => 1,
 | 
						|
        Retries    => 1,           # Give up sooner to make commands go smoother
 | 
						|
        Timeout => 300000000, #Beacon, for one, takes a bit over a second to return
 | 
						|
        PrivPass => $mpapass);
 | 
						|
    my $stat = $session->get([ $beaconoid . "." . $slot ]);
 | 
						|
    if ($session->{ErrorStr}) { return (1, $session->{ErrorStr}); }
 | 
						|
    if ($stat == 0) {
 | 
						|
        return (0, "off");
 | 
						|
    } elsif ($stat == 1) {
 | 
						|
        return (0, "on");
 | 
						|
    } elsif ($stat == 2) {
 | 
						|
        return (0, "blink");
 | 
						|
    } elsif ($stat == 3) {
 | 
						|
        return (0, "unsupported");
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
# The oids which are used in the renergy command
 | 
						|
my $bladetype_oid = ".1.3.6.1.4.1.2.3.51.2.2.21.1.1.1.0"; #bladeCenterVpdMachineType
 | 
						|
 | 
						|
my $pdstatus_oid = ".1.3.6.1.4.1.2.3.51.2.2.10.1.1.1.3";  #fuelGaugeStatus
 | 
						|
my $pdpolicy_oid = ".1.3.6.1.4.1.2.3.51.2.2.10.1.1.1.6"; #fuelGaugePowerManagementPolicySetting
 | 
						|
my $pdmodule1_oid = ".1.3.6.1.4.1.2.3.51.2.2.10.1.1.1.4"; #fuelGaugeFirstPowerModule
 | 
						|
my $pdmodule2_oid = ".1.3.6.1.4.1.2.3.51.2.2.10.1.1.1.5"; #fuelGaugeSecondPowerModule
 | 
						|
my $pdavailablepower_oid = ".1.3.6.1.4.1.2.3.51.2.2.10.1.1.1.7"; #fuelGaugeTotalPower
 | 
						|
my $pdreservepower_oid = ".1.3.6.1.4.1.2.3.51.2.2.10.1.1.1.8"; #fuelGaugeAllocatedPower
 | 
						|
my $pdremainpower_oid = ".1.3.6.1.4.1.2.3.51.2.2.10.1.1.1.9"; #fuelGaugeRemainingPower
 | 
						|
my $pdinused_oid = ".1.3.6.1.4.1.2.3.51.2.2.10.1.1.1.10";  #fuelGaugePowerInUsed
 | 
						|
 | 
						|
my $chassisDCavailable_oid = ".1.3.6.1.4.1.2.3.51.2.2.10.5.1.1.0"; #chassisTotalDCPowerAvailable
 | 
						|
my $chassisACinused_oid = ".1.3.6.1.4.1.2.3.51.2.2.10.5.1.2.0"; #chassisTotalACPowerInUsed
 | 
						|
my $chassisThermalOutput_oid = ".1.3.6.1.4.1.2.3.51.2.2.10.5.1.3.0"; #chassisTotalThermalOutput
 | 
						|
 | 
						|
my $chassisFrontTmp_oid = ".1.3.6.1.4.1.2.3.51.2.2.1.5.1.0";    #frontPanelTemp
 | 
						|
my $mmtemp_oid          = ".1.3.6.1.4.1.2.3.51.2.2.1.1.2.0";    #mmTemp
 | 
						|
 | 
						|
my $bladewidth_oid = ".1.3.6.1.4.1.2.3.51.2.22.1.5.1.1.15";     #bladeWidth
 | 
						|
 | 
						|
my $curallocpower_oid = ".1.3.6.1.4.1.2.3.51.2.2.10.pdnum.1.1.7"; #pd1ModuleAllocatedPowerCurrent
 | 
						|
my $maxallocpower_oid = ".1.3.6.1.4.1.2.3.51.2.2.10.pdnum.1.1.8"; #pd1ModuleAllocatedPowerMax
 | 
						|
my $minallocpower_oid = ".1.3.6.1.4.1.2.3.51.2.2.10.pdnum.1.1.9"; #pd1ModuleAllocatedPowerMin
 | 
						|
my $powercapability_oid = ".1.3.6.1.4.1.2.3.51.2.2.10.pdnum.1.1.12"; #pd1ModulePowerCapabilities
 | 
						|
 | 
						|
my $powercapping_oid = ".1.3.6.1.4.1.2.3.51.2.2.10.4.1.1.1.3"; #bladeDetailsMaxPowerConfig
 | 
						|
my $effCPU_oid = ".1.3.6.1.4.1.2.3.51.2.2.10.4.1.1.1.4"; #bladeDetailsEffectiveClockRate
 | 
						|
my $maxCPU_oid = ".1.3.6.1.4.1.2.3.51.2.2.10.4.1.1.1.5"; #bladeDetailsMaximumClockRate
 | 
						|
my $savingstatus_oid = ".1.3.6.1.4.1.2.3.51.2.2.10.4.1.1.1.6"; #bladeDetailsPowerSaverMode
 | 
						|
my $dsavingstatus_oid = ".1.3.6.1.4.1.2.3.51.2.2.10.4.1.1.1.7"; #bladeDetailsDynamicPowerSaver
 | 
						|
my $dsperformance_oid = ".1.3.6.1.4.1.2.3.51.2.2.10.4.1.1.1.8"; #bladeDetailsDynamicPowerFavorPerformanceOverPower
 | 
						|
 | 
						|
# New attributes which supported by CMM
 | 
						|
my $PowerControl_oid = ".1.3.6.1.4.1.2.3.51.2.2.10.4.1.1.1.9"; #bladeDetailsPowerControl
 | 
						|
my $PowerPcapMin_oid = ".1.3.6.1.4.1.2.3.51.2.2.10.4.1.1.1.10"; #bladeDetailsPcapMin
 | 
						|
my $PowerPcapGMin_oid = ".1.3.6.1.4.1.2.3.51.2.2.10.4.1.1.1.11"; #bladeDetailsPcapGuaranteedMin
 | 
						|
my $PowerPcapMax_oid = ".1.3.6.1.4.1.2.3.51.2.2.10.4.1.1.1.12"; #bladeDetailsPcapMax
 | 
						|
 | 
						|
# New table used to control the power management
 | 
						|
#my $powerPcapMin =".1.3.6.1.4.1.2.3.51.2.22.31.6.1.10";    # componentPowerDetailsPcapMin
 | 
						|
#my $powerPcapGMin = ".1.3.6.1.4.1.2.3.51.2.22.31.6.1.11";    # componentPowerDetailsPcapGuaranteedMin
 | 
						|
#my $powerPcapMax = ".1.3.6.1.4.1.2.3.51.2.22.31.6.1.12";    # componentPowerDetailsPcapMax
 | 
						|
 | 
						|
#my $powerPcapSet = ".1.3.6.1.4.1.2.3.51.2.22.31.6.1.3"; # componentPowerDetailsMaxPowerConfig
 | 
						|
#my $powerControl = ".1.3.6.1.4.1.2.3.51.2.22.31.6.1.9"; # componentPowerDetailsPowerControl
 | 
						|
#my $powersavingstatus_oid = ".1.3.6.1.4.1.2.3.51.2.22.31.6.1.6";    #componentPowerDetailsPowerSaverMode
 | 
						|
#my $powerdsavingstatus_oid = ".1.3.6.1.4.1.2.3.51.2.22.31.6.1.7";    #componentPowerDetailsDynamicPowerSaver
 | 
						|
#my $powerdsperformance_oid = ".1.3.6.1.4.1.2.3.51.2.22.31.6.1.8";    #componentPowerDetailsDynamicPowerFavorPerformanceOverPower
 | 
						|
 | 
						|
 | 
						|
 | 
						|
# The meaning of obj fuelGaugePowerManagementPolicySetting
 | 
						|
my %pdpolicymap = (
 | 
						|
    '0'   => "redundantWithoutPerformanceImpact",
 | 
						|
    '1'   => "redundantWithPerformanceImpact",
 | 
						|
    '2'   => "nonRedundant",
 | 
						|
    '3'   => "redundantACPowerSource",
 | 
						|
    '4'   => "acPowerSourceWithBladeThrottlingAllowed",
 | 
						|
    '255' => "notApplicable",
 | 
						|
);
 | 
						|
 | 
						|
# The meaning of obj pd1/2ModulePowerCapabilities
 | 
						|
my %capabilitymap = (
 | 
						|
    '0'   => "noAbility",
 | 
						|
    '1'   => "staticPowerManagement",
 | 
						|
    '2'   => "fixedPowerManagement",
 | 
						|
    '3'   => "dynamicPowerManagement",
 | 
						|
    '4'   => "dynamicPowerMeasurement1",
 | 
						|
    '5'   => "dynamicPowerMeasurement2",
 | 
						|
    '6'   => "dynamicPowerMeasurementWithPowerCapping",
 | 
						|
    '255' => "notApplicable",
 | 
						|
);
 | 
						|
 | 
						|
# The valid attributes the renergy command can support
 | 
						|
# 1 for readonly; 2 for write; 3 readwrite
 | 
						|
 | 
						|
my %mm_valid_items = (
 | 
						|
    'pd1status'        => 1,
 | 
						|
    'pd2status'        => 1,
 | 
						|
    'pd1policy'        => 1,
 | 
						|
    'pd2policy'        => 1,
 | 
						|
    'pd1powermodule1'  => 1,
 | 
						|
    'pd1powermodule2'  => 1,
 | 
						|
    'pd2powermodule1'  => 1,
 | 
						|
    'pd2powermodule2'  => 1,
 | 
						|
    'pd1avaiablepower' => 1,
 | 
						|
    'pd2avaiablepower' => 1,
 | 
						|
    'pd1reservedpower' => 1,
 | 
						|
    'pd2reservedpower' => 1,
 | 
						|
    'pd1remainpower'   => 1,
 | 
						|
    'pd2remainpower'   => 1,
 | 
						|
    'pd1inusedpower'   => 1,
 | 
						|
    'pd2inusedpower'   => 1,
 | 
						|
    'availableDC'      => 1,
 | 
						|
    'averageAC'        => 1,
 | 
						|
    'thermaloutput'    => 1,
 | 
						|
    'ambienttemp'      => 1,
 | 
						|
    'mmtemp'           => 1,
 | 
						|
);
 | 
						|
 | 
						|
my %cmm_valid_items = (
 | 
						|
    'powerstatus'   => 1,
 | 
						|
    'powerpolicy'   => 1,
 | 
						|
    'powermodule'   => 1,
 | 
						|
    'avaiablepower' => 1,
 | 
						|
    'reservedpower' => 1,
 | 
						|
    'remainpower'   => 1,
 | 
						|
    'inusedpower'   => 1,
 | 
						|
    'availableDC'   => 1,
 | 
						|
    'averageAC'     => 1,
 | 
						|
    'thermaloutput' => 1,
 | 
						|
    'ambienttemp'   => 1,
 | 
						|
    'mmtemp'        => 1,
 | 
						|
);
 | 
						|
 | 
						|
my %pd1_valid_items = (
 | 
						|
    'pd1status'        => 1,
 | 
						|
    'pd1policy'        => 1,
 | 
						|
    'pd1powermodule1'  => 1,
 | 
						|
    'pd1powermodule2'  => 1,
 | 
						|
    'pd1avaiablepower' => 1,
 | 
						|
    'pd1reservedpower' => 1,
 | 
						|
    'pd1remainpower'   => 1,
 | 
						|
    'pd1inusedpower'   => 1,
 | 
						|
);
 | 
						|
 | 
						|
my %pd2_valid_items = (
 | 
						|
    'pd2status'        => 1,
 | 
						|
    'pd2policy'        => 1,
 | 
						|
    'pd2powermodule1'  => 1,
 | 
						|
    'pd2powermodule2'  => 1,
 | 
						|
    'pd2avaiablepower' => 1,
 | 
						|
    'pd2reservedpower' => 1,
 | 
						|
    'pd2remainpower'   => 1,
 | 
						|
    'pd2inusedpower'   => 1,
 | 
						|
);
 | 
						|
 | 
						|
my %blade_valid_items = (
 | 
						|
    'averageDC'     => 1,
 | 
						|
    'cappingmaxmin' => 0,
 | 
						|
    'cappingmax'    => 0,
 | 
						|
    'cappingmin'    => 0,
 | 
						|
    'capability'    => 1,
 | 
						|
    'cappingvalue'  => 1,
 | 
						|
    'cappingwatt'   => 0,
 | 
						|
    'cappingperc'   => 0,
 | 
						|
    'CPUspeed'      => 1,
 | 
						|
    'maxCPUspeed'   => 1,
 | 
						|
    'savingstatus'  => 3,
 | 
						|
    'dsavingstatus' => 3,
 | 
						|
);
 | 
						|
 | 
						|
my %flex_blade_valid_items = (
 | 
						|
    'averageDC'     => 1,
 | 
						|
    'cappingmaxmin' => 1,
 | 
						|
    'cappingmax'    => 1,
 | 
						|
    'cappingmin'    => 1,
 | 
						|
    'cappingGmin'   => 1,
 | 
						|
    'capability'    => 1,
 | 
						|
    'cappingvalue'  => 1,
 | 
						|
    'cappingwatt'   => 2,
 | 
						|
    'cappingperc'   => 2,
 | 
						|
    'CPUspeed'      => 1,
 | 
						|
    'maxCPUspeed'   => 1,
 | 
						|
    'cappingstatus' => 3,
 | 
						|
    'savingstatus'  => 3,
 | 
						|
    'dsavingstatus' => 3,
 | 
						|
);
 | 
						|
 | 
						|
# use the slot number of serverblade to get the powerdomain number
 | 
						|
# and the bay number in the powerdomain
 | 
						|
sub getpdbayinfo {
 | 
						|
    my ($bc_type, $slot) = @_;
 | 
						|
 | 
						|
    my $pdnum = 0;
 | 
						|
    my $pdbay = 0;
 | 
						|
 | 
						|
    if ($bc_type =~ /^1886|7989|8852$/) {    # for blade center H
 | 
						|
        if ($slot < 8) {
 | 
						|
            $pdnum = 1;
 | 
						|
            $pdbay = $slot + 16;
 | 
						|
        } elsif ($slot < 15) {
 | 
						|
            $pdnum = 2;
 | 
						|
            $pdbay = $slot + 16 - 7;
 | 
						|
        }
 | 
						|
    } elsif ($bc_type =~ /^8740|8750$/) {    # for blade center HT
 | 
						|
        if ($slot < 7) {
 | 
						|
            $pdnum = 1;
 | 
						|
            $pdbay = $slot + 22;
 | 
						|
        } elsif ($slot < 13) {
 | 
						|
            $pdnum = 2;
 | 
						|
            $pdbay = $slot + 12 - 6;
 | 
						|
        }
 | 
						|
    } elsif ($bc_type =~ /^8720|8730$/) {    # for blade center T
 | 
						|
        if ($slot < 5) {
 | 
						|
            $pdnum = 1;
 | 
						|
            $pdbay = $slot + 12;
 | 
						|
        } elsif ($slot < 9) {
 | 
						|
            $pdnum = 2;
 | 
						|
            $pdbay = $slot + 2 - 4;
 | 
						|
        }
 | 
						|
    } elsif ($bc_type =~ /^8720|8730$/) {    # for blade center S
 | 
						|
        if ($slot < 7) {
 | 
						|
            $pdnum = 1;
 | 
						|
            $pdbay = $slot + 17;
 | 
						|
        }
 | 
						|
    } elsif ($bc_type =~ /^7893$/) {         # for flex
 | 
						|
        $pdnum = 1;
 | 
						|
        $pdbay = $slot + 18;
 | 
						|
    } else {                                 # for common blade center
 | 
						|
        if ($slot < 7) {
 | 
						|
            $pdnum = 1;
 | 
						|
            $pdbay = $slot + 10;
 | 
						|
        } elsif ($slot < 15) {
 | 
						|
            $pdnum = 2;
 | 
						|
            $pdbay = $slot - 6;
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    return ($pdnum, $pdbay);
 | 
						|
}
 | 
						|
 | 
						|
# command to hand the renergy request
 | 
						|
sub renergy {
 | 
						|
    my ($mpa, $node, $slot, @items) = @_;
 | 
						|
 | 
						|
    if (!$mpa) {
 | 
						|
        return (1, "The attribute [mpa] needs to be set for the node $node.");
 | 
						|
    }
 | 
						|
    if (!$slot && ($mpa ne $node)) {
 | 
						|
        return (1, "The attribute [id] needs to be set for the node $node.");
 | 
						|
    }
 | 
						|
 | 
						|
    # the type of blade center
 | 
						|
    my $bc_type = "";
 | 
						|
 | 
						|
    #check the validity of all the attributes
 | 
						|
 | 
						|
    my @readlist  = ();
 | 
						|
    my %writelist = ();
 | 
						|
    my @r4wlist   = ();
 | 
						|
    foreach my $item (@items) {
 | 
						|
        if (!$item) {
 | 
						|
            next;
 | 
						|
        }
 | 
						|
        my $readpath  = ();
 | 
						|
        my $checkpath = ();
 | 
						|
        if ($item =~ /^all$/) {
 | 
						|
            if ($mpa eq $node) {
 | 
						|
 | 
						|
                #handle the mm itself
 | 
						|
                if ($mptype eq "cmm") {
 | 
						|
                    $readpath = \%cmm_valid_items;
 | 
						|
                } else {    # Assume it's AMM
 | 
						|
                    $readpath = \%mm_valid_items;
 | 
						|
                }
 | 
						|
            } else {
 | 
						|
                if ($mptype eq "cmm") {
 | 
						|
                    $readpath = \%flex_blade_valid_items;
 | 
						|
                } else {    # Assume it's AMM
 | 
						|
                    $readpath = \%blade_valid_items;
 | 
						|
                }
 | 
						|
            }
 | 
						|
        } elsif ($item =~ /^pd1all$/) {
 | 
						|
            if ($mpa ne $node) {
 | 
						|
                return (1, "pd1all is NOT available for flex or blade center server.");
 | 
						|
            }
 | 
						|
            if ($mptype eq "cmm") {    # It only works for AMM
 | 
						|
                return (1, "pd1all is NOT available for flex chassis.");
 | 
						|
            }
 | 
						|
            $readpath = \%pd1_valid_items;
 | 
						|
        } elsif ($item =~ /^pd2all$/) {
 | 
						|
            if ($mpa ne $node) {
 | 
						|
                return (1, "pd2all is NOT available for flex or blade center server.");
 | 
						|
            }
 | 
						|
            if ($mptype eq "cmm") {    # It only works for AMM
 | 
						|
                return (1, "pd2all is NOT available for flex chassis.");
 | 
						|
            }
 | 
						|
            $readpath = \%pd2_valid_items;
 | 
						|
        } elsif ($item =~ /^cappingmaxmin$/) {
 | 
						|
            push @readlist, ('cappingmin', 'cappingmax');
 | 
						|
        } elsif ($item =~ /(.*)=(.*)/) {
 | 
						|
            my $name  = $1;
 | 
						|
            my $value = $2;
 | 
						|
            if ($mpa eq $node) {
 | 
						|
                if ($mptype eq "cmm") {
 | 
						|
                    $checkpath = \%cmm_valid_items;
 | 
						|
                } else {
 | 
						|
                    $checkpath = \%mm_valid_items;
 | 
						|
                }
 | 
						|
            } else {
 | 
						|
                if ($mptype eq "cmm") {
 | 
						|
                    $checkpath = \%flex_blade_valid_items;
 | 
						|
                } else {
 | 
						|
                    $checkpath = \%blade_valid_items;
 | 
						|
                }
 | 
						|
            }
 | 
						|
 | 
						|
            if ($checkpath->{$name} < 2) {
 | 
						|
                return (1, "$name is NOT writable.");
 | 
						|
            }
 | 
						|
 | 
						|
            $writelist{$name} = $value;
 | 
						|
            if ($name eq "cappingwatt" || $name eq "cappingperc") {
 | 
						|
                push @r4wlist, ('cappingmin', 'cappingmax');
 | 
						|
            }
 | 
						|
        } else {
 | 
						|
            if ($mpa eq $node) {
 | 
						|
                if ($mptype eq "cmm") {
 | 
						|
                    $checkpath = \%cmm_valid_items;
 | 
						|
                } else {
 | 
						|
                    $checkpath = \%mm_valid_items;
 | 
						|
                }
 | 
						|
            } else {
 | 
						|
                if ($mptype eq "cmm") {
 | 
						|
                    $checkpath = \%flex_blade_valid_items;
 | 
						|
                } else {
 | 
						|
                    $checkpath = \%blade_valid_items;
 | 
						|
                }
 | 
						|
            }
 | 
						|
 | 
						|
            if ($checkpath->{$item} != 1 && $checkpath->{$item} != 3) {
 | 
						|
                return (1, "$item is NOT a valid attribute.");
 | 
						|
            }
 | 
						|
 | 
						|
            push @readlist, $item;
 | 
						|
        }
 | 
						|
 | 
						|
        # Handle the attribute equals 'all', 'pd1all', 'pd2all'
 | 
						|
        if ($readpath) {
 | 
						|
            foreach (keys %$readpath) {
 | 
						|
                if ($readpath->{$_} == 1 || $readpath->{$_} == 3) {
 | 
						|
                    if (/^cappingmaxmin$/) { next; }
 | 
						|
                    push @readlist, $_;
 | 
						|
                }
 | 
						|
            }
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
 | 
						|
    # does not support to read and write in one command
 | 
						|
    if (@readlist && %writelist) {
 | 
						|
        return (1, "Cannot handle read and write in one command.");
 | 
						|
    }
 | 
						|
 | 
						|
    if (scalar(keys %writelist) > 1) {
 | 
						|
        return (1, "renergy cannot set multiple attributes at one command.");
 | 
						|
    }
 | 
						|
 | 
						|
    if (!(@readlist || %writelist)) {
 | 
						|
        return (1, "Does not get any valid attributes.");
 | 
						|
    }
 | 
						|
 | 
						|
    if ((!@readlist) && %writelist) {
 | 
						|
        push @readlist, @r4wlist;
 | 
						|
    }
 | 
						|
 | 
						|
    # get the blade center type first
 | 
						|
    if (grep (/^averageAC|averageDC|cappingmax|cappingmin|capability$/, @readlist)) {
 | 
						|
        $bc_type = $session->get([$bladetype_oid]);
 | 
						|
        if ($session->{ErrorStr}) { return (1, $session->{ErrorStr}); }
 | 
						|
    }
 | 
						|
 | 
						|
    my @output = ();
 | 
						|
    foreach my $item (sort(@readlist)) {
 | 
						|
        my $oid = "";
 | 
						|
        if ($item =~ /^(pd1status|powerstatus)$/) {
 | 
						|
            $oid = $pdstatus_oid . ".1";
 | 
						|
        } elsif ($item eq "pd2status") {
 | 
						|
            $oid = $pdstatus_oid . ".2";
 | 
						|
        } elsif ($item =~ /^(pd1policy|powerpolicy)$/) {
 | 
						|
            $oid = $pdpolicy_oid . ".1";
 | 
						|
        } elsif ($item eq "pd2policy") {
 | 
						|
            $oid = $pdpolicy_oid . ".2";
 | 
						|
        } elsif ($item =~ /^(pd1powermodule1|powermodule)$/) {
 | 
						|
            $oid = $pdmodule1_oid . ".1";
 | 
						|
        } elsif ($item eq "pd2powermodule1") {
 | 
						|
            $oid = $pdmodule1_oid . ".2";
 | 
						|
        } elsif ($item eq "pd1powermodule2") {
 | 
						|
            $oid = $pdmodule2_oid . ".1";
 | 
						|
        } elsif ($item eq "pd2powermodule2") {
 | 
						|
            $oid = $pdmodule2_oid . ".2";
 | 
						|
        } elsif ($item =~ /^(pd1avaiablepower|avaiablepower)$/) {
 | 
						|
            $oid = $pdavailablepower_oid . ".1";
 | 
						|
        } elsif ($item eq "pd2avaiablepower") {
 | 
						|
            $oid = $pdavailablepower_oid . ".2";
 | 
						|
        } elsif ($item =~ /^(pd1reservedpower|reservedpower)$/) {
 | 
						|
            $oid = $pdreservepower_oid . ".1";
 | 
						|
        } elsif ($item eq "pd2reservedpower") {
 | 
						|
            $oid = $pdreservepower_oid . ".2";
 | 
						|
        } elsif ($item =~ /^(pd1remainpower|remainpower)$/) {
 | 
						|
            $oid = $pdremainpower_oid . ".1";
 | 
						|
        } elsif ($item eq "pd2remainpower") {
 | 
						|
            $oid = $pdremainpower_oid . ".2";
 | 
						|
        } elsif ($item =~ /^(pd1inusedpower|inusedpower)$/) {
 | 
						|
            $oid = $pdinused_oid . ".1";
 | 
						|
        } elsif ($item eq "pd2inusedpower") {
 | 
						|
            $oid = $pdinused_oid . ".2";
 | 
						|
        } elsif ($item eq "availableDC") {
 | 
						|
            $oid = $chassisDCavailable_oid;
 | 
						|
        } elsif ($item eq "thermaloutput") {
 | 
						|
            $oid = $chassisThermalOutput_oid;
 | 
						|
        } elsif ($item eq "ambienttemp") {
 | 
						|
            $oid = $chassisFrontTmp_oid;
 | 
						|
        } elsif ($item eq "mmtemp") {
 | 
						|
            $oid = $mmtemp_oid;
 | 
						|
        } elsif ($item eq "averageAC") {
 | 
						|
 | 
						|
            # just for management module
 | 
						|
            $oid = $chassisACinused_oid;
 | 
						|
        } elsif ($item eq "averageDC") {
 | 
						|
 | 
						|
            # just for server blade
 | 
						|
            my ($pdnum, $pdbay) = getpdbayinfo($bc_type, $slot);
 | 
						|
            $oid = $curallocpower_oid;
 | 
						|
            $pdnum++;
 | 
						|
            $oid =~ s/pdnum/$pdnum/;
 | 
						|
            $oid = $oid . "." . $pdbay;
 | 
						|
        } elsif ($item eq "capability") {
 | 
						|
            my ($pdnum, $pdbay) = getpdbayinfo($bc_type, $slot);
 | 
						|
            $oid = $powercapability_oid;
 | 
						|
            $pdnum++;
 | 
						|
            $oid =~ s/pdnum/$pdnum/;
 | 
						|
            $oid = $oid . "." . $pdbay;
 | 
						|
        } elsif ($item eq "cappingmax") {
 | 
						|
            $oid = $PowerPcapMax_oid . "." . $slot;
 | 
						|
        } elsif ($item eq "cappingmin") {
 | 
						|
            $oid = $PowerPcapMin_oid . "." . $slot;
 | 
						|
        } elsif ($item eq "cappingGmin") {
 | 
						|
            $oid = $PowerPcapGMin_oid . "." . $slot;
 | 
						|
        } elsif ($item eq "cappingvalue") {
 | 
						|
            $oid = $powercapping_oid . "." . $slot;
 | 
						|
        } elsif ($item eq "CPUspeed") {
 | 
						|
            $oid = $effCPU_oid . "." . $slot;
 | 
						|
        } elsif ($item eq "maxCPUspeed") {
 | 
						|
            $oid = $maxCPU_oid . "." . $slot;
 | 
						|
        } elsif ($item eq "cappingstatus") {
 | 
						|
            $oid = $PowerControl_oid . "." . $slot;
 | 
						|
        } elsif ($item eq "savingstatus") {
 | 
						|
            $oid = $savingstatus_oid . "." . $slot;
 | 
						|
        } elsif ($item eq "dsavingstatus") {
 | 
						|
            $oid = $dsavingstatus_oid . "." . $slot;
 | 
						|
        } else {
 | 
						|
            push @output, "$item is NOT a valid attribute.";
 | 
						|
        }
 | 
						|
 | 
						|
        if ($oid ne "") {
 | 
						|
            my $data = $session->get([$oid]);
 | 
						|
            if ($session->{ErrorStr}) { return (1, $session->{ErrorStr}); }
 | 
						|
 | 
						|
            if ($data ne ""
 | 
						|
                && $data ne "NOSUCHINSTANCE"
 | 
						|
                && $data ne "notApplicable") {
 | 
						|
                if ($item =~ /^(pd1|pd2|power)policy$/) {
 | 
						|
                    push @output, "$item: $pdpolicymap{$data}";
 | 
						|
                } elsif ($item eq "capability") {
 | 
						|
                    push @output, "$item: $capabilitymap{$data}";
 | 
						|
                } elsif ($item =~ /cappingvalue|averageDC|cappingmax|cappingmin|cappingGmin/) {
 | 
						|
                    if ($item eq "cappingvalue" && $data eq "0") {
 | 
						|
                        push @output, "$item: na";
 | 
						|
                    } else {
 | 
						|
                        my $bladewidth = $session->get([ $bladewidth_oid . ".$slot" ]);
 | 
						|
                        if ($session->{ErrorStr}) { return (1, $session->{ErrorStr}); }
 | 
						|
                        $data =~ s/[^\d]*$//;
 | 
						|
                        foreach (1 .. $bladewidth - 1) {
 | 
						|
                            $oid =~ /(\d+)$/;
 | 
						|
                            my $next = $1 + $_;
 | 
						|
                            $oid =~ s/(\d+)$/$next/;
 | 
						|
                            my $nextdata = $session->get([$oid]);
 | 
						|
                            if ($session->{ErrorStr}) { return (1, $session->{ErrorStr}); }
 | 
						|
                            $nextdata =~ s/[^\d]*$//;
 | 
						|
                            $data += $nextdata;
 | 
						|
                        }
 | 
						|
                        push @output, "$item: $data" . "W";
 | 
						|
                    }
 | 
						|
                } elsif ($item eq "cappingstatus") {
 | 
						|
                    if ($data eq "2" || $data eq "5" || $data eq "10") {
 | 
						|
 | 
						|
                        # 1 all off; 2 cap;
 | 
						|
                        # 4 staticsaving; 5 cap + staticsaving;
 | 
						|
                        # 9 dynamicsaving; 10 cap + dynamicsaving;
 | 
						|
                        push @output, "$item: on";
 | 
						|
                    } elsif ($data eq "0" || $data eq "1" || $data eq "3" || $data eq "4" || $data eq "9") {
 | 
						|
                        push @output, "$item: off";
 | 
						|
                    } else {
 | 
						|
                        push @output, "$item: na";
 | 
						|
                    }
 | 
						|
                } elsif ($item eq "savingstatus") {
 | 
						|
                    if ($data eq "0") {
 | 
						|
                        push @output, "$item: off";
 | 
						|
                    } elsif ($data eq "1") {
 | 
						|
                        push @output, "$item: on";
 | 
						|
                    } else {
 | 
						|
                        push @output, "$item: na";
 | 
						|
                    }
 | 
						|
                } elsif ($item eq "dsavingstatus") {
 | 
						|
 | 
						|
                    # get the favor performance
 | 
						|
                    my $pdata = $session->get([ $dsperformance_oid . "." . $slot ]);
 | 
						|
                    if ($session->{ErrorStr}) { return (1, $session->{ErrorStr}); }
 | 
						|
 | 
						|
                    if ($data eq "0") {
 | 
						|
                        push @output, "$item: off";
 | 
						|
                    } elsif ($data eq "1" && $pdata eq "0") {
 | 
						|
                        push @output, "$item: on-norm";
 | 
						|
                    } elsif ($data eq "1" && $pdata eq "1") {
 | 
						|
                        push @output, "$item: on-maxp";
 | 
						|
                    } else {
 | 
						|
                        push @output, "$item: na";
 | 
						|
                    }
 | 
						|
                } else {
 | 
						|
                    push @output, "$item: $data";
 | 
						|
                }
 | 
						|
            } else {
 | 
						|
                push @output, "$item: na";
 | 
						|
            }
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    # save the values gotten for setting
 | 
						|
    my @setneed;
 | 
						|
    if (scalar(keys %writelist)) {
 | 
						|
        @setneed = @output;
 | 
						|
        @output  = ();
 | 
						|
    }
 | 
						|
 | 
						|
    # Handle the setting operation
 | 
						|
    foreach my $item (keys %writelist) {
 | 
						|
        my $oid = "";
 | 
						|
        my $svalue;
 | 
						|
        my $cvalue;
 | 
						|
 | 
						|
        my $capmax;
 | 
						|
        my $capmin;
 | 
						|
        if ($item eq "cappingstatus") {
 | 
						|
            if ($writelist{$item} eq "on") {
 | 
						|
                $cvalue = "1";
 | 
						|
            } elsif ($writelist{$item} eq "off") {
 | 
						|
                $cvalue = "0";
 | 
						|
            } else {
 | 
						|
                return (1, "The setting value should be on|off.");
 | 
						|
            }
 | 
						|
 | 
						|
            # Get the power control value
 | 
						|
            my $cdata = $session->get([ $PowerControl_oid . "." . $slot ]);
 | 
						|
            if ($session->{ErrorStr}) { return (1, $session->{ErrorStr}); }
 | 
						|
 | 
						|
            # 1 all off; 2 cap;
 | 
						|
            # 4 staticsaving; 5 cap + staticsaving;
 | 
						|
            # 9 dynamicsaving; 10 cap + dynamicsaving;
 | 
						|
 | 
						|
            if ($cvalue eq "1") {
 | 
						|
 | 
						|
                # to enable capping
 | 
						|
                if ($cdata eq "2" || $cdata eq "5" || $cdata eq "10") {
 | 
						|
                    return (0, "Power capping has been enabled.");
 | 
						|
                } elsif ($cdata eq "0" || $cdata eq "1") {
 | 
						|
                    $cvalue = "2";
 | 
						|
                } elsif ($cdata eq "4") {
 | 
						|
                    $cvalue = "5";
 | 
						|
                } elsif ($cdata eq "9") {
 | 
						|
                    $cvalue = "10";
 | 
						|
                } else {
 | 
						|
                    return (1, "Encountered error to turn on capping.");
 | 
						|
                }
 | 
						|
            } else {
 | 
						|
 | 
						|
                # to disable capping
 | 
						|
                if ($cdata eq "1" || $cdata eq "4" || $cdata eq "9") {
 | 
						|
                    return (0, "Power capping has been disabled.");
 | 
						|
                } elsif ($cdata eq "2") {
 | 
						|
                    $cvalue = "1";
 | 
						|
                } elsif ($cdata eq "5") {
 | 
						|
                    $cvalue = "4";
 | 
						|
                } elsif ($cdata eq "10") {
 | 
						|
                    $cvalue = "9";
 | 
						|
                } else {
 | 
						|
                    return (1, "Encountered error to turn off capping.");
 | 
						|
                }
 | 
						|
            }
 | 
						|
 | 
						|
            my $data = $session->set(new SNMP::Varbind([ $PowerControl_oid, $slot, $cvalue, 'INTEGER' ]));
 | 
						|
            unless ($data) { return (1, $session->{ErrorStr}); }
 | 
						|
 | 
						|
            my $rdata = $session->get([ $PowerControl_oid . "." . $slot ]);
 | 
						|
            if ($session->{ErrorStr}) { return (1, $session->{ErrorStr}); }
 | 
						|
            if ($rdata ne $cvalue) {
 | 
						|
                return (1, "$item: set operation failed.");
 | 
						|
            }
 | 
						|
        } elsif ($item eq "cappingwatt" || $item eq "cappingperc") {
 | 
						|
            my $bladewidth = $session->get([ $bladewidth_oid . ".$slot" ]);
 | 
						|
            if ($session->{ErrorStr}) { return (1, $session->{ErrorStr}); }
 | 
						|
            if ($bladewidth == 1) {
 | 
						|
                foreach my $i (@setneed) {
 | 
						|
                    if ($i =~ /^cappingmax: (\d*)W/) {
 | 
						|
                        $capmax = $1;
 | 
						|
                    } elsif ($i =~ /^cappingmin: (\d*)W/) {
 | 
						|
                        $capmin = $1;
 | 
						|
                    }
 | 
						|
                }
 | 
						|
 | 
						|
                if (!(defined($capmax) && defined($capmin))) {
 | 
						|
                    return (1, "Cannot get the value of cappingmin or cappingmax.");
 | 
						|
                }
 | 
						|
 | 
						|
                if ($item eq "cappingwatt" && ($writelist{$item} > $capmax || $writelist{$item} < $capmin)) {
 | 
						|
                    return (1, "The set value should be in the range $capmin - $capmax.");
 | 
						|
                }
 | 
						|
 | 
						|
                if ($item eq "cappingperc") {
 | 
						|
                    if ($writelist{$item} > 100 || $writelist{$item} < 0) {
 | 
						|
                        return (1, "The percentage value should be in the range 0 - 100");
 | 
						|
                    }
 | 
						|
                    $writelist{$item} = int(($capmax - $capmin) * $writelist{$item} / 100 + $capmin);
 | 
						|
                }
 | 
						|
 | 
						|
                my $data = $session->set(new SNMP::Varbind([ $powercapping_oid, $slot, $writelist{$item}, 'INTEGER' ]));
 | 
						|
                unless ($data) { return (1, $session->{ErrorStr}); }
 | 
						|
 | 
						|
                my $ndata = $session->get([ $powercapping_oid . "." . $slot ]);
 | 
						|
                if ($session->{ErrorStr}) { return (1, $session->{ErrorStr}); }
 | 
						|
                if ($ndata ne $writelist{$item}) {
 | 
						|
                    return (1, "$item: set operation failed.");
 | 
						|
                }
 | 
						|
            } elsif ($bladewidth == 2) {
 | 
						|
 | 
						|
                # for double wide blade, the capping needs to be set for the two slots one by one
 | 
						|
                # base on the min/max of the slots to know the rate of how many set to slot1 and how many set to slot2
 | 
						|
                my $min1 = $session->get([ $PowerPcapMin_oid . "." . $slot ]);
 | 
						|
                if ($session->{ErrorStr}) { return (1, $session->{ErrorStr}); }
 | 
						|
                my $min2 = $session->get([ $PowerPcapMin_oid . "." . ($slot + 1) ]);
 | 
						|
                if ($session->{ErrorStr}) { return (1, $session->{ErrorStr}); }
 | 
						|
                my $max1 = $session->get([ $PowerPcapMax_oid . "." . $slot ]);
 | 
						|
                if ($session->{ErrorStr}) { return (1, $session->{ErrorStr}); }
 | 
						|
                my $max2 = $session->get([ $PowerPcapMax_oid . "." . ($slot + 1) ]);
 | 
						|
                if ($session->{ErrorStr}) { return (1, $session->{ErrorStr}); }
 | 
						|
 | 
						|
                my ($cv1, $cv2);
 | 
						|
                if ($item eq "cappingperc") {
 | 
						|
                    if ($writelist{$item} > 100 || $writelist{$item} < 0) {
 | 
						|
                        return (1, "The percentage value should be in the range 0 - 100");
 | 
						|
                    }
 | 
						|
                    $cv1 = int(($max1 - $min1) * $writelist{$item} / 100 + $min1);
 | 
						|
                    $cv2 = int(($max2 - $min2) * $writelist{$item} / 100 + $min2);
 | 
						|
                } elsif ($item eq "cappingwatt") {
 | 
						|
                    if (($min1 + $min2) > $writelist{$item} || ($max1 + $max2) < $writelist{$item}) {
 | 
						|
                        return (1, "The set value should be in the range " . ($min1 + $min2) . " - " . ($max1 + $max2) . ".");
 | 
						|
                    } elsif (($max1 + $max2) == $writelist{$item}) {
 | 
						|
                        $cv1 = $max1;
 | 
						|
                        $cv2 = $max2;
 | 
						|
                    } elsif (($min1 + $min2) == $writelist{$item}) {
 | 
						|
                        $cv1 = $min1;
 | 
						|
                        $cv2 = $min2;
 | 
						|
                    } else {
 | 
						|
                        my $x1 = ($max1 + $min1) / 2;
 | 
						|
                        my $x2 = ($max2 + $min2) / 2;
 | 
						|
 | 
						|
                        # cv1/cv2 = $x1/$x2; cv1+cv2=$writelist{$item}
 | 
						|
                        $cv1 = int($writelist{$item} * $x1 / ($x1 + $x2));
 | 
						|
                        $cv2 = $writelist{$item} - $cv1;
 | 
						|
                    }
 | 
						|
                }
 | 
						|
                my $data = $session->set(new SNMP::Varbind([ $powercapping_oid, $slot, $cv1, 'INTEGER' ]));
 | 
						|
                unless ($data) { return (1, $session->{ErrorStr}); }
 | 
						|
 | 
						|
                $data = $session->set(new SNMP::Varbind([ $powercapping_oid, ($slot + 1), $cv2, 'INTEGER' ]));
 | 
						|
                unless ($data) { return (1, $session->{ErrorStr}); }
 | 
						|
            } else {
 | 
						|
                return (1, "Don't know the wide of the blade.");
 | 
						|
            }
 | 
						|
        } elsif ($item eq "savingstatus") {
 | 
						|
            if ($writelist{$item} eq "on") {
 | 
						|
                $svalue = "1";
 | 
						|
            } elsif ($writelist{$item} eq "off") {
 | 
						|
                $svalue = "0";
 | 
						|
            } else {
 | 
						|
                return (1, "The setting value should be on|off.");
 | 
						|
            }
 | 
						|
 | 
						|
            # static power saving and dynamic power saving cannot be turn on at same time
 | 
						|
            if ($svalue eq "1") {
 | 
						|
                my $gdata = $session->get([ $dsavingstatus_oid . "." . $slot ]);
 | 
						|
                if ($session->{ErrorStr}) { return (1, $session->{ErrorStr}); }
 | 
						|
 | 
						|
                if ($gdata eq "1") {
 | 
						|
                    return (1, "The attributes savingstatus and dsavingstatus cannot be turn on at same time.");
 | 
						|
                }
 | 
						|
            }
 | 
						|
 | 
						|
            # get the attribute static power save
 | 
						|
            my $data = $session->get([ $savingstatus_oid . "." . $slot ]);
 | 
						|
            if ($session->{ErrorStr}) { return (1, $session->{ErrorStr}); }
 | 
						|
            if ($data eq "NOSUCHINSTANCE" || $data eq "notApplicable" || $data eq "255") {
 | 
						|
                return (1, "Does not supported by this blade server.");
 | 
						|
            }
 | 
						|
            if ($data ne $svalue) {
 | 
						|
 | 
						|
                # set it
 | 
						|
                my $sdata = $session->set(new SNMP::Varbind([ $savingstatus_oid, $slot, $svalue, 'INTEGER' ]));
 | 
						|
                unless ($sdata) { return (1, $session->{ErrorStr}); }
 | 
						|
 | 
						|
                my $ndata = $session->get([ $savingstatus_oid . "." . $slot ]);
 | 
						|
                if ($session->{ErrorStr}) { return (1, $session->{ErrorStr}); }
 | 
						|
                if ($ndata ne $svalue) {
 | 
						|
                    return (1, "Set operation failed.");
 | 
						|
                }
 | 
						|
            }
 | 
						|
        } elsif ($item eq "dsavingstatus") {
 | 
						|
            if ($writelist{$item} eq "on-norm") {
 | 
						|
                $svalue = "1";
 | 
						|
            } elsif ($writelist{$item} eq "on-maxp") {
 | 
						|
                $svalue = "2";
 | 
						|
            } elsif ($writelist{$item} eq "off") {
 | 
						|
                $svalue = "0";
 | 
						|
            } else {
 | 
						|
                return (1, "The setting value should be one of on-norm|on-maxp|off.");
 | 
						|
            }
 | 
						|
 | 
						|
            # static power saving and dynamic power saving cannot be turn on at same time
 | 
						|
            if ($svalue gt "0") {
 | 
						|
                my $gdata = $session->get([ $savingstatus_oid . "." . $slot ]);
 | 
						|
                if ($session->{ErrorStr}) { return (1, $session->{ErrorStr}); }
 | 
						|
 | 
						|
                if ($gdata eq "1") {
 | 
						|
                    return (1, "The attributes savingstatus and dsavingstatus cannot be turn on at same time.");
 | 
						|
                }
 | 
						|
            }
 | 
						|
 | 
						|
            # get the attribute dynamic power save
 | 
						|
            my $data = $session->get([ $dsavingstatus_oid . "." . $slot ]);
 | 
						|
            if ($session->{ErrorStr}) { return (1, $session->{ErrorStr}); }
 | 
						|
            if ($data eq "NOSUCHINSTANCE" || $data eq "notApplicable" || $data eq "255") {
 | 
						|
                return (1, "Does not supported by this blade server.");
 | 
						|
            }
 | 
						|
 | 
						|
            # get the attribute favor performance
 | 
						|
            my $pdata = $session->get([ $dsperformance_oid . "." . $slot ]);
 | 
						|
            if ($session->{ErrorStr}) { return (1, $session->{ErrorStr}); }
 | 
						|
            if ($pdata eq "NOSUCHINSTANCE" || $pdata eq "notApplicable" || $pdata eq "255") {
 | 
						|
                $pdata = "255";
 | 
						|
            }
 | 
						|
 | 
						|
            # turn off the dynamic power save
 | 
						|
            if ($svalue eq "0" && ($data eq "1" || $pdata eq "1")) {
 | 
						|
                if ($data eq "1") {
 | 
						|
                    my $sdata = $session->set(new SNMP::Varbind([ $dsavingstatus_oid, $slot, "0", 'INTEGER' ]));
 | 
						|
                    unless ($sdata) { return (1, $session->{ErrorStr}); }
 | 
						|
 | 
						|
                    my $ndata = $session->get([ $dsavingstatus_oid . "." . $slot ]);
 | 
						|
                    if ($session->{ErrorStr}) { return (1, $session->{ErrorStr}); }
 | 
						|
                    if ($ndata ne "0") {
 | 
						|
                        return (1, "Set operation failed.");
 | 
						|
                    }
 | 
						|
                }
 | 
						|
                if ($pdata eq "1") {
 | 
						|
                    my $sdata = $session->set(new SNMP::Varbind([ $dsperformance_oid, $slot, "0", 'INTEGER' ]));
 | 
						|
                    unless ($sdata) { return (1, $session->{ErrorStr}); }
 | 
						|
 | 
						|
                    my $ndata = $session->get([ $dsperformance_oid . "." . $slot ]);
 | 
						|
                    if ($session->{ErrorStr}) { return (1, $session->{ErrorStr}); }
 | 
						|
                    if ($ndata ne "0") {
 | 
						|
                        return (1, "Set operation failed.");
 | 
						|
                    }
 | 
						|
                }
 | 
						|
            }
 | 
						|
 | 
						|
            # trun on the dynamic power save but trun off the favor performance
 | 
						|
            if ($svalue eq "1" && ($data eq "0" || $pdata eq "1")) {
 | 
						|
                if ($data eq "0") {
 | 
						|
                    my $sdata = $session->set(new SNMP::Varbind([ $dsavingstatus_oid, $slot, "1", 'INTEGER' ]));
 | 
						|
                    unless ($sdata) { return (1, $session->{ErrorStr}); }
 | 
						|
 | 
						|
                    my $ndata = $session->get([ $dsavingstatus_oid . "." . $slot ]);
 | 
						|
                    if ($session->{ErrorStr}) { return (1, $session->{ErrorStr}); }
 | 
						|
                    if ($ndata ne "1") {
 | 
						|
                        return (1, "Set operation failed.");
 | 
						|
                    }
 | 
						|
                }
 | 
						|
 | 
						|
                if ($pdata eq "1") {
 | 
						|
                    my $sdata = $session->set(new SNMP::Varbind([ $dsperformance_oid, $slot, "0", 'INTEGER' ]));
 | 
						|
                    unless ($sdata) { return (1, $session->{ErrorStr}); }
 | 
						|
 | 
						|
                    my $ndata = $session->get([ $dsperformance_oid . "." . $slot ]);
 | 
						|
                    if ($session->{ErrorStr}) { return (1, $session->{ErrorStr}); }
 | 
						|
                    if ($ndata ne "0") {
 | 
						|
                        return (1, "Set operation failed.");
 | 
						|
                    }
 | 
						|
                }
 | 
						|
            }
 | 
						|
 | 
						|
            # trun on the dynamic power save and trun on the favor performance
 | 
						|
            if ($svalue eq "2" && $pdata eq "255") {
 | 
						|
                return (1, "The on-maxp is NOT supported.");
 | 
						|
            }
 | 
						|
            if ($svalue eq "2" && ($data eq "0" || $pdata eq "0")) {
 | 
						|
                if ($data eq "0") {
 | 
						|
                    my $sdata = $session->set(new SNMP::Varbind([ $dsavingstatus_oid, $slot, "1", 'INTEGER' ]));
 | 
						|
                    unless ($sdata) { return (1, $session->{ErrorStr}); }
 | 
						|
 | 
						|
                    my $ndata = $session->get([ $dsavingstatus_oid . "." . $slot ]);
 | 
						|
                    if ($session->{ErrorStr}) { return (1, $session->{ErrorStr}); }
 | 
						|
                    if ($ndata ne "1") {
 | 
						|
                        return (1, "Set operation failed.");
 | 
						|
                    }
 | 
						|
                }
 | 
						|
 | 
						|
                if ($pdata eq "0") {
 | 
						|
                    my $sdata = $session->set(new SNMP::Varbind([ $dsperformance_oid, $slot, "1", 'INTEGER' ]));
 | 
						|
                    unless ($sdata) { return (1, $session->{ErrorStr}); }
 | 
						|
 | 
						|
                    my $ndata = $session->get([ $dsperformance_oid . "." . $slot ]);
 | 
						|
                    if ($session->{ErrorStr}) { return (1, $session->{ErrorStr}); }
 | 
						|
                    if ($ndata ne "1") {
 | 
						|
                        return (1, "Set operation failed.");
 | 
						|
                    }
 | 
						|
                }
 | 
						|
            }
 | 
						|
        } else {
 | 
						|
            return (1, "$item is NOT a valid attribute..");
 | 
						|
        }
 | 
						|
 | 
						|
        push @output, "$item: Set operation succeeded.";
 | 
						|
    }
 | 
						|
 | 
						|
    return (0, @output);
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
# the mib object of complex table
 | 
						|
my $comp_table_oid = ".1.3.6.1.4.1.2.3.51.2.24.1";    #scalableComplexTable
 | 
						|
my $comppart_table_oid = ".1.3.6.1.4.1.2.3.51.2.24.2"; #scalableComplexPartitionTable
 | 
						|
my $compnode_table_oid = ".1.3.6.1.4.1.2.3.51.2.24.3"; #scalableComplexNodeTable
 | 
						|
 | 
						|
# the mib object used for flexnode management
 | 
						|
my $comp_id_oid = ".1.3.6.1.4.1.2.3.51.2.24.1.1.1";   #scalableComplexIdentifier
 | 
						|
my $comp_part_num_oid = ".1.3.6.1.4.1.2.3.51.2.24.1.1.2"; #scalableComplexNumPartitions
 | 
						|
my $comp_node_num_oid = ".1.3.6.1.4.1.2.3.51.2.24.1.1.3"; #scalableComplexNumNodes
 | 
						|
 | 
						|
# following two oid are used for create partition
 | 
						|
my $comp_node_start_oid = ".1.3.6.1.4.1.2.3.51.2.24.1.1.4"; #scalableComplexPartStartSlot
 | 
						|
my $comp_partnode_num_oid = ".1.3.6.1.4.1.2.3.51.2.24.1.1.5"; #scalableComplexPartNumNodes
 | 
						|
 | 
						|
# operate for the partition
 | 
						|
my $comp_action_oid = ".1.3.6.1.4.1.2.3.51.2.24.1.1.6";   #scalableComplexAction
 | 
						|
 | 
						|
 | 
						|
# oid for complex partitions
 | 
						|
my $comp_part_comp_id_oid = ".1.3.6.1.4.1.2.3.51.2.24.2.1.1"; #scalableComplexId
 | 
						|
my $comp_part_mode_oid = ".1.3.6.1.4.1.2.3.51.2.24.2.1.3"; #scalableComplexPartitionMode
 | 
						|
my $comp_part_nodenum_oid = ".1.3.6.1.4.1.2.3.51.2.24.2.1.4"; #scalableComplexPartitionNumNodes
 | 
						|
my $comp_part_status_oid = ".1.3.6.1.4.1.2.3.51.2.24.2.1.5"; #scalableComplexPartitionStatus
 | 
						|
my $comp_part_action_oid = ".1.3.6.1.4.1.2.3.51.2.24.2.1.6"; #scalableComplexPartitionAction
 | 
						|
 | 
						|
 | 
						|
#oid for complex nodes
 | 
						|
my $comp_node_slot_oid = ".1.3.6.1.4.1.2.3.51.2.24.3.1.1"; #scalableComplexNodeSlot
 | 
						|
my $comp_node_type_oid = ".1.3.6.1.4.1.2.3.51.2.24.3.1.3"; #scalableComplexNodeType
 | 
						|
my $comp_node_res_oid = ".1.3.6.1.4.1.2.3.51.2.24.3.1.4"; #scalableComplexNodeResources
 | 
						|
my $comp_node_role_oid = ".1.3.6.1.4.1.2.3.51.2.24.3.1.5"; #scalableComplexNodeRole
 | 
						|
my $comp_node_state_oid = ".1.3.6.1.4.1.2.3.51.2.24.3.1.6"; #scalableComplexNodeState
 | 
						|
my $comp_node_cid_oid = ".1.3.6.1.4.1.2.3.51.2.24.3.1.10"; #scalableComplexNodeComplexID
 | 
						|
my $comp_node_pid_oid = ".1.3.6.1.4.1.2.3.51.2.24.3.1.11"; #scalableComplexNodePartitionID
 | 
						|
my $comp_node_lid_oid = ".1.3.6.1.4.1.2.3.51.2.24.3.1.12"; #scalableComplexNodeLogicalID
 | 
						|
my $comp_node_action_oid = ".1.3.6.1.4.1.2.3.51.2.24.3.1.14"; #scalableComplexNodeAction
 | 
						|
 | 
						|
my %compdata = ();
 | 
						|
 | 
						|
# get all the attributes for a specified complex
 | 
						|
sub getcomplex {
 | 
						|
    my ($complex_id) = @_;
 | 
						|
 | 
						|
    my $oid  = $comp_part_num_oid . ".$complex_id";
 | 
						|
    my $data = $session->get([$oid]);
 | 
						|
    if ($session->{ErrorStr}) { return (1, $session->{ErrorStr}); }
 | 
						|
    $compdata{$complex_id}{'Partition number'} = $data;
 | 
						|
 | 
						|
    $oid  = $comp_node_num_oid . ".$complex_id";
 | 
						|
    $data = $session->get([$oid]);
 | 
						|
    if ($session->{ErrorStr}) { return (1, $session->{ErrorStr}); }
 | 
						|
    $compdata{$complex_id}{'Complex node number'} = $data;
 | 
						|
}
 | 
						|
 | 
						|
# get all the attributes for a partition which belong a certain complex
 | 
						|
sub getcomppart {
 | 
						|
    my ($complex_id, $part_id) = @_;
 | 
						|
 | 
						|
    my $oid  = $comp_part_mode_oid . ".$complex_id" . ".$part_id";
 | 
						|
    my $data = $session->get([$oid]);
 | 
						|
    if ($data == 1) {
 | 
						|
        $data = "partition";
 | 
						|
    } elsif ($data == 2) {
 | 
						|
        $data = "standalone";
 | 
						|
    }
 | 
						|
    if ($session->{ErrorStr}) { return (1, $session->{ErrorStr}); }
 | 
						|
    $compdata{$complex_id}{'partition'}{$part_id}{'Partition Mode'} = $data;
 | 
						|
 | 
						|
    $oid  = $comp_part_nodenum_oid . ".$complex_id" . ".$part_id";
 | 
						|
    $data = $session->get([$oid]);
 | 
						|
    if ($session->{ErrorStr}) { return (1, $session->{ErrorStr}); }
 | 
						|
    $compdata{$complex_id}{'partition'}{$part_id}{'Partition node number'} = $data;
 | 
						|
 | 
						|
    $oid  = $comp_part_status_oid . ".$complex_id" . ".$part_id";
 | 
						|
    $data = $session->get([$oid]);
 | 
						|
    if ($data == 1) {
 | 
						|
        $data = "poweredoff";
 | 
						|
    } elsif ($data == 2) {
 | 
						|
        $data = "poweredon";
 | 
						|
    } elsif ($data == 3) {
 | 
						|
        $data = "resetting";
 | 
						|
    } else {
 | 
						|
        $data = "invalid";
 | 
						|
    }
 | 
						|
    if ($session->{ErrorStr}) { return (1, $session->{ErrorStr}); }
 | 
						|
    $compdata{$complex_id}{'partition'}{$part_id}{'Partition status'} = $data;
 | 
						|
}
 | 
						|
 | 
						|
# get all the attributes for a node in a complex
 | 
						|
sub getcomnode {
 | 
						|
    my ($node_id) = @_;
 | 
						|
 | 
						|
    my $oid           = $comp_node_lid_oid . ".$node_id";
 | 
						|
    my $node_logic_id = $session->get([$oid]);
 | 
						|
    if ($session->{ErrorStr}) { return (1, $session->{ErrorStr}); }
 | 
						|
 | 
						|
    $oid = $comp_node_cid_oid . ".$node_id";
 | 
						|
    my $complex_id = $session->get([$oid]);
 | 
						|
    if ($session->{ErrorStr}) { return (1, $session->{ErrorStr}); }
 | 
						|
 | 
						|
    $oid = $comp_node_pid_oid . ".$node_id";
 | 
						|
    my $part_id = $session->get([$oid]);
 | 
						|
    if ($session->{ErrorStr}) { return (1, $session->{ErrorStr}); }
 | 
						|
 | 
						|
    $oid = $comp_node_slot_oid . ".$node_id";
 | 
						|
    my $slot_id = $session->get([$oid]);
 | 
						|
 | 
						|
    if ($part_id == 255) {
 | 
						|
        $part_id       = "unassigned";
 | 
						|
        $node_logic_id = $slot_id;
 | 
						|
    }
 | 
						|
 | 
						|
    if ($session->{ErrorStr}) { return (1, $session->{ErrorStr}); }
 | 
						|
    $compdata{$complex_id}{'partition'}{$part_id}{'node'}{$node_logic_id}{'Node slot'} = $slot_id;
 | 
						|
 | 
						|
    $oid = $comp_node_type_oid . ".$node_id";
 | 
						|
    my $data = $session->get([$oid]);
 | 
						|
    if ($data == 1) {
 | 
						|
        $data = "processor";
 | 
						|
    } elsif ($data == 2) {
 | 
						|
        $data = "memory";
 | 
						|
    } elsif ($data == 3) {
 | 
						|
        $data = "io";
 | 
						|
    }
 | 
						|
    if ($session->{ErrorStr}) { return (1, $session->{ErrorStr}); }
 | 
						|
    $compdata{$complex_id}{'partition'}{$part_id}{'node'}{$node_logic_id}{'Node type'} = $data;
 | 
						|
 | 
						|
    $oid = $comp_node_res_oid . ".$node_id";
 | 
						|
    my $data = $session->get([$oid]);
 | 
						|
    if ($session->{ErrorStr}) { return (1, $session->{ErrorStr}); }
 | 
						|
    $compdata{$complex_id}{'partition'}{$part_id}{'node'}{$node_logic_id}{'Node resource'} = $data;
 | 
						|
 | 
						|
    $oid = $comp_node_role_oid . ".$node_id";
 | 
						|
    my $data = $session->get([$oid]);
 | 
						|
    if ($data == 1) {
 | 
						|
        $data = "primary";
 | 
						|
    } elsif ($data == 2) {
 | 
						|
        $data = "secondary";
 | 
						|
    } else {
 | 
						|
        $data = "unassigned";
 | 
						|
    }
 | 
						|
    if ($session->{ErrorStr}) { return (1, $session->{ErrorStr}); }
 | 
						|
    $compdata{$complex_id}{'partition'}{$part_id}{'node'}{$node_logic_id}{'Node role'} = $data;
 | 
						|
 | 
						|
    $oid = $comp_node_state_oid . ".$node_id";
 | 
						|
    my $data = $session->get([$oid]);
 | 
						|
    if ($data == 1) {
 | 
						|
        $data = "poweredoff";
 | 
						|
    } elsif ($data == 2) {
 | 
						|
        $data = "poweredon";
 | 
						|
    } elsif ($data == 3) {
 | 
						|
        $data = "resetting";
 | 
						|
    }
 | 
						|
    if ($session->{ErrorStr}) { return (1, $session->{ErrorStr}); }
 | 
						|
    $compdata{$complex_id}{'partition'}{$part_id}{'node'}{$node_logic_id}{'Node state'} = $data;
 | 
						|
 | 
						|
    return ($complex_id, $part_id, $node_logic_id);
 | 
						|
}
 | 
						|
 | 
						|
# display the flexnodes for amm
 | 
						|
sub lsflexnode {
 | 
						|
    my ($mpa, $node, $slot, @moreslot) = @_;
 | 
						|
 | 
						|
    my @output = ();
 | 
						|
    %compdata = ();
 | 
						|
 | 
						|
    # if specify the mpa as node, then list all the complex, partition and node in this chassis
 | 
						|
    if ($node eq $mpa) {
 | 
						|
        my @attrs = ($comp_id_oid);
 | 
						|
        while (1) {
 | 
						|
            my $orig_oid = $attrs[0];
 | 
						|
            $session->getnext(\@attrs);
 | 
						|
            if ($session->{ErrorStr}) { return (1, $session->{ErrorStr}); }
 | 
						|
 | 
						|
            # if success of getnext, the @attrs will be set to (obj,iid,val,type)
 | 
						|
            my $complex_obj = $attrs[0];
 | 
						|
            my $complex_id  = $attrs[1];
 | 
						|
            if ($orig_oid =~ /^$complex_obj/) {
 | 
						|
                &getcomplex($complex_id);
 | 
						|
 | 
						|
                # search all the partitions in the complex
 | 
						|
                my @part_attrs = ($comp_part_comp_id_oid . ".$complex_id");
 | 
						|
                while (1) {
 | 
						|
                    my $orig_part_oid = $part_attrs[0];
 | 
						|
                    $session->getnext(\@part_attrs);
 | 
						|
                    if ($session->{ErrorStr}) { return (1, $session->{ErrorStr}); }
 | 
						|
 | 
						|
                    my $part_obj = $part_attrs[0];
 | 
						|
                    my $part_id  = $part_attrs[1];
 | 
						|
                    if ($orig_part_oid =~ /^$part_obj/) {
 | 
						|
                        &getcomppart($complex_id, $part_id);
 | 
						|
 | 
						|
                    } else {
 | 
						|
                        last;
 | 
						|
                    }
 | 
						|
 | 
						|
                    @part_attrs = ($part_obj . ".$part_id");
 | 
						|
                }    # end of searching partition
 | 
						|
 | 
						|
            } else {
 | 
						|
                last;
 | 
						|
            }
 | 
						|
 | 
						|
            @attrs = ($complex_obj . ".$complex_id");
 | 
						|
        }    # end of searching complex
 | 
						|
 | 
						|
        # search all the nodes in the complex
 | 
						|
        my @node_attrs = ($comp_node_slot_oid);
 | 
						|
        while (1) {
 | 
						|
            my $orig_node_oid = $node_attrs[0];
 | 
						|
            $session->getnext(\@node_attrs);
 | 
						|
            if ($session->{ErrorStr}) { return (1, $session->{ErrorStr}); }
 | 
						|
 | 
						|
            my $node_obj = $node_attrs[0];
 | 
						|
            my $node_id  = $node_attrs[1];
 | 
						|
            if ($orig_node_oid =~ /^$node_obj/) {
 | 
						|
                &getcomnode($node_id);
 | 
						|
            } else {
 | 
						|
                last;
 | 
						|
            }
 | 
						|
 | 
						|
            @node_attrs = ($node_obj . ".$node_id");
 | 
						|
        }
 | 
						|
 | 
						|
        # display complex, parition and nodes in a chassis
 | 
						|
        foreach my $comp (keys %compdata) {
 | 
						|
            push @output, "Complex - $comp";
 | 
						|
 | 
						|
            foreach my $compattr (keys %{ $compdata{$comp} }) {
 | 
						|
                if ($compattr ne "partition") {
 | 
						|
                    push @output, "..$compattr - $compdata{$comp}{$compattr}";
 | 
						|
                } else {
 | 
						|
                    foreach my $part (sort(keys %{ $compdata{$comp}{'partition'} })) {
 | 
						|
                        push @output, "..Partition = $part";
 | 
						|
                        foreach my $partattr (keys %{ $compdata{$comp}{'partition'}{$part} }) {
 | 
						|
                            if ($partattr ne "node") {
 | 
						|
                                push @output, "....$partattr - $compdata{$comp}{'partition'}{$part}{$partattr}";
 | 
						|
                            } else {
 | 
						|
                                foreach my $node (sort(keys %{ $compdata{$comp}{'partition'}{$part}{'node'} })) {
 | 
						|
                                    if ($node eq "unassigned") {
 | 
						|
                                        push @output, "....Node - $node (slot id)";
 | 
						|
                                    } else {
 | 
						|
                                        push @output, "....Node - $node (logic id)";
 | 
						|
                                    }
 | 
						|
                                    foreach my $nodeattr (keys %{ $compdata{$comp}{'partition'}{$part}{'node'}{$node} }) {
 | 
						|
                                        push @output, "......$nodeattr - $compdata{$comp}{'partition'}{$part}{'node'}{$node}{$nodeattr}";
 | 
						|
                                    }
 | 
						|
                                }    #end of node go ghrough
 | 
						|
                            }
 | 
						|
                        }    #end of partition attributes
 | 
						|
                    }    #end of parition go through
 | 
						|
                }
 | 
						|
            }    #end of complex attributes
 | 
						|
        }    #end of complex go through
 | 
						|
 | 
						|
    } else {    # display the information of a node
 | 
						|
        my @slots = ($slot, @moreslot);
 | 
						|
        my @sortslots = sort(@slots);
 | 
						|
        foreach (0 .. $#sortslots - 1) {
 | 
						|
            if ($sortslots[$_] + 1 != $sortslots[ $_ + 1 ]) {
 | 
						|
                return (1, "The slots used to create flexed node should be consecutive.");
 | 
						|
            }
 | 
						|
        }
 | 
						|
 | 
						|
        #get the slot information
 | 
						|
        my $complex_flag = "";
 | 
						|
        my $part_flag    = "";
 | 
						|
        foreach my $slot (@sortslots) {
 | 
						|
            my ($complex_id, $part_id, $node_id) = &getcomnode($slot);
 | 
						|
            if ($complex_id eq "NOSUCHINSTANCE") {
 | 
						|
                return (1, "This node should belong to a complex.");
 | 
						|
            }
 | 
						|
            if ($complex_flag ne "" && $complex_flag ne $complex_id) {
 | 
						|
                return (1, "All the slots of this flexnode should be located in one complex.");
 | 
						|
            } else {
 | 
						|
                $complex_flag = $complex_id;
 | 
						|
            }
 | 
						|
            if ($part_flag ne "" && $part_flag ne $part_id) {
 | 
						|
                return (1, "All the slots of this flexnode should belong to one parition.");
 | 
						|
            } else {
 | 
						|
                $part_flag = $part_id;
 | 
						|
            }
 | 
						|
 | 
						|
            if ($slot eq $sortslots[0]) {
 | 
						|
                my $oid  = $comp_part_status_oid . ".$complex_id" . ".$part_id";
 | 
						|
                my $data = $session->get([$oid]);
 | 
						|
                if ($data == 1) {
 | 
						|
                    $data = "poweredoff";
 | 
						|
                } elsif ($data == 2) {
 | 
						|
                    $data = "poweredon";
 | 
						|
                } elsif ($data == 3) {
 | 
						|
                    $data = "resetting";
 | 
						|
                } else {
 | 
						|
                    $data = "invalid";
 | 
						|
                }
 | 
						|
                if ($session->{ErrorStr}) { return (1, $session->{ErrorStr}); }
 | 
						|
                push @output, "Flexnode state - $data";
 | 
						|
                push @output, "Complex id - $complex_id";
 | 
						|
                push @output, "Partition id - $part_id";
 | 
						|
            }
 | 
						|
            foreach my $nodeattr (keys %{ $compdata{$complex_id}{'partition'}{$part_id}{'node'}{$node_id} }) {
 | 
						|
                push @output, "Slot$slot: $nodeattr - $compdata{$complex_id}{'partition'}{$part_id}{'node'}{$node_id}{$nodeattr}";
 | 
						|
            }
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    return (0, @output);
 | 
						|
}
 | 
						|
 | 
						|
# Create a flexnode
 | 
						|
sub mkflexnode {
 | 
						|
    my ($mpa, $node, $slot, @moreslot) = @_;
 | 
						|
 | 
						|
    my @slots = ($slot, @moreslot);
 | 
						|
 | 
						|
    # the slots assigned for a partition must be consecutive
 | 
						|
    my @sortslots = sort(@slots);
 | 
						|
    foreach (0 .. $#sortslots - 1) {
 | 
						|
        if ($sortslots[$_] + 1 != $sortslots[ $_ + 1 ]) {
 | 
						|
            return (1, "The slots used to create flexed node should be consecutive.");
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    # get the status of all the nodes
 | 
						|
    my $complex_id = "";
 | 
						|
    foreach my $slot (@sortslots) {
 | 
						|
 | 
						|
        #get the complex of the node
 | 
						|
        my $oid       = $comp_node_cid_oid . ".$slot";
 | 
						|
        my $node_comp = $session->get([$oid]);
 | 
						|
        if ($session->{ErrorStr}) { return (1, $session->{ErrorStr}); }
 | 
						|
        if ($node_comp eq 'NOSUCHINSTANCE') {
 | 
						|
            return (1, "The slot [$slot] is NOT a member of a complex.");
 | 
						|
        }
 | 
						|
 | 
						|
        # all the nodes should be located in one complex
 | 
						|
        if ($complex_id ne "" && $node_comp ne $complex_id) {
 | 
						|
            return (1, "All the slots of this flexnode should be located in one complex.");
 | 
						|
        } else {
 | 
						|
            $complex_id = $node_comp;
 | 
						|
        }
 | 
						|
 | 
						|
        $oid = $comp_node_pid_oid . ".$slot";
 | 
						|
        my $node_part = $session->get([$oid]);
 | 
						|
        if ($session->{ErrorStr}) { return (1, $session->{ErrorStr}); }
 | 
						|
        if ($node_part ne '255') {
 | 
						|
            return (1, "The slot [$slot] has been assigned to one partition.");
 | 
						|
        }
 | 
						|
 | 
						|
        $oid = $comp_node_state_oid . ".$slot";
 | 
						|
        my $node_state = $session->get([$oid]);
 | 
						|
        if ($session->{ErrorStr}) { return (1, $session->{ErrorStr}); }
 | 
						|
        if ($node_state != 1) {    # 1 is power off
 | 
						|
            return (1, "The slot [$slot] is NOT in power off state.");
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    # set the startslot
 | 
						|
    my $startslot = @sortslots[0];
 | 
						|
    $session->set(new SNMP::Varbind([ $comp_node_start_oid, $complex_id, $startslot, 'INTEGER' ]));
 | 
						|
    if ($session->{ErrorStr}) { return (1, $session->{ErrorStr}); }
 | 
						|
 | 
						|
    # set the slot number
 | 
						|
    my $slotnum = $#sortslots + 1;
 | 
						|
    $session->set(new SNMP::Varbind([ $comp_partnode_num_oid, $complex_id, $slotnum, 'INTEGER' ]));
 | 
						|
    if ($session->{ErrorStr}) { return (1, $session->{ErrorStr}); }
 | 
						|
 | 
						|
    # create the partition
 | 
						|
    $session->set(new SNMP::Varbind([ $comp_action_oid, $complex_id, 3, 'INTEGER' ]));
 | 
						|
    if ($session->{ErrorStr}) { return (1, $session->{ErrorStr}); }
 | 
						|
 | 
						|
    # check to make sure the parition has been created
 | 
						|
    my $waiting = 60;    #waiting time before creating parition take affect
 | 
						|
    while ($waiting > 0) {
 | 
						|
        sleep 1;
 | 
						|
        my $oid       = $comp_node_pid_oid . ".$slot";
 | 
						|
        my $node_part = $session->get([$oid]);
 | 
						|
        if ($session->{ErrorStr}) { return (1, $session->{ErrorStr}); }
 | 
						|
        if ($node_part ne '255') {
 | 
						|
            my $slotlist = join(',', @slots);
 | 
						|
            return (0, "Creating flexed node succeeded with slots: $slotlist.");
 | 
						|
        }
 | 
						|
        $waiting--;
 | 
						|
    }
 | 
						|
 | 
						|
    return (1, "Failed to create the flexnode.");
 | 
						|
}
 | 
						|
 | 
						|
# remove a flexnode
 | 
						|
sub rmflexnode {
 | 
						|
    my ($mpa, $node, $slot, @moreslot) = @_;
 | 
						|
 | 
						|
    my @slots = ($slot, @moreslot);
 | 
						|
 | 
						|
    # get the status of all the nodes
 | 
						|
    my $complex_id = "";
 | 
						|
    my $part_id    = "";
 | 
						|
    foreach my $slot (@slots) {
 | 
						|
 | 
						|
        #get the complex of the node
 | 
						|
        my $oid       = $comp_node_cid_oid . ".$slot";
 | 
						|
        my $node_comp = $session->get([$oid]);
 | 
						|
        if ($session->{ErrorStr}) { return (1, $session->{ErrorStr}); }
 | 
						|
        if ($node_comp eq 'NOSUCHINSTANCE') {
 | 
						|
            return (1, "The slot [$slot] is NOT a member of one complex.");
 | 
						|
        }
 | 
						|
 | 
						|
        # all the nodes should be located in one complex
 | 
						|
        if ($complex_id ne "" && $node_comp ne $complex_id) {
 | 
						|
            return (1, "All the slots of this node should be located in one complex.");
 | 
						|
        } else {
 | 
						|
            $complex_id = $node_comp;
 | 
						|
        }
 | 
						|
 | 
						|
        # get the partition of the node
 | 
						|
        $oid = $comp_node_pid_oid . ".$slot";
 | 
						|
        my $node_part = $session->get([$oid]);
 | 
						|
        if ($session->{ErrorStr}) { return (1, $session->{ErrorStr}); }
 | 
						|
        if ($node_part eq '255') {
 | 
						|
            return (1, "The slot [$slot] was NOT assigned to a partition.");
 | 
						|
        }
 | 
						|
 | 
						|
        # all the nodes should belong to one parition
 | 
						|
        if ($part_id ne "" && $node_part ne $part_id) {
 | 
						|
            return (1, "All the slots of this flexnode should belong to one parition.");
 | 
						|
        } else {
 | 
						|
            $part_id = $node_part;
 | 
						|
        }
 | 
						|
 | 
						|
        $oid = $comp_node_state_oid . ".$slot";
 | 
						|
        my $node_state = $session->get([$oid]);
 | 
						|
        if ($session->{ErrorStr}) { return (1, $session->{ErrorStr}); }
 | 
						|
        if ($node_state != 1) {    # 1 is power off
 | 
						|
            return (1, "The slot [$slot] is NOT in power off state.");
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    my $output = $session->set(new SNMP::Varbind([ $comp_part_action_oid . ".$complex_id", $part_id, 1, 'INTEGER' ]));
 | 
						|
    if ($session->{ErrorStr}) { return (1, $session->{ErrorStr}); }
 | 
						|
 | 
						|
    # check to make sure the parition has been deleted
 | 
						|
    my $waiting = 60;    #waiting time before delete parition take affect
 | 
						|
    while ($waiting > 0) {
 | 
						|
        sleep 1;
 | 
						|
        my $oid       = $comp_part_comp_id_oid . ".$complex_id" . ".$part_id";
 | 
						|
        my $part_comp = $session->get([$oid]);
 | 
						|
        if ($session->{ErrorStr}) { return (1, $session->{ErrorStr}); }
 | 
						|
        if ($part_comp eq 'NOSUCHINSTANCE') {
 | 
						|
            return (0, "The flexnode has been removed successfully.");
 | 
						|
        }
 | 
						|
        $waiting--;
 | 
						|
    }
 | 
						|
    return (1, "Failed to remove the flexnode.");
 | 
						|
}
 | 
						|
 | 
						|
sub bladecmd {
 | 
						|
    $mpa = shift;
 | 
						|
    my $node = shift;
 | 
						|
    $currnode = $node;
 | 
						|
    $slot     = shift;
 | 
						|
    if ($slot =~ /-/) {
 | 
						|
        $slot =~ s/-(.*)//;
 | 
						|
        @moreslots = ($slot + 1 .. $1);
 | 
						|
    } else {
 | 
						|
        @moreslots = ();
 | 
						|
    }
 | 
						|
    my $user    = shift;
 | 
						|
    my $pass    = shift;
 | 
						|
    my $command = shift;
 | 
						|
    my @args    = @_;
 | 
						|
    my $error;
 | 
						|
 | 
						|
    if ($slot > 0 and not $slot =~ /:/) {
 | 
						|
        my $tmp = $session->get([ $bladexistsoid . ".$slot" ]);
 | 
						|
        if     ($session->{ErrorStr}) { return (1, $session->{ErrorStr}); }
 | 
						|
        unless ($tmp == 1)            { return (1, "Target bay empty"); }
 | 
						|
    }
 | 
						|
    if ($command eq "rbeacon") {
 | 
						|
        return beacon(@args);
 | 
						|
    } elsif ($command eq "rpower") {
 | 
						|
        return power(@args);
 | 
						|
    } elsif ($command eq "rvitals") {
 | 
						|
        my ($rc, @result) = vitals(@args);
 | 
						|
        if (defined($vitals_info) and defined($vitals_info->{$currnode})) {
 | 
						|
            my $attr = $vitals_info->{$currnode};
 | 
						|
            my $fsp_api = ($::XCATROOT) ? "$::XCATROOT/sbin/fsp-api" : "/opt/xcat/sbin/fsp-api";
 | 
						|
            my $cmd = "$fsp_api -a pblade_query_lcds -T 0 -t 0:$$attr[3]:$$attr[0]:$currnode: 2>&1";
 | 
						|
            my $res = xCAT::Utils->runcmd($cmd, -1);
 | 
						|
            if ($res !~ /error/i) {
 | 
						|
                my @array = split(/\n/, $res);
 | 
						|
                foreach my $a (@array) {
 | 
						|
                    my ($name, $data) = split(/:/, $a);
 | 
						|
                    if ($data =~ /1\|(\w[\w\s]*)/) {
 | 
						|
                        push @result, "Current LCD: $1";
 | 
						|
                    } else {
 | 
						|
                        push @result, "Current LCD: blank";
 | 
						|
                    }
 | 
						|
                }
 | 
						|
            }
 | 
						|
        }
 | 
						|
        return ($rc, @result);
 | 
						|
 | 
						|
        #return vitals(@args);
 | 
						|
    } elsif ($command =~ /r[ms]preset/) {
 | 
						|
        return resetmp(@args);
 | 
						|
    } elsif ($command eq "rspconfig") {
 | 
						|
        return mpaconfig($mpa, $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($node, @args);
 | 
						|
    } elsif ($command eq "rinv") {
 | 
						|
        return inv($node, @args);
 | 
						|
    } elsif ($command eq "reventlog") {
 | 
						|
        return eventlog(@args);
 | 
						|
    } elsif ($command eq "rscan") {
 | 
						|
        return rscan(\@args);
 | 
						|
    } elsif ($command eq "renergy") {
 | 
						|
        return renergy($mpa, $node, $slot, @args);
 | 
						|
    } elsif ($command eq "lsflexnode") {
 | 
						|
        return lsflexnode($mpa, $node, $slot, @moreslots);
 | 
						|
    } elsif ($command eq "mkflexnode") {
 | 
						|
        return mkflexnode($mpa, $node, $slot, @moreslots);
 | 
						|
    } elsif ($command eq "rmflexnode") {
 | 
						|
        return rmflexnode($mpa, $node, $slot, @moreslots);
 | 
						|
    }
 | 
						|
 | 
						|
    return (1, "$command not a supported command by blade method");
 | 
						|
}
 | 
						|
 | 
						|
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
 | 
						|
            %mpahash = ();
 | 
						|
            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}) && $name ne $ent->{mpa}) ? $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->{mpa} ne $_) ? $ent->{id} : "";
 | 
						|
                    push @{ $mpa_hash{$_} }, $ent->{mpa};
 | 
						|
                    push @{ $mpa_hash{$_} }, $id;
 | 
						|
                }
 | 
						|
            }
 | 
						|
        }
 | 
						|
    }
 | 
						|
    return ([ \%dp, \%mpa_hash ]);
 | 
						|
}
 | 
						|
 | 
						|
sub httplogin {
 | 
						|
 | 
						|
    #TODO: Checked for failed login here.
 | 
						|
    my $mpa    = shift;
 | 
						|
    my $user   = shift;
 | 
						|
    my $pass   = shift;
 | 
						|
    my $prefix = "http://";
 | 
						|
    my $url    = "http://$mpa/shared/userlogin.php";
 | 
						|
    $browser = LWP::UserAgent->new;
 | 
						|
    $browser->cookie_jar({});
 | 
						|
    my $response = $browser->post("$prefix$mpa/shared/userlogin.php", { userid => $user, password => $pass, login => "Log In" });
 | 
						|
 | 
						|
    if ($response->{_rc} eq '301') {    #returned when https is enabled
 | 
						|
        $prefix = "https://";
 | 
						|
        $response = $browser->post("$prefix$mpa/shared/userlogin.php", { userid => $user, password => $pass, login => "Log In" });
 | 
						|
    }
 | 
						|
    $response = $browser->post("$prefix$mpa/shared/welcome.php", { timeout => 1, save => "" });
 | 
						|
    unless ($response->{_rc} =~ /^2.*/) {
 | 
						|
        $response = $browser->post("$prefix$mpa/shared/welcomeright.php", { timeout => 1, save => "" });
 | 
						|
    }
 | 
						|
    unless ($response->{_rc} =~ /^2.*/) {
 | 
						|
        return undef;
 | 
						|
    }
 | 
						|
    return $prefix;
 | 
						|
 | 
						|
}
 | 
						|
 | 
						|
sub get_kvm_params {
 | 
						|
    my $mpa      = shift;
 | 
						|
    my $method   = shift;
 | 
						|
    my $response = $browser->get("$method$mpa/private/vnc_only.php");
 | 
						|
    my $html     = $response->{_content};
 | 
						|
    my $destip;
 | 
						|
    my $rbs;
 | 
						|
    my $fwrev;
 | 
						|
    my $port;
 | 
						|
 | 
						|
    foreach (split /\n/, $html) {
 | 
						|
        if (/<param\s+name\s*=\s*"([^"]*)"\s+value\s*=\s*"([^"]*)"/) {
 | 
						|
            if ($1 eq 'ip') {
 | 
						|
                $destip = $2;
 | 
						|
            } elsif ($1 eq 'rbs') {
 | 
						|
                $rbs = $2;
 | 
						|
            } elsif ($1 eq 'cdl') {
 | 
						|
                $fwrev = $2;
 | 
						|
            }
 | 
						|
        }
 | 
						|
    }
 | 
						|
    my $ba;
 | 
						|
    unless (defined $destip and defined $rbs) {    #Try another way
 | 
						|
        $response = $browser->get("$method$mpa/private/remotecontrol.js.php");
 | 
						|
        if ($response->{_rc} == 404) { #In some firmwares, its "shared" instead of private
 | 
						|
            $response = $browser->get("$method$mpa/shared/remotecontrol.js.php");
 | 
						|
        }
 | 
						|
        $html = $response->{_content};
 | 
						|
        foreach (split /\n/, $html) {
 | 
						|
            if (/<param\s+name\s*=\s*"?([^"]*)"?\s+value\s*=\s*"?([^"]*)"?/i) {
 | 
						|
                if ($1 eq 'ip') {
 | 
						|
                    $destip = $2;
 | 
						|
                } elsif ($1 eq 'rbs') {
 | 
						|
                    $rbs = $2;
 | 
						|
 | 
						|
                    #} elsif ($1 eq 'ba') {
 | 
						|
                    #    $ba=$2; #NOTE: This is the username and password.  The client seems to required it for this version of firmware, not exporting for SECURITY
 | 
						|
                } elsif ($1 eq 'cdl') {
 | 
						|
                    $fwrev = $2;
 | 
						|
                } elsif ($1 eq 'port') {
 | 
						|
                    $port = $2;
 | 
						|
                }
 | 
						|
 | 
						|
            }
 | 
						|
        }
 | 
						|
    }
 | 
						|
    return ($destip, $rbs, $fwrev, $port, $ba);
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
 | 
						|
 | 
						|
 | 
						|
sub getbladecons {
 | 
						|
    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 %mpausers;
 | 
						|
    my %checkedmpas = ();
 | 
						|
    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})) {
 | 
						|
            $rsp->{node}->[0]->{mm}->[0] = $ent->{mpa};
 | 
						|
            if (defined($checkedmpas{ $ent->{mpa} }) or not defined $mpatab) {
 | 
						|
                if (defined($mpausers{ $ent->{mpa} })) {
 | 
						|
                    $rsp->{node}->[0]->{username} = [ $mpausers{ $ent->{mpa} } ];
 | 
						|
                } else {
 | 
						|
                    $rsp->{node}->[0]->{username} = [$user];
 | 
						|
                }
 | 
						|
            } else {
 | 
						|
                $checkedmpas{ $ent->{mpa} } = 1;
 | 
						|
                ($tmp) = $mpatab->getNodeAttribs($ent->{mpa}, ['username']);
 | 
						|
                if (defined($tmp) and defined $tmp->{username}) {
 | 
						|
                    $mpausers{ $ent->{mpa} } = $tmp->{username};
 | 
						|
                    $rsp->{node}->[0]->{username} = [ $tmp->{username} ];
 | 
						|
                } else {
 | 
						|
                    $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 ($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;
 | 
						|
    }
 | 
						|
 | 
						|
    #parse the arguments for commands
 | 
						|
    if ($command eq "getmacs") {
 | 
						|
        my (@mpnodes, @nohandle);
 | 
						|
        xCAT::Utils->filter_nodes($request, \@mpnodes, undef, undef, \@nohandle);
 | 
						|
        if (@nohandle) {
 | 
						|
            $callback->({ data => "Cannot figure out plugin for nodes:@nohandle" });
 | 
						|
        }
 | 
						|
        if (@mpnodes) {
 | 
						|
            $noderange = \@mpnodes;
 | 
						|
            my @args = @exargs;
 | 
						|
            while (@args) {
 | 
						|
                my $arg = shift @args;
 | 
						|
                if ($arg =~ /^-V|--verbose|-d|--arp$/) {
 | 
						|
                    next;
 | 
						|
                } elsif ($arg =~ /^-i$/) {
 | 
						|
                    my $int = shift @args;
 | 
						|
                    if (defined($int) && $int =~ /^(eth|en)\d$/) {
 | 
						|
                        next;
 | 
						|
                    }
 | 
						|
                } elsif ($arg eq '') {
 | 
						|
                    next;
 | 
						|
                }
 | 
						|
                $usage_string = ":Error arguments\n";
 | 
						|
                $usage_string .= xCAT::Usage->getUsage($command);
 | 
						|
                $callback->({ data => $usage_string });
 | 
						|
                $request = {};
 | 
						|
                return;
 | 
						|
            }
 | 
						|
        } else {
 | 
						|
            $request = {};
 | 
						|
            return;
 | 
						|
        }
 | 
						|
    } elsif ($command eq "renergy") {
 | 
						|
        if (!@exargs) {
 | 
						|
            $usage_string = "Missing arguments\n";
 | 
						|
            $usage_string .= xCAT::Usage->getUsage($command);
 | 
						|
            $callback->({ data => $usage_string });
 | 
						|
            $request = {};
 | 
						|
            return;
 | 
						|
        }
 | 
						|
        my (@mpnodes, @nohandle);
 | 
						|
        xCAT::Utils->filter_nodes($request, \@mpnodes, undef, undef, \@nohandle);
 | 
						|
        if (@nohandle) {
 | 
						|
            $callback->({ data => "Error: Cannot figure out plugin for nodes:@nohandle" });
 | 
						|
        }
 | 
						|
        if (@mpnodes) {
 | 
						|
            $noderange = \@mpnodes;
 | 
						|
        } else {
 | 
						|
            $request = {};
 | 
						|
            return;
 | 
						|
        }
 | 
						|
    } elsif ($command =~ /^(rspconfig|rvitals)$/) {
 | 
						|
 | 
						|
        # All the nodes with mgt=blade or mgt=fsp will get here
 | 
						|
        # filter out the nodes for blade.pm
 | 
						|
        my (@mpnodes, @nohandle);
 | 
						|
        xCAT::Utils->filter_nodes($request, \@mpnodes, undef, undef, \@nohandle);
 | 
						|
        if (@nohandle) {
 | 
						|
            $callback->({ data => "Cannot figure out plugin for nodes:@nohandle" });
 | 
						|
        }
 | 
						|
        if (@mpnodes) {
 | 
						|
            $noderange = \@mpnodes;
 | 
						|
        } else {
 | 
						|
            $request = {};
 | 
						|
            return;
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    if (!$noderange) {
 | 
						|
        $usage_string = "Missing Noderange\n";
 | 
						|
        $usage_string .= xCAT::Usage->getUsage($command);
 | 
						|
        $callback->({ error => [$usage_string], errorcode => [1] });
 | 
						|
        $request = {};
 | 
						|
        return;
 | 
						|
    }
 | 
						|
 | 
						|
    #get the MMs 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', 'nodetype' ]);
 | 
						|
    if ($request->{command}->[0] eq "getbladecons") { #Can handle it here and now
 | 
						|
        getbladecons($noderange, $callback);
 | 
						|
        return [];
 | 
						|
    }
 | 
						|
 | 
						|
    my %mpatype = ();
 | 
						|
    foreach my $node (@$noderange) {
 | 
						|
        my $ent = $mptabhash->{$node}->[0]; #$mptab->getNodeAttribs($node,['mpa', 'id']);
 | 
						|
        my $mpaent;
 | 
						|
        if (defined($ent->{mpa})) {
 | 
						|
            push @{ $mpa_hash{ $ent->{mpa} }{nodes} }, $node;
 | 
						|
            unless ($mpatype{ $ent->{mpa} }) {
 | 
						|
                my $mpaent = $mptab->getNodeAttribs($ent->{mpa}, ['nodetype']);
 | 
						|
                if ($mpaent && $mpaent->{'nodetype'}) {
 | 
						|
                    $mpatype{ $ent->{mpa} } = $mpaent->{'nodetype'};
 | 
						|
                }
 | 
						|
            }
 | 
						|
        } elsif ($indiscover) {
 | 
						|
            next;
 | 
						|
        } else {
 | 
						|
            $callback->({ data => ["no mpa defined for node $node"] });
 | 
						|
            $request = {};
 | 
						|
            return;
 | 
						|
        }
 | 
						|
        if (defined($ent->{id}) && $node ne $ent->{mpa}) { push @{ $mpa_hash{ $ent->{mpa} }{ids} }, $ent->{id}; }
 | 
						|
        else { push @{ $mpa_hash{ $ent->{mpa} }{ids} }, ""; }
 | 
						|
        if (defined($mpatype{ $ent->{mpa} })) { push @{ $mpa_hash{ $ent->{mpa} }{nodetype} }, $mpatype{ $ent->{mpa} }; }
 | 
						|
        else { push @{ $mpa_hash{ $ent->{mpa} }{nodetype} }, "mm"; }
 | 
						|
    }
 | 
						|
 | 
						|
    # 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;
 | 
						|
        $reqcopy->{_xcatpreprocessed}->[0] = 1;
 | 
						|
        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} }) . "\]\[" . join(',', @{ $mpa_hash{$_}{nodetype} }) . "\]";
 | 
						|
        }
 | 
						|
        $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;
 | 
						|
    unless ($noderange) { return []; }
 | 
						|
    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', 'nodetype' ]);
 | 
						|
 | 
						|
    my %mpatype = ();
 | 
						|
    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;
 | 
						|
            unless ($mpatype{ $ent->{mpa} }) {
 | 
						|
                my $mpaent = $mptab->getNodeAttribs($ent->{mpa}, ['nodetype']);
 | 
						|
                if ($mpaent && $mpaent->{'nodetype'}) {
 | 
						|
                    $mpatype{ $ent->{mpa} } = $mpaent->{'nodetype'};
 | 
						|
                }
 | 
						|
            }
 | 
						|
        } else {
 | 
						|
            $callback->({ data => ["no mpa defined for node $node"] });
 | 
						|
            return @moreinfo;
 | 
						|
        }
 | 
						|
        if (defined($ent->{id}) && $node ne $ent->{mpa}) { push @{ $mpa_hash{ $ent->{mpa} }{ids} }, $ent->{id}; }
 | 
						|
        else { push @{ $mpa_hash{ $ent->{mpa} }{ids} }, ""; }
 | 
						|
        if (defined($mpatype{ $ent->{mpa} })) { push @{ $mpa_hash{ $ent->{mpa} }{nodetype} }, $mpatype{ $ent->{mpa} }; }
 | 
						|
        else { push @{ $mpa_hash{ $ent->{mpa} }{nodetype} }, "mm"; }
 | 
						|
    }
 | 
						|
 | 
						|
    foreach (keys %mpa_hash) {
 | 
						|
        push @moreinfo, "\[$_\]\[" . join(',', @{ $mpa_hash{$_}{nodes} }) . "\]\[" . join(',', @{ $mpa_hash{$_}{ids} }) . "\]\[" . join(',', @{ $mpa_hash{$_}{nodetype} }) . "\]";
 | 
						|
    }
 | 
						|
 | 
						|
    return \@moreinfo;
 | 
						|
}
 | 
						|
 | 
						|
sub verbose_message {
 | 
						|
    my $data = shift;
 | 
						|
    if (!defined($CALLBACK) or !defined($verbose_cmd)) {
 | 
						|
        return;
 | 
						|
    }
 | 
						|
    my ($sec, $min, $hour, $mday, $mon, $yr, $wday, $yday, $dst) = localtime(time);
 | 
						|
    my $time = sprintf "%04d%02d%02d.%02d:%02d:%02d", $yr + 1900, $mon + 1, $mday, $hour, $min, $sec;
 | 
						|
    $data = "$time ($$) $verbose_cmd:" . $data;
 | 
						|
    my %rsp;
 | 
						|
    $rsp{data} = [$data];
 | 
						|
    xCAT::MsgUtils->message("I", \%rsp, $CALLBACK);
 | 
						|
}
 | 
						|
 | 
						|
sub process_request {
 | 
						|
    $SIG{INT} = $SIG{TERM} = sub {
 | 
						|
        foreach (keys %mm_comm_pids) {
 | 
						|
            kill 2, $_;
 | 
						|
        }
 | 
						|
        exit 0;
 | 
						|
    };
 | 
						|
    my $request  = shift;
 | 
						|
    my $callback = shift;
 | 
						|
 | 
						|
    # Since switch.pm and lsslp.pm both create a MacMap object (which requires SNMP), SNMP is still required at xcatd start up.
 | 
						|
    # So do not bother trying to do this require in an eval.
 | 
						|
    #eval {
 | 
						|
    require SNMP;
 | 
						|
 | 
						|
    #};
 | 
						|
    #if ($@) { $callback->{error=>['Missing SNMP perl support'],errorcode=>[1]};  return; }
 | 
						|
 | 
						|
    my $doreq     = shift;
 | 
						|
    my $level     = shift;
 | 
						|
    my $noderange = $request->{node};
 | 
						|
    my $command   = $request->{command}->[0];
 | 
						|
    my @exargs;
 | 
						|
    unless ($command) {
 | 
						|
        return;    #Empty request
 | 
						|
    }
 | 
						|
    if (ref($request->{arg})) {
 | 
						|
        @exargs = @{ $request->{arg} };
 | 
						|
    } else {
 | 
						|
        @exargs = ($request->{arg});
 | 
						|
    }
 | 
						|
    $CALLBACK = $callback;
 | 
						|
    if (grep /-V|--verbose/, @exargs) {
 | 
						|
        $verbose_cmd = $command;
 | 
						|
    }
 | 
						|
 | 
						|
    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|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->({ error => ["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;
 | 
						|
    my @entries    = xCAT::TableUtils->get_site_attribute("blademaxp");
 | 
						|
    my $site_entry = $entries[0];
 | 
						|
    if (defined($site_entry)) {
 | 
						|
        $blademaxp = $site_entry;
 | 
						|
    }
 | 
						|
 | 
						|
    #if ($sitetab) {
 | 
						|
    #  ($tmp)=$sitetab->getAttribs({'key'=>'blademaxp'},'value');
 | 
						|
    #  if (defined($tmp)) { $blademaxp=$tmp->{value}; }
 | 
						|
    #}
 | 
						|
    if ($request->{environment}->[0]->{XCAT_BLADEUSER}) {
 | 
						|
        $bladeuser = $request->{environment}->[0]->{XCAT_BLADEUSER}->[0];
 | 
						|
        $bladepass = $request->{environment}->[0]->{XCAT_BLADEPASS}->[0];
 | 
						|
    } else {
 | 
						|
        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,uuid'];
 | 
						|
        $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;
 | 
						|
            }
 | 
						|
        }
 | 
						|
 | 
						|
        #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();
 | 
						|
            $indiscover      = 1;
 | 
						|
            my $reqs = preprocess_request(\%invreq, \&fillresps);
 | 
						|
            my @reql;
 | 
						|
            if ($reqs) { @reql = @{$reqs}; }
 | 
						|
            foreach (@reql) {
 | 
						|
                %invreq = %$_;
 | 
						|
                process_request(\%invreq, \&fillresps);
 | 
						|
            }
 | 
						|
            $indiscover = 0;
 | 
						|
        }
 | 
						|
        my $found = 0;
 | 
						|
        if ($mac and $macmap{$mac}) {
 | 
						|
            $found = 1;
 | 
						|
        } else {
 | 
						|
            foreach (@{ $request->{mac} }) {
 | 
						|
                /.*\|.*\|([\dABCDEFabcdef:]+)(\||$)/;
 | 
						|
                if ($1 and $macmap{$1}) {
 | 
						|
                    $mac   = $1;    #the mac of consequence is identified here
 | 
						|
                    $found = 1;
 | 
						|
                    last;
 | 
						|
                }
 | 
						|
            }
 | 
						|
        }
 | 
						|
        my $node;
 | 
						|
        if ($found) {
 | 
						|
            $node = $macmap{$mac};
 | 
						|
        } else {
 | 
						|
            my $ruid;
 | 
						|
            foreach $ruid (@{ $request->{uuid} }) {
 | 
						|
                my $uuid = uc($ruid);
 | 
						|
                if ($uuid and $uuidmap{$uuid}) {
 | 
						|
                    $node = $uuidmap{$uuid};
 | 
						|
                    last;
 | 
						|
                }
 | 
						|
                $uuid =~ s/(..)(..)(..)(..)-(..)(..)-(..)(..)/$4$3$2$1-$6$5-$8$7/;
 | 
						|
                if ($uuid and $uuidmap{$uuid}) {
 | 
						|
                    $node = $uuidmap{$uuid};
 | 
						|
                    last;
 | 
						|
                }
 | 
						|
            }
 | 
						|
        }
 | 
						|
        unless ($node) {
 | 
						|
            xCAT::MsgUtils->message("S", "xcat.discovery.blade: ($request->{_xcat_clientmac}->[0]) Warning: Could not find any nodes using blade-based discovery");
 | 
						|
            return 1;    #failure
 | 
						|
        }
 | 
						|
        if ($request->{mtm} and $request->{mtm} =~ /^(\w{4})/) {
 | 
						|
            my $group = xCAT::data::ibmhwtypes::parse_group($request->{mtm});
 | 
						|
            if (defined($group)) {
 | 
						|
                xCAT::TableUtils->updatenodegroups($node, $group . ",all");
 | 
						|
            }
 | 
						|
        }
 | 
						|
        if ($mac) {
 | 
						|
            my $mactab = xCAT::Table->new('mac', -create => 1);
 | 
						|
            $mactab->setNodeAttribs($macmap{$mac}, { mac => $mac });
 | 
						|
            $mactab->close();
 | 
						|
            undef $mactab;
 | 
						|
        }
 | 
						|
 | 
						|
        xCAT::MsgUtils->message("S", "xcat.discovery.blade: ($request->{_xcat_clientmac}->[0]) Found node: $node");
 | 
						|
 | 
						|
        #my %request = (
 | 
						|
        #  command => ['makedhcp'],
 | 
						|
        #  node => [$macmap{$mac}]
 | 
						|
        #  );
 | 
						|
        #$doreq->(\%request);
 | 
						|
        $request->{command} = ['discovered'];
 | 
						|
        my $req = {%$request};
 | 
						|
        $req->{noderange}       = [$node];
 | 
						|
        $req->{discoverymethod} = ['blade'];
 | 
						|
        $doreq->($req);
 | 
						|
        %{$req} = ();    #Clear request. it is done
 | 
						|
        return 0;
 | 
						|
    }
 | 
						|
 | 
						|
 | 
						|
    my $children = 0;
 | 
						|
    $SIG{CHLD} = sub { my $cpid; while (($cpid = waitpid(-1, WNOHANG)) > 0) { if ($mm_comm_pids{$cpid}) { delete $mm_comm_pids{$cpid}; $children--; } } };
 | 
						|
    my $inputs = new IO::Select;
 | 
						|
    foreach my $info (@$moreinfo) {
 | 
						|
        $info =~ /^\[(.*)\]\[(.*)\]\[(.*)\]\[(.*)\]/;
 | 
						|
        ## TRACE_LINE print "Target info: node [$2], mpa [$1], slotid [$3], mptype [$4].\n";
 | 
						|
        my $mpa     = $1;
 | 
						|
        my @nodes   = split(',', $2);
 | 
						|
        my @ids     = split(',', $3);
 | 
						|
        my @mptypes = split(',', $4);
 | 
						|
        my $user    = $bladeuser;
 | 
						|
        my $pass    = $bladepass;
 | 
						|
        my $ent;
 | 
						|
 | 
						|
        if (defined($mpatab)) {
 | 
						|
            my @user_array = $mpatab->getNodeAttribs($mpa, qw(username password));
 | 
						|
            foreach my $entry (@user_array) {
 | 
						|
                if ($entry->{username}) {
 | 
						|
                    if ($entry->{username} =~ /^USERID$/) {
 | 
						|
                        $ent = $entry;
 | 
						|
                        last;
 | 
						|
                    }
 | 
						|
                }
 | 
						|
            }
 | 
						|
            if (defined($ent->{password})) { $pass = $ent->{password}; }
 | 
						|
            if (defined($ent->{username})) { $user = $ent->{username}; }
 | 
						|
        }
 | 
						|
        $mpahash{$mpa}->{username} = $user;
 | 
						|
        $mpahash{$mpa}->{password} = $pass;
 | 
						|
        my $nodehmtab = xCAT::Table->new('nodehm');
 | 
						|
        my $hmdata = $nodehmtab->getNodesAttribs(\@nodes, [ 'node', 'mgt' ]);
 | 
						|
        for (my $i = 0 ; $i < @nodes ; $i++) {
 | 
						|
            my $node   = $nodes[$i];
 | 
						|
            my $nodeid = $ids[$i];
 | 
						|
            $mpahash{$mpa}->{nodes}->{$node} = $nodeid;
 | 
						|
            my $mptype = $mptypes[$i];
 | 
						|
            $mpahash{$mpa}->{nodetype}->{$node} = $mptype;
 | 
						|
            my $tmp1 = $hmdata->{$node}->[0];
 | 
						|
            if ($tmp1) {
 | 
						|
                if ($tmp1->{mgt} =~ /ipmi/) {
 | 
						|
                    $mpahash{$mpa}->{ipminodes}->{$node} = $nodeid;
 | 
						|
 | 
						|
                }
 | 
						|
            }
 | 
						|
 | 
						|
        }
 | 
						|
    }
 | 
						|
    my @mpas     = (keys %mpahash);
 | 
						|
    my $mpatypes = $mptab->getNodesAttribs(\@mpas, ['nodetype']);
 | 
						|
    my $sub_fds  = new IO::Select;
 | 
						|
    foreach $mpa (sort (keys %mpahash)) {
 | 
						|
        if (defined($mpatypes->{$mpa}->[0]->{'nodetype'})) {
 | 
						|
            $mpahash{$mpa}->{mpatype} = $mpatypes->{$mpa}->[0]->{'nodetype'};
 | 
						|
        }
 | 
						|
        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 {
 | 
						|
                dompa($pfd, $mpa, \%mpahash, $command, -args => \@exargs);
 | 
						|
                exit(0);
 | 
						|
            };
 | 
						|
            if ($@) { die "$@"; }
 | 
						|
            die "blade plugin encountered a general error while communication with $mpa";
 | 
						|
        }
 | 
						|
        $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)) { }
 | 
						|
}
 | 
						|
 | 
						|
sub clicmds {
 | 
						|
 | 
						|
    my $mpa      = shift;
 | 
						|
    my $user     = shift;
 | 
						|
    my $pass     = shift;
 | 
						|
    my $node     = shift;
 | 
						|
    my $nodeid   = shift;
 | 
						|
    my %args     = @_;
 | 
						|
    my $ipmiflag = 0;
 | 
						|
    $ipmiflag = 1 if ($node =~ s/--ipmi//);
 | 
						|
    my $value;
 | 
						|
    my @unhandled;
 | 
						|
    my %handled = ();
 | 
						|
    my $result;
 | 
						|
    my @tcmds = qw(snmpcfg sshcfg network swnet pd1 pd2 textid network_reset rscanfsp initnetwork solcfg userpassword USERID updateBMC);
 | 
						|
    verbose_message("start deal with $mptype CLI options:@{$args{cmds}}.");
 | 
						|
 | 
						|
    # most of these commands should be able to be done
 | 
						|
    # through SNMP, but they produce various errors.
 | 
						|
    foreach my $cmd (@{ $args{cmds} }) {
 | 
						|
        if ($cmd =~ /^swnet|pd1|pd2|sshcfg|rscanfsp|USERID|userpassword|updateBMC|=/) {
 | 
						|
            if (($cmd =~ /^textid/) and ($nodeid > 0)) {
 | 
						|
                push @unhandled, $cmd;
 | 
						|
                next;
 | 
						|
            }
 | 
						|
            my ($command, $value) = split /=/, $cmd, 2;
 | 
						|
 | 
						|
            #$command =~ /^swnet/) allows for swnet1, swnet2, etc.
 | 
						|
            if (grep(/^$command$/, @tcmds) || $command =~ /^swnet/) {
 | 
						|
                $handled{$command} = $value;
 | 
						|
                next;
 | 
						|
            }
 | 
						|
        }
 | 
						|
        if ($cmd =~ /-V|--verbose/) {
 | 
						|
            next;
 | 
						|
        }
 | 
						|
        push @unhandled, $cmd;
 | 
						|
    }
 | 
						|
 | 
						|
    # the option 'updateBMC' and 'USERID' can only work together when specified value for 'updateBMC', otherwise we shall only run 'rspconfig cmm updateBMC' to update BMC passwords associate with this cmm.
 | 
						|
    if (defined($handled{updateBMC}) and !($handled{USERID})) {
 | 
						|
        push @cfgtext, "'updateBMC' mush work with 'USERID'";
 | 
						|
        return ([ 1, \@unhandled, "" ]);
 | 
						|
    }
 | 
						|
    if (exists($handled{updateBMC}) and !defined($handled{updateBMC}) and $handled{USERID}) {
 | 
						|
        push @cfgtext, "No value specified for 'updateBMC'";
 | 
						|
        return ([ 1, \@unhandled, "" ]);
 | 
						|
    }
 | 
						|
    unless (%handled) {
 | 
						|
        verbose_message("no option needed to be handled with $mptype CLI.");
 | 
						|
        return ([ 0, \@unhandled ]);
 | 
						|
    }
 | 
						|
    my $curruser   = $user;
 | 
						|
    my $currpass   = $pass;
 | 
						|
    my $nokeycheck = 0;       #default to checking ssh key
 | 
						|
    if ($args{defaultcfg}) {
 | 
						|
        $curruser   = "USERID";
 | 
						|
        $currpass   = "PASSW0RD";
 | 
						|
        $nokeycheck = 1;
 | 
						|
    } else {
 | 
						|
        if ($args{curruser}) { $curruser = $args{curruser}; $nokeycheck = 1; }
 | 
						|
        if ($args{currpass}) { $currpass = $args{currpass}; $nokeycheck = 1; }
 | 
						|
    }
 | 
						|
 | 
						|
    if ($args{nokeycheck}) {
 | 
						|
        $nokeycheck = 1;
 | 
						|
    }
 | 
						|
    my $promote_pass = $pass;    #used for genesis state processing
 | 
						|
    my $curraddr     = $mpa;
 | 
						|
    if ($args{curraddr}) {
 | 
						|
        $curraddr = $args{curraddr};
 | 
						|
    } elsif (defined($handled{'initnetwork'}) or defined($handled{'USERID'})) {
 | 
						|
 | 
						|
        # get the IP of mpa from the hosts.otherinterfaces
 | 
						|
        my $hoststab = xCAT::Table->new('hosts');
 | 
						|
        if ($hoststab) {
 | 
						|
            my $hostdata = $hoststab->getNodeAttribs($node, ['otherinterfaces']);
 | 
						|
            if (!$hostdata->{'otherinterfaces'}) {
 | 
						|
                if (!defined($handled{'USERID'})) {
 | 
						|
                    push @cfgtext, "Cannot find the temporary IP from the hosts.otherinterfaces";
 | 
						|
                    return ([ 1, \@unhandled, "" ]);
 | 
						|
                }
 | 
						|
            } else {
 | 
						|
                $curraddr = $hostdata->{'otherinterfaces'};
 | 
						|
            }
 | 
						|
        }
 | 
						|
    }
 | 
						|
    require xCAT::SSHInteract;
 | 
						|
    my $t;
 | 
						|
    verbose_message("start SSH mpa:$mpa session for node:$node.");
 | 
						|
    eval {
 | 
						|
        $t = new xCAT::SSHInteract(
 | 
						|
            -username                => $curruser,
 | 
						|
            -password                => $currpass,
 | 
						|
            -host                    => $curraddr,
 | 
						|
            -nokeycheck              => $nokeycheck,
 | 
						|
            -output_record_separator => "\r",
 | 
						|
            Timeout                  => 15,
 | 
						|
            Errmode                  => 'return',
 | 
						|
            Prompt                   => '/system> $/'
 | 
						|
        );
 | 
						|
    };
 | 
						|
    my $errmsg = $@;
 | 
						|
    if ($errmsg) {
 | 
						|
        if ($errmsg =~ /Known_hosts issue/) {
 | 
						|
            $errmsg = "The entry for $mpa in known_hosts table is out of date, pls run 'makeknownhosts $mpa -r' to delete it from known_hosts table.";
 | 
						|
            push @cfgtext, $errmsg;
 | 
						|
            return ([ 1, \@unhandled, $errmsg ]);
 | 
						|
        }
 | 
						|
        if ($errmsg =~ /Login Failed/) {
 | 
						|
            $errmsg = "Failed to login to $mpa";
 | 
						|
            if ($curraddr ne $mpa) { $errmsg .= " (currently at $curraddr)" }
 | 
						|
            push @cfgtext, $errmsg;
 | 
						|
            return ([ 1, \@unhandled, $errmsg ]);
 | 
						|
        } else {
 | 
						|
            push @cfgtext, $errmsg;
 | 
						|
            return ([ 1, \@unhandled, $errmsg ]);
 | 
						|
 | 
						|
            #die $@;
 | 
						|
        }
 | 
						|
    }
 | 
						|
    my $Rc = 1;
 | 
						|
    if ($t and not $t->atprompt) { #we sshed in, but we may be forced to deal with initial password set
 | 
						|
        my $output = $t->get();
 | 
						|
        if ($output =~ /Enter current password/) {
 | 
						|
            if (defined($handled{USERID})) {
 | 
						|
                $promote_pass = $handled{USERID};
 | 
						|
            }
 | 
						|
            verbose_message("deal with genesis state for mpa:$mpa.");
 | 
						|
            $t->print($currpass);
 | 
						|
            $t->waitfor(-match => "/password:/i");
 | 
						|
            $t->print($promote_pass);
 | 
						|
            $t->waitfor(-match => "/password:/i");
 | 
						|
            $t->print($promote_pass);
 | 
						|
            my $result = $t->getline();
 | 
						|
            chomp($result);
 | 
						|
            $result =~ s/\s*//;
 | 
						|
 | 
						|
            while ($result eq "") {
 | 
						|
                $result = $t->getline();
 | 
						|
                $result =~ s/\s*//;
 | 
						|
            }
 | 
						|
            if ($result =~ /not compliant/) {
 | 
						|
                push @cfgtext, "The current account password has expired, please modify it first";
 | 
						|
                return ([ 1, \@unhandled, "Management module refuses requested password as insufficiently secure, try another password" ]);
 | 
						|
            }
 | 
						|
            $t->waitfor(match => "/system> /");
 | 
						|
            $t->cmd("accseccfg -rc 0 -pe 0 -pi 0 -ct 0 -lp 0 -lf 0 -T system:mm[1]");
 | 
						|
            $t->waitfor(match => "/system> /");
 | 
						|
            $t->cmd("accseccfg -rc 0 -pe 0 -pi 0 -ct 0 -lp 0 -lf 0 -T system:mm[2]");
 | 
						|
        }
 | 
						|
        $t->waitfor(match => "/system> /");
 | 
						|
    } elsif (not $t) { #ssh failed.. fallback to a telnet attempt for older AMMs with telnet disabled by default
 | 
						|
        verbose_message("start telnet mpa:$curraddr session for node:$node.");
 | 
						|
        require Net::Telnet;
 | 
						|
        $t = new Net::Telnet(
 | 
						|
            Timeout => 15,
 | 
						|
            Errmode => 'return',
 | 
						|
            Prompt  => '/system> $/'
 | 
						|
        );
 | 
						|
        $Rc = $t->open($curraddr);
 | 
						|
        if ($Rc) {
 | 
						|
            $Rc = $t->login($user, $pass);
 | 
						|
        }
 | 
						|
    }
 | 
						|
    if (!$Rc) {
 | 
						|
        push @cfgtext, $t->errmsg;
 | 
						|
        return ([ 1, \@unhandled, $t->errmsg ]);
 | 
						|
    }
 | 
						|
    $Rc = 0;
 | 
						|
    my $mm;
 | 
						|
    my @data = $t->cmd("list -l 2");
 | 
						|
    foreach (@data) {
 | 
						|
        if (/(mm\[\d+\])\s+primary/) {
 | 
						|
            $mm = $1;
 | 
						|
            last;
 | 
						|
        }
 | 
						|
    }
 | 
						|
    if (!defined($mm)) {
 | 
						|
        push @cfgtext, "Cannot find primary MM";
 | 
						|
        return ([ 1, \@unhandled ]);
 | 
						|
    }
 | 
						|
    @data = ();
 | 
						|
 | 
						|
    my $reset;
 | 
						|
    my $cmm_modified = 0;
 | 
						|
    my $bmc_modified = 0;
 | 
						|
    foreach (keys %handled) {
 | 
						|
        if (/^snmpcfg/) { $result = snmpcfg($t, $handled{$_}, $user, $pass, $mm); }
 | 
						|
        elsif (/^sshcfg$/) { $result = sshcfg($t, $handled{$_}, $user, $mm); }
 | 
						|
        elsif (/^network$/) { $node .= "--ipmi" if ($ipmiflag); $result = network($t, $handled{$_}, $mpa, $mm, $node, $nodeid); $node =~ s/--ipmi//; }
 | 
						|
        elsif (/^initnetwork$/) { $result = network($t, $handled{$_}, $mpa, $mm, $node, $nodeid, 1); $reset = 1; }
 | 
						|
        elsif (/^swnet/) { $result = swnet($t, $_, $handled{$_}); }
 | 
						|
        elsif (/^pd1|pd2$/) { $result = pd($t, $_, $handled{$_}); }
 | 
						|
        elsif (/^textid$/) { $result = mmtextid($t, $mpa, $handled{$_}, $mm); }
 | 
						|
        elsif (/^rscanfsp$/) { $result = rscanfsp($t, $mpa, $handled{$_}, $mm); }
 | 
						|
        elsif (/^solcfg$/) { $result = solcfg($t, $handled{$_}, $mm); }
 | 
						|
        elsif (/^network_reset$/) { $result = network($t, $handled{$_}, $mpa, $mm, $node, $nodeid, 1); $reset = 1; }
 | 
						|
        elsif (/^(USERID)$/ and !$cmm_modified) { $result = passwd($t, $mpa, $1, "=" . $handled{$_}, $promote_pass, $mm); $cmm_modified = 1; }
 | 
						|
        elsif (/^userpassword$/) { $result = passwd($t, $mpa, $1, $handled{$_}, $promote_pass, $mm); }
 | 
						|
 | 
						|
        if ((/^updateBMC$/ or ($cmm_modified)) and !($bmc_modified)) {
 | 
						|
            unless (defined($handled{updateBMC}) and $handled{updateBMC} =~ /(0|n|no)/i) {
 | 
						|
                if (defined($handled{updateBMC}) and !$cmm_modified) {
 | 
						|
                    $result = passwd($t, $mpa, "USERID", "=" . $handled{USERID}, $promote_pass, $mm);
 | 
						|
                    $cmm_modified = 1;
 | 
						|
                }
 | 
						|
                verbose_message("start update password for all BMCs.");
 | 
						|
                my $start = Time::HiRes::gettimeofday();
 | 
						|
                updateBMC($mpa, $user, $handled{USERID});
 | 
						|
                verbose_message("Finish update password for all BMCs.");
 | 
						|
                my $slp = Time::HiRes::gettimeofday() - $start;
 | 
						|
                my $msg = sprintf("The main process time slp: %.3f sec", $slp);
 | 
						|
                verbose_message($msg);
 | 
						|
            }
 | 
						|
            $bmc_modified = 1;
 | 
						|
        }
 | 
						|
        if (!defined($result)) { next; }
 | 
						|
        push @data, "$_: @$result";
 | 
						|
        if (/^initnetwork$/) {
 | 
						|
            if (!@$result[0]) {
 | 
						|
                my $hoststab = xCAT::Table->new('hosts');
 | 
						|
                if ($hoststab) {
 | 
						|
                    $hoststab->setNodeAttribs($mpa, { otherinterfaces => '' });
 | 
						|
                }
 | 
						|
            }
 | 
						|
        }
 | 
						|
        $Rc |= shift(@$result);
 | 
						|
        push @cfgtext, @$result;
 | 
						|
    }
 | 
						|
 | 
						|
    # dealing with SNMP v3 disable in genesis state#
 | 
						|
    if ($promote_pass ne $pass) {
 | 
						|
        snmpcfg($t, 'disable', $user, $promote_pass, $mm);
 | 
						|
    }
 | 
						|
    if ($reset) {
 | 
						|
        $t->cmd("reset -T system:$mm");
 | 
						|
        push @data, "The management module has been reset to load the configuration";
 | 
						|
    }
 | 
						|
    $t->close;
 | 
						|
    verbose_message("finished SSH mpa:$curraddr session for node:$node.");
 | 
						|
    return ([ $Rc, \@unhandled, \@data ]);
 | 
						|
}
 | 
						|
 | 
						|
# Enable/Disable the sol against the mm and blades
 | 
						|
# The target node is mm, but all the blade servers belongs to this mm will be
 | 
						|
# handled implicated
 | 
						|
sub solcfg {
 | 
						|
    my $t     = shift;
 | 
						|
    my $value = shift;
 | 
						|
    my $mm    = shift;
 | 
						|
 | 
						|
    if ($value !~ /^enable|disable$/i) {
 | 
						|
        return ([ 1, "Invalid argument '$value' (enable|disable)" ]);
 | 
						|
    }
 | 
						|
 | 
						|
    my $setval;
 | 
						|
    if ($value eq "enable") {
 | 
						|
        $setval = "enabled";
 | 
						|
    } else {
 | 
						|
        $setval = "disabled";
 | 
						|
    }
 | 
						|
 | 
						|
    my @output;
 | 
						|
    my $rc   = 0;
 | 
						|
    my @data = $t->cmd("sol -status $setval -T system:$mm");
 | 
						|
    if (grep (/OK/, @data)) {
 | 
						|
        push @output, "$value: succeeded on $mm";
 | 
						|
    } else {
 | 
						|
        push @output, "$value: failed on $mm";
 | 
						|
        $rc = 1;
 | 
						|
    }
 | 
						|
 | 
						|
    # Get the component list
 | 
						|
    my @data = $t->cmd("list -l 2");
 | 
						|
    foreach (@data) {
 | 
						|
        if (/^\s*(blade\[\d+\])\s+/) {
 | 
						|
            my @ret = $t->cmd("sol -status $setval -T $1");
 | 
						|
            if (grep (/OK/, @ret)) {
 | 
						|
                push @output, "$value: succeeded on $1";
 | 
						|
            } else {
 | 
						|
                push @output, "$value: failed on $1";
 | 
						|
                $rc = 1;
 | 
						|
            }
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    return ([ $rc, @output ]);
 | 
						|
}
 | 
						|
 | 
						|
sub load_x222_info {
 | 
						|
    my $t       = shift;
 | 
						|
    my $id_flag = undef;
 | 
						|
    my $id_start;
 | 
						|
    my $id_sub;
 | 
						|
    my @id_array = ();
 | 
						|
    my @data     = $t->cmd("list -l 3");
 | 
						|
    ## find out the x222 nodes
 | 
						|
    foreach (@data) {
 | 
						|
        if (/^(\s*)(bladegroup\[\d+\])\s*/) {
 | 
						|
            $id_flag  = $1;
 | 
						|
            $id_start = $2;
 | 
						|
            $id_sub   = undef;
 | 
						|
        } elsif (/^(\s*)(blade\[\d+\])\s*/) {
 | 
						|
            if (defined($id_flag) and $id_flag ne $1) {
 | 
						|
                $id_sub = $id_start . ":$2";
 | 
						|
            } else {
 | 
						|
                $id_flag = undef;
 | 
						|
                $id_sub  = undef;
 | 
						|
                next;
 | 
						|
            }
 | 
						|
        } else {
 | 
						|
            next;
 | 
						|
        }
 | 
						|
        if (defined($id_sub)) {
 | 
						|
            push @id_array, $id_sub;
 | 
						|
        }
 | 
						|
    }
 | 
						|
    foreach (@id_array) {
 | 
						|
        my $node = $_;
 | 
						|
        @data = $t->cmd("info -T system:$node");
 | 
						|
        my $node_name = $node;
 | 
						|
        foreach (@data) {
 | 
						|
            if (/^Name:\s/) {
 | 
						|
                if (/^Name:\s*(.*)\s\(\s*(.*)\s\).*$/) {
 | 
						|
                    if (grep (/ /, $2)) {
 | 
						|
                        $node_name = $1;
 | 
						|
                    } else {
 | 
						|
                        $node_name = $2;
 | 
						|
                    }
 | 
						|
                } elsif (/^Name:\s*(.*)\s*$/) {
 | 
						|
                    $node_name = $1;
 | 
						|
                }
 | 
						|
                $node_name =~ s/ /_/;
 | 
						|
                $node_name =~ tr/A-Z/a-z/;
 | 
						|
                $x222_info{$node}{node_name} = $node_name;
 | 
						|
            } elsif (/^Mach type\/model: (\w+)/) {
 | 
						|
                $x222_info{$node}{mtm} = $1;
 | 
						|
            } elsif (/^Mach serial number: (\w+)/) {
 | 
						|
                $x222_info{$node}{serial} = $1;
 | 
						|
            } elsif (/(Product Name: IBM Flex System p)|(Mach type\/model:.*PPC)|(Mach type\/model: pITE)|(Mach type\/model: IBM Flex System p)|(Firebird)/) {
 | 
						|
                $x222_info{$node}{type} = "ppcblade";
 | 
						|
            } elsif (/(Product Name: IBM Flex System x)|(Device Description: HX)/) {
 | 
						|
                $x222_info{$node}{type} = "xblade";
 | 
						|
            } elsif (/^MAC Address (\d+):\s*(\w+:\w+:\w+:\w+:\w+:\w+)/) {
 | 
						|
                my $macid = "mac$1";
 | 
						|
                my $mac   = $2;
 | 
						|
                $mac =~ tr/A-Z/a-z/;
 | 
						|
                $x222_info{$node}{$macid} = $mac;
 | 
						|
            } elsif (/^Slots: (\d+:\d+|\d+)/) {
 | 
						|
                $x222_info{$node}{slotid} = $1;
 | 
						|
            }
 | 
						|
        }
 | 
						|
        @data = $t->cmd("ifconfig -T system:$node");
 | 
						|
        my $side = undef;
 | 
						|
        foreach (@data) {
 | 
						|
            if (/eth(\d+)/) {
 | 
						|
                $side = $1;
 | 
						|
            }
 | 
						|
            if (defined($side) && /-i (\d+.\d+.\d+.\d+)/) {
 | 
						|
                $x222_info{$node}{$side}{side} = $side;
 | 
						|
                $x222_info{$node}{$side}{ip}   = $1;
 | 
						|
            }
 | 
						|
        }
 | 
						|
        $has_x222 = '1';
 | 
						|
    }
 | 
						|
    return;
 | 
						|
}
 | 
						|
 | 
						|
# Scan the fsp for the NGP ppc nodes
 | 
						|
sub rscanfsp {
 | 
						|
    my $t     = shift;
 | 
						|
    my $mpa   = shift;
 | 
						|
    my $value = shift;
 | 
						|
    my $mm    = shift;
 | 
						|
 | 
						|
    my @blade;
 | 
						|
 | 
						|
    # Get the component list
 | 
						|
    my @data = $t->cmd("list -l 2");
 | 
						|
    if (grep /bladegroup/, @data) {
 | 
						|
        &load_x222_info($t);
 | 
						|
    }
 | 
						|
    foreach (@data) {
 | 
						|
        if (/^\s*(blade\[\d+\])\s+/) {
 | 
						|
            push @blade, $1;
 | 
						|
        }
 | 
						|
        if (/(mm\[\d+\])\s+primary/) {
 | 
						|
 | 
						|
            # get the type of mm
 | 
						|
            @data = $t->cmd("info -T system:$1");
 | 
						|
            if (grep /(Mach type\/model: Chassis Management Module)|(Mach type\/model: CMM)|(Product Name:.*Chassis Management Module)/, @data) {
 | 
						|
                $telnetrscan{'mm'}{'type'} = "cmm";
 | 
						|
            }
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    # Get the interface side of fsp
 | 
						|
    # mm[1] -> eth1; mm[2] -> eth0;
 | 
						|
    my $ifside;
 | 
						|
    if ($mm =~ /\[(\d)\]/) {
 | 
						|
        if ($1 eq "1") {
 | 
						|
            $ifside = "1";
 | 
						|
        } elsif ($1 eq "2") {
 | 
						|
            $ifside = "0";
 | 
						|
        } else {
 | 
						|
            $ifside = $1;
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    # for fsp
 | 
						|
    foreach (@blade) {
 | 
						|
        /blade\[(\d+)\]/;
 | 
						|
        my $id = $1;
 | 
						|
 | 
						|
        # get the hardware type, only get the fsp for PPC blade
 | 
						|
        @data = $t->cmd("info -T system:$_");
 | 
						|
        if (!grep /(Product Name: IBM Flex System p)|(Mach type\/model:.*PPC)|(Mach type\/model: pITE)|(Mach type\/model: IBM Flex System p)|(Firebird)/, @data) {
 | 
						|
            next;
 | 
						|
        }
 | 
						|
        @data = $t->cmd("ifconfig -T system:$_");
 | 
						|
        my $side;
 | 
						|
        foreach (@data) {
 | 
						|
            if (/eth(\d)/) {
 | 
						|
                if ($1 eq $ifside) {
 | 
						|
                    $side                            = $1;
 | 
						|
                    $telnetrscan{$id}{$side}{'side'} = $side;
 | 
						|
                    $telnetrscan{$id}{$side}{'type'} = "fsp";
 | 
						|
                } else {
 | 
						|
                    undef $side;
 | 
						|
                }
 | 
						|
            }
 | 
						|
            if (/-i (\d+\.\d+\.\d+\.\d+)/ && defined($side)) {
 | 
						|
                $telnetrscan{$id}{$side}{'ip'} = $1;
 | 
						|
                ## TRACE_LINE print "rscanfsp found: blade[$id] - ip [$telnetrscan{$id}{$side}{'ip'}], type [$telnetrscan{$id}{$side}{'type'}], side [$telnetrscan{$id}{$side}{'side'}].\n";
 | 
						|
            }
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    # for bmc
 | 
						|
    foreach (@blade) {
 | 
						|
        /blade\[(\d+)\]/;
 | 
						|
        my $id = $1;
 | 
						|
 | 
						|
        # get the hardware type, only get the fsp for PPC blade
 | 
						|
        @data = $t->cmd("info -T system:$_");
 | 
						|
        if ((!grep /(Product Name: IBM Flex System x)/, @data) and (!grep /Device Description: HX/, @data)) {
 | 
						|
            next;
 | 
						|
        }
 | 
						|
        @data = $t->cmd("ifconfig -T system:$_");
 | 
						|
        my $side = "0";
 | 
						|
        foreach (@data) {
 | 
						|
            if (/eth(\d)/) {
 | 
						|
                $telnetrscan{$id}{$side}{'side'} = $side;
 | 
						|
                $telnetrscan{$id}{$side}{'type'} = "bmc";
 | 
						|
            }
 | 
						|
            if (/-i (\d+\.\d+\.\d+\.\d+)/ && defined($side)) {
 | 
						|
                $telnetrscan{$id}{$side}{'ip'} = $1;
 | 
						|
                ## TRACE_LINE print "rscanfsp found: blade[$id] - ip [$telnetrscan{$id}{$side}{'ip'}], type [$telnetrscan{$id}{$side}{'type'}], side [$telnetrscan{$id}{$side}{'side'}].\n";
 | 
						|
            }
 | 
						|
        }
 | 
						|
    }
 | 
						|
    return [0];
 | 
						|
}
 | 
						|
 | 
						|
sub mmtextid {
 | 
						|
 | 
						|
    my $t     = shift;
 | 
						|
    my $mpa   = shift;
 | 
						|
    my $value = shift;
 | 
						|
    my $mm    = shift;
 | 
						|
 | 
						|
    $value = ($value =~ /^\*/) ? $mpa : $value;
 | 
						|
    my @data = $t->cmd("config -name $value -T system:$mm");
 | 
						|
    if (!grep(/OK/i, @data)) {
 | 
						|
        return ([ 1, @data ]);
 | 
						|
    }
 | 
						|
    my @data = $t->cmd("config -name \"$value\" -T system"); #on cmms, this identifier is frequently relevant...
 | 
						|
    return undef;                                            #([0,"textid: $value"]);
 | 
						|
}
 | 
						|
 | 
						|
sub get_blades_for_mpa {
 | 
						|
    my $mpa         = shift;
 | 
						|
    my %blades_hash = ();
 | 
						|
    my $mptab       = xCAT::Table->new('mp');
 | 
						|
    my $ppctab      = xCAT::Table->new('ppc');
 | 
						|
    my @attribs     = qw(id nodetype parent hcp);
 | 
						|
    if (!defined($mptab) or !defined($ppctab)) {
 | 
						|
        return undef;
 | 
						|
    }
 | 
						|
    my @nodearray = $mptab->getAttribs({ mpa => $mpa }, qw(node));
 | 
						|
    my @blades = ();
 | 
						|
    my $nodesattrs;
 | 
						|
    if (!(@nodearray)) {
 | 
						|
        return (\%blades_hash);
 | 
						|
    } else {
 | 
						|
        foreach (@nodearray) {
 | 
						|
            if (defined($_->{node})) {
 | 
						|
                push @blades, $_->{node};
 | 
						|
            }
 | 
						|
        }
 | 
						|
        $nodesattrs = $ppctab->getNodesAttribs(\@blades, \@attribs);
 | 
						|
    }
 | 
						|
    foreach my $node (@blades) {
 | 
						|
        my @values = ();
 | 
						|
        my $att    = $nodesattrs->{$node}->[0];
 | 
						|
        if (!defined($att)) {
 | 
						|
            next;
 | 
						|
        } elsif (!defined($att->{parent}) or ($att->{parent} ne $mpa) or !defined($att->{nodetype}) or ($att->{nodetype} ne "blade")) {
 | 
						|
            next;
 | 
						|
        }
 | 
						|
        my $request;
 | 
						|
        my $hcp_ip = xCAT::FSPUtils::getIPaddress($request, $att->{nodetype}, $att->{hcp});
 | 
						|
        if (!defined($hcp_ip) or ($hcp_ip == -3)) {
 | 
						|
            next;
 | 
						|
        }
 | 
						|
        push @values, $att->{id};
 | 
						|
        push @values, '0';
 | 
						|
        push @values, '0';
 | 
						|
        push @values, $hcp_ip;
 | 
						|
        push @values, "blade";
 | 
						|
        push @values, $mpa;
 | 
						|
        $blades_hash{$node} = \@values;
 | 
						|
        verbose_message("values for node:$node, value:@values.");
 | 
						|
    }
 | 
						|
    return (\%blades_hash);
 | 
						|
}
 | 
						|
 | 
						|
sub updateBMC {
 | 
						|
    my $mpa   = shift;
 | 
						|
    my $user  = shift;
 | 
						|
    my $pass  = shift;
 | 
						|
    my @nodes = ();
 | 
						|
    my $mphash;
 | 
						|
    my $mptab = xCAT::Table->new('mp');
 | 
						|
    if ($mptab) {
 | 
						|
        my @mpents = $mptab->getAllNodeAttribs([ 'node', 'mpa', 'id' ]);
 | 
						|
        foreach (@mpents) {
 | 
						|
            my $node = $_->{node};
 | 
						|
            if (defined($_->{mpa}) and ($_->{mpa} eq $mpa) and defined($_->{id}) and ($_->{id} ne '0')) {
 | 
						|
                push @nodes, $node;
 | 
						|
                $mphash->{$node} = [$_];
 | 
						|
            }
 | 
						|
        }
 | 
						|
    }
 | 
						|
    my $ipmitab = xCAT::Table->new('ipmi');
 | 
						|
    if ($ipmitab) {
 | 
						|
        my $ipmihash = $ipmitab->getNodesAttribs(\@nodes, [ 'bmc', 'username', 'password' ]);
 | 
						|
        foreach (@nodes) {
 | 
						|
            if (defined($ipmihash->{$_}->[0]) && defined($ipmihash->{$_}->[0]->{'bmc'})) {
 | 
						|
                my $ipmiuser = $user;
 | 
						|
                my $ipmipass = $pass;
 | 
						|
 | 
						|
                my $authdata = xCAT::PasswordUtils::getIPMIAuth(noderange => [$_], ipmihash => $ipmihash, mphash => $mphash);
 | 
						|
                if (exists($authdata->{$_}->{username})) {
 | 
						|
                    $ipmiuser = $authdata->{$_}->{username};
 | 
						|
                }
 | 
						|
                if (exists($authdata->{$_}->{password})) {
 | 
						|
                    $ipmipass = $authdata->{$_}->{password};
 | 
						|
                }
 | 
						|
                xCAT::IMMUtils::setupIMM($_, curraddr => $ipmihash->{$_}->[0]->{'bmc'}, skipbmcidcheck => 1, skipnetconfig => 1, cliusername => $ipmiuser, clipassword => $ipmipass, callback => $CALLBACK);
 | 
						|
            }
 | 
						|
        }
 | 
						|
    }
 | 
						|
    return;
 | 
						|
}
 | 
						|
 | 
						|
sub passwd {
 | 
						|
    my $t       = shift;
 | 
						|
    my $mpa     = shift;
 | 
						|
    my $user    = shift;
 | 
						|
    my $pass    = shift;
 | 
						|
    my $oldpass = shift;
 | 
						|
    my $mm      = shift;
 | 
						|
    if ($pass =~ /^=/) {
 | 
						|
        $pass =~ s/=//;
 | 
						|
    } elsif ($pass =~ /=/) {
 | 
						|
        ($user, $pass) = split /=/, $pass;
 | 
						|
    }
 | 
						|
 | 
						|
    if (!$pass) {
 | 
						|
        return ([ 1, "No param specified for '$user'" ]);
 | 
						|
    }
 | 
						|
    my $mpatab = xCAT::Table->new('mpa');
 | 
						|
    if ($mpatab) {
 | 
						|
        my ($ent) = $mpatab->getAttribs({ mpa => $mpa, username => $user }, qw(password));
 | 
						|
 | 
						|
        #my $oldpass = 'PASSW0RD';
 | 
						|
        #if (defined($ent->{password})) {$oldpass = $ent->{password}};
 | 
						|
        my @data = ();
 | 
						|
        if ($oldpass ne $pass) {
 | 
						|
            my $cmd  = "users -n $user -op $oldpass -p $pass -T system:$mm";
 | 
						|
            my @data = $t->cmd($cmd);
 | 
						|
            if (!grep(/OK/i, @data)) {
 | 
						|
                return ([ 1, @data ]);
 | 
						|
            }
 | 
						|
        }
 | 
						|
        @data = ();
 | 
						|
        my $snmp_cmd = "users -n $user -ap sha -pp des -ppw $pass -T system:$mm";
 | 
						|
        @data = $t->cmd($snmp_cmd);
 | 
						|
        if (!grep(/ok/i, @data)) {
 | 
						|
            my $cmd      = "users -n $user -op $pass -p $oldpass -T system:$mm";
 | 
						|
            my @back_pwd = $t->cmd($cmd);
 | 
						|
            if (!grep(/OK/i, @back_pwd)) {
 | 
						|
                $mpatab->setAttribs({ mpa => $mpa, username => $user }, { password => $pass });
 | 
						|
            }
 | 
						|
            return ([ 1, @data ]);
 | 
						|
        }
 | 
						|
 | 
						|
        $mpatab->setAttribs({ mpa => $mpa, username => $user }, { password => $pass });
 | 
						|
        if ($user eq "USERID") {
 | 
						|
            my $fsp_api = ($::XCATROOT) ? "$::XCATROOT/sbin/fsp-api" : "/opt/xcat/sbin/fsp-api";
 | 
						|
            my $blades = &get_blades_for_mpa($mpa);
 | 
						|
            if (!defined($blades)) {
 | 
						|
                return ([ 1, "Find blades failed for $mpa" ]);
 | 
						|
            }
 | 
						|
            my @failed_blades = ();
 | 
						|
            foreach (keys %$blades) {
 | 
						|
                my $node_name = $_;
 | 
						|
                my $att       = $blades->{$node_name};
 | 
						|
                my $con_cmd = "$fsp_api -a query_connection -T 0 -t 0:$$att[3]:$$att[0]:$node_name: 2>&1";
 | 
						|
 | 
						|
                #print "===>query_con_cmd=$con_cmd\n";
 | 
						|
                my $res = xCAT::Utils->runcmd($con_cmd, -1);
 | 
						|
                if ($res =~ /No connection information found/i) {
 | 
						|
                    next; #we don't need to update password for FSPs that havn't created DFM links#
 | 
						|
                } elsif ($res =~ /The hdwr_svr daemon is not currently running/i) {
 | 
						|
                    return ([ 1, "Update password for 'hdwr_svr' failed because the 'hdwr_svr' daemon is not currently running. Please recreate the connections between blades and hdwr_svr." ]);
 | 
						|
                }
 | 
						|
                my $hws_cmd = "$fsp_api -a reset_hws_pw -u HMC -p $oldpass -P $pass -T 0 -t 0:$$att[3]:$$att[0]:$node_name: 2>&1";
 | 
						|
 | 
						|
                #print "===>set_hws_cmd=$hws_cmd\n";
 | 
						|
 | 
						|
                $res = xCAT::Utils->runcmd($hws_cmd, -1);
 | 
						|
                if ($res =~ /Error/i) {
 | 
						|
                    push @failed_blades, $node_name;
 | 
						|
                }
 | 
						|
            }
 | 
						|
            if (scalar(@failed_blades)) {
 | 
						|
                my $fblades = join(',', @failed_blades);
 | 
						|
                return ([ 1, "Update password of HMC for '$fblades' failed. Please recreate the DFM connections for them." ]);
 | 
						|
            }
 | 
						|
        } else {
 | 
						|
 | 
						|
            #TODO: add new user if name mismatches what MM alread understands..
 | 
						|
            #additionally, may have to delete USERID in this event
 | 
						|
        }
 | 
						|
    } else {
 | 
						|
        return ([ 1, "Update password for $user in 'mpa' table failed" ]);
 | 
						|
    }
 | 
						|
    return ([ 0, "Succeeded" ]);
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
 | 
						|
sub pd {
 | 
						|
 | 
						|
    my $t     = shift;
 | 
						|
    my $pd    = shift;
 | 
						|
    my $value = shift;
 | 
						|
    my @result;
 | 
						|
 | 
						|
    if ($value) {
 | 
						|
        if ($value !~ /^nonred|redwoperf|redwperf$/) {
 | 
						|
            return ([ 1, "Invalid power management (redwoperf|redwperf|nonred)" ]);
 | 
						|
        }
 | 
						|
        my @data = $t->cmd("fuelg $pd -os $value");
 | 
						|
        if (!grep(/OK/i, @data)) {
 | 
						|
            return ([ 1, @data ]);
 | 
						|
        }
 | 
						|
        return ([ 0, "$pd: $value" ]);
 | 
						|
    }
 | 
						|
    my @data = $t->cmd("fuelg");
 | 
						|
    my @pds = split /--------------/, join('', @data);
 | 
						|
    $pd =~ /pd(\d)/;
 | 
						|
 | 
						|
    $pds[$1] =~ /Power Management Policy:\s+(.*)\n/;
 | 
						|
    return ([ 0, $1 ]);
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
sub network {
 | 
						|
 | 
						|
    my $t     = shift;
 | 
						|
    my $value = shift;
 | 
						|
    my $mpa   = shift;
 | 
						|
    my $mm    = shift;
 | 
						|
    my $node  = shift;
 | 
						|
    my $slot  = shift;
 | 
						|
    my $reset = shift;
 | 
						|
 | 
						|
    my $ipmiflag = 0;
 | 
						|
    $ipmiflag = 1 if ($node =~ s/--ipmi//);
 | 
						|
    my $cmd;
 | 
						|
    if ($mpa eq $node) {
 | 
						|
 | 
						|
        # The network setting for the mm
 | 
						|
        $cmd = "ifconfig -eth0 -c static -r auto -d auto -m 1500 -T system:$mm";
 | 
						|
    } else {
 | 
						|
 | 
						|
        # The network setting for the service processor of blade
 | 
						|
        my @data = $t->cmd("ifconfig -T system:blade[$slot]");
 | 
						|
 | 
						|
        # get the active interface
 | 
						|
        # MM[1] - FSP eth1 MM[2] - FSP eth0
 | 
						|
        my $if;
 | 
						|
        if ($mm =~ /\[(\d)\]/) {
 | 
						|
            if ($1 eq "1") {
 | 
						|
                $if = "eth1";
 | 
						|
            } elsif ($1 eq "2") {
 | 
						|
                $if = "eth0";
 | 
						|
            } else {
 | 
						|
                $if = "eth" . $1;
 | 
						|
            }
 | 
						|
        } else {
 | 
						|
            foreach (@data) {
 | 
						|
                if (/eth(\d)/) { $if = "eth" . $1; last; }
 | 
						|
            }
 | 
						|
        }
 | 
						|
        if (!$if) { return ([ 1, "Cannot find the interface of blade." ]) }
 | 
						|
        $cmd = "ifconfig -$if -c static -T system:blade[$slot]";
 | 
						|
    }
 | 
						|
    my ($ip, $host, $gateway, $mask);
 | 
						|
 | 
						|
    if ($value) {
 | 
						|
        if ($value !~ /\*/) {
 | 
						|
            ($ip, $host, $gateway, $mask) = split /,/, $value;
 | 
						|
            if (!$ip and !$host and !$gateway and !$mask) {
 | 
						|
                return ([ 1, "No changes specified" ]);
 | 
						|
            }
 | 
						|
            if ($mpa ne $node) {
 | 
						|
                $host = undef;
 | 
						|
            }
 | 
						|
        }
 | 
						|
        else {
 | 
						|
            if ($value !~ /^\*$/) {
 | 
						|
                return ([ 1, "Invalid format: 'network=*'" ]);
 | 
						|
            }
 | 
						|
            if ($mpa eq $node) {    #for network configure to management module
 | 
						|
                my %nethash = xCAT::DBobjUtils->getNetwkInfo([$node]);
 | 
						|
                my $gate    = $nethash{$node}{gateway};
 | 
						|
                my $result;
 | 
						|
 | 
						|
                if ($gate) {
 | 
						|
                    $result = xCAT::NetworkUtils::toIP($gate);
 | 
						|
                    if (@$result[0] == 0) {
 | 
						|
                        $gateway = @$result[1];
 | 
						|
                    }
 | 
						|
                }
 | 
						|
                $mask = $nethash{$node}{mask};
 | 
						|
 | 
						|
                #the host is only needed for the mpa network configuration
 | 
						|
                $host = $node;
 | 
						|
 | 
						|
                my $hosttab = xCAT::Table->new('hosts');
 | 
						|
                if ($hosttab) {
 | 
						|
                    my ($ent) = $hosttab->getNodeAttribs($node, ['ip']);
 | 
						|
                    if (defined($ent)) {
 | 
						|
                        $ip = $ent->{ip};
 | 
						|
                    }
 | 
						|
                    $hosttab->close();
 | 
						|
                }
 | 
						|
                unless ($ip) {
 | 
						|
                    $ip = xCAT::NetworkUtils->getipaddr($node);
 | 
						|
                }
 | 
						|
            } else {
 | 
						|
 | 
						|
                if ($ipmiflag) {
 | 
						|
                    my $ipmitab = xCAT::Table->new('ipmi');
 | 
						|
                    if ($ipmitab) {
 | 
						|
                        my $bmcip = $ipmitab->getNodeAttribs($node, ['bmc']);
 | 
						|
                        if (defined($bmcip)) {
 | 
						|
                            $ip = $bmcip->{bmc};
 | 
						|
                        }
 | 
						|
                    }
 | 
						|
                } else {
 | 
						|
                    my $ppctab = xCAT::Table->new('ppc');
 | 
						|
                    if ($ppctab) {
 | 
						|
                        my $ppcent = $ppctab->getNodeAttribs($node, ['hcp']);
 | 
						|
                        if (defined($ppcent)) {
 | 
						|
                            $ip = $ppcent->{hcp};
 | 
						|
                        }
 | 
						|
                    }
 | 
						|
                }
 | 
						|
                my %nethash = xCAT::DBobjUtils->getNetwkInfo([$ip]);
 | 
						|
                my $gate    = $nethash{$ip}{gateway};
 | 
						|
                my $result;
 | 
						|
 | 
						|
                if ($gate) {
 | 
						|
                    $result = xCAT::NetworkUtils::toIP($gate);
 | 
						|
                    if (@$result[0] == 0) {
 | 
						|
                        $gateway = @$result[1];
 | 
						|
                    }
 | 
						|
                }
 | 
						|
                $mask = $nethash{$ip}{mask};
 | 
						|
            }
 | 
						|
        }
 | 
						|
    } else {
 | 
						|
        return ([ 1, "No changes specified" ]);
 | 
						|
    }
 | 
						|
    if (!$ip && !$host && !$gateway && !$mask) {
 | 
						|
        return ([ 1, "No changes specified" ]);
 | 
						|
    } elsif (!$ip) {
 | 
						|
        return ([ 1, "No ip address specified" ]);
 | 
						|
    }
 | 
						|
 | 
						|
    if ($ip)      { $cmd .= " -i $ip"; }
 | 
						|
    if ($host)    { $cmd .= " -n $host"; }
 | 
						|
    if ($gateway) { $cmd .= " -g $gateway"; }
 | 
						|
    if ($mask)    { $cmd .= " -s $mask"; }
 | 
						|
 | 
						|
    ## TRACE_LINE print "The cmd to set for the network = $cmd\n";
 | 
						|
    my @data = $t->cmd($cmd);
 | 
						|
    if (!@data) {
 | 
						|
        return ([ 1, "Failed" ]);
 | 
						|
    }
 | 
						|
 | 
						|
    my @result = grep(/These configuration changes will become active/, @data);
 | 
						|
    ## TRACE_LINE print "  rc = @data\n";
 | 
						|
    if (!@result) {
 | 
						|
        if (!(@result = grep (/OK/, @data))) {
 | 
						|
            return ([ 1, @data ]);
 | 
						|
        }
 | 
						|
    } elsif (defined($reset)) {
 | 
						|
        @result = ();
 | 
						|
    }
 | 
						|
 | 
						|
    if ($mask)    { unshift @result, "Subnet Mask: $mask"; }
 | 
						|
    if ($gateway) { unshift @result, "Gateway: $gateway"; }
 | 
						|
    if ($host)    { unshift @result, "Hostname: $host"; }
 | 
						|
    if ($ip)      { unshift @result, "IP: $ip"; }
 | 
						|
 | 
						|
    return ([ 0, @result ]);
 | 
						|
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
sub swnet {
 | 
						|
 | 
						|
    my $t       = shift;
 | 
						|
    my $command = shift;
 | 
						|
    my $value   = shift;
 | 
						|
    my @result;
 | 
						|
    my ($ip, $gateway, $mask);
 | 
						|
 | 
						|
    #default is switch[1].  if the user specificed a number, use it instead
 | 
						|
    my $switch = "switch[1]";
 | 
						|
    if ($command !~ /^swnet$/) {
 | 
						|
        my $switchNum = $command;
 | 
						|
        $switchNum =~ s/swnet//;
 | 
						|
        $switch = "switch[$switchNum]";
 | 
						|
    }
 | 
						|
 | 
						|
    if (!$value) {
 | 
						|
        my @data = $t->cmd("ifconfig -T system:$switch");
 | 
						|
        my $s = join('', @data);
 | 
						|
        if ($s =~ /-i\s+(\S+)/) { $ip      = $1; }
 | 
						|
        if ($s =~ /-g\s+(\S+)/) { $gateway = $1; }
 | 
						|
        if ($s =~ /-s\s+(\S+)/) { $mask    = $1; }
 | 
						|
    }
 | 
						|
    else {
 | 
						|
        my $cmd =
 | 
						|
          "ifconfig -em disabled -ep enabled -pip enabled -T system:$switch";
 | 
						|
        ($ip, $gateway, $mask) = split /,/, $value;
 | 
						|
 | 
						|
        if (!$ip and !$gateway and !$mask) {
 | 
						|
            return ([ 1, "No changes specified" ]);
 | 
						|
        }
 | 
						|
        if ($ip)      { $cmd .= " -i $ip"; }
 | 
						|
        if ($gateway) { $cmd .= " -g $gateway"; }
 | 
						|
        if ($mask)    { $cmd .= " -s $mask"; }
 | 
						|
 | 
						|
        my @data = $t->cmd($cmd);
 | 
						|
        @result = grep(/OK/i, @data);
 | 
						|
        if (!@result) {
 | 
						|
            return ([ 1, @data ]);
 | 
						|
        }
 | 
						|
    }
 | 
						|
    if ($ip)      { push @result, "Switch IP: $ip"; }
 | 
						|
    if ($gateway) { push @result, "Gateway: $gateway"; }
 | 
						|
    if ($mask)    { push @result, "Subnet Mask: $mask"; }
 | 
						|
    return ([ 0, @result ]);
 | 
						|
 | 
						|
}
 | 
						|
 | 
						|
sub snmpcfg {
 | 
						|
 | 
						|
    my $t     = shift;
 | 
						|
    my $value = shift;
 | 
						|
    my $uid   = shift;
 | 
						|
    my $pass  = shift;
 | 
						|
    my $mm    = shift;
 | 
						|
 | 
						|
    if ($value !~ /^enable|disable$/i) {
 | 
						|
        return ([ 1, "Invalid argument '$value' (enable|disable)" ]);
 | 
						|
    }
 | 
						|
 | 
						|
    # Check the type of mm
 | 
						|
    my @data = $t->cmd("info -T system:$mm");
 | 
						|
    if (grep(/: Chassis Management Module/, @data) && $mptype ne "cmm") {
 | 
						|
        $mptype = "cmm";
 | 
						|
 | 
						|
        #return ([1,"The hwtype attribute should be set to \'cmm\' for a Chassis Management Module."]);
 | 
						|
    }
 | 
						|
 | 
						|
    # Query users on MM
 | 
						|
    my $id;
 | 
						|
    if ($mptype =~ /^[a]?mm$/) {
 | 
						|
        @data = $t->cmd("users -T system:$mm");
 | 
						|
        my ($user) = grep(/\d+\.\s+$uid/, @data);
 | 
						|
        if (!$user) {
 | 
						|
            return ([ 1, "Cannot find user: '$uid' on MM" ]);
 | 
						|
        }
 | 
						|
        $user =~ /^(\d+)./;
 | 
						|
        $id = $1;
 | 
						|
    } elsif ($mptype eq "cmm") {
 | 
						|
        @data = $t->cmd("users -n $uid -T system:$mm");
 | 
						|
        if (!grep (/Account is active/, @data)) {
 | 
						|
            return ([ 1, "Cannot find user: '$uid' on MM" ]);
 | 
						|
        }
 | 
						|
    } else {
 | 
						|
        return ([ 1, "Hardware type [$mptype] is not supported. Valid types: mm,cmm." ]);
 | 
						|
    }
 | 
						|
 | 
						|
    my $pp = ($value =~ /^enable$/i) ? "des" : "none";
 | 
						|
    if ($pp eq "des") {
 | 
						|
        @data = $t->cmd("snmp -a3 -on -T system:$mm");
 | 
						|
    } else {
 | 
						|
        @data = $t->cmd("snmp -a3 -off -T system:$mm");
 | 
						|
    }
 | 
						|
 | 
						|
    my $cmd;
 | 
						|
    if ($mptype =~ /^[a]?mm$/) {
 | 
						|
        $cmd = "users -$id -ap sha -at write -ppw $pass -pp $pp -T system:$mm";
 | 
						|
    } elsif ($mptype eq "cmm") {
 | 
						|
        $cmd = "users -n $uid  -ap sha -at set -ppw $pass -pp $pp -T system:$mm";
 | 
						|
    }
 | 
						|
    @data = $t->cmd($cmd);
 | 
						|
 | 
						|
    if (grep(/OK/i, @data)) {
 | 
						|
        return ([ 0, "SNMP $value: OK" ]);
 | 
						|
    }
 | 
						|
    return ([ 1, @data ]);
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
sub sshcfg {
 | 
						|
 | 
						|
    my $t     = shift;
 | 
						|
    my $value = shift;
 | 
						|
    my $uid   = shift;
 | 
						|
    my $mm    = shift;
 | 
						|
    my $fname = ((xCAT::Utils::isAIX()) ? "/.ssh/" : "/root/.ssh/") . "id_rsa.pub";
 | 
						|
 | 
						|
    if ($value) {
 | 
						|
        if ($value !~ /^enable|disable$/i) {
 | 
						|
            return ([ 1, "Invalid argument '$value' (enable|disable)" ]);
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    # Does MM support SSH
 | 
						|
    my @data = $t->cmd("sshcfg -hk rsa -T system:$mm");
 | 
						|
 | 
						|
    if (grep(/Error: Command not recognized/, @data)) {
 | 
						|
        return ([ 1, "SSH supported on AMM with minimum firmware BPET32" ]);
 | 
						|
    }
 | 
						|
 | 
						|
    # Check the type of mm
 | 
						|
    @data = $t->cmd("info -T system:$mm");
 | 
						|
    if (grep(/: Chassis Management Module/, @data) && $mptype ne "cmm") {
 | 
						|
 | 
						|
        #return ([1,"The hwtype attribute should be set to \'cmm\' for a Chassis Management Module."]);
 | 
						|
        $mptype = "cmm"; #why in the world wouldn't we have just done this from the get go????
 | 
						|
    }
 | 
						|
 | 
						|
    # Get firmware version on MM
 | 
						|
    if ($mptype =~ /^[a]?mm$/) {
 | 
						|
        @data = $t->cmd("update -a -T system:$mm");
 | 
						|
        my ($line) = grep(/Build ID:\s+\S+/, @data);
 | 
						|
 | 
						|
        # Minumum firmware version BPET32 required for SSH
 | 
						|
        $line =~ /(\d.)/;
 | 
						|
        if (hex($1) < hex(32)) {
 | 
						|
            return ([ 1, "SSH supported on AMM with minimum firmware BPET32" ]);
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    # Get SSH key on Management Node
 | 
						|
    unless (open(RSAKEY, "<$fname")) {
 | 
						|
        return ([ 1, "Error opening '$fname'" ]);
 | 
						|
    }
 | 
						|
    my ($sshkey) = <RSAKEY>;
 | 
						|
    close(RSAKEY);
 | 
						|
 | 
						|
    if ($sshkey !~ /\s+(\S+\@\S+$)/) {
 | 
						|
        return ([ 1, "Cannot find userid\@host in '$fname'" ]);
 | 
						|
    }
 | 
						|
    my $login = $1;
 | 
						|
 | 
						|
    # Query users on MM
 | 
						|
    my $user;
 | 
						|
    @data = $t->cmd("users -T system:$mm");
 | 
						|
    if ($mptype =~ /^[a]?mm$/) {
 | 
						|
        ($user) = grep(/\d+\.\s+$uid/, @data);
 | 
						|
    } elsif ($mptype eq "cmm") {
 | 
						|
        my $getin; # The userid is wrapped insied the lines with keywords 'Users' and 'User Permission Groups'
 | 
						|
        foreach my $line (@data) {
 | 
						|
            chomp($line);
 | 
						|
            if ($line =~ /^Users$/) {
 | 
						|
                $getin = 1;
 | 
						|
            } elsif ($line =~ /^User Permission Groups$/) {
 | 
						|
                last;
 | 
						|
            }
 | 
						|
 | 
						|
            if ($getin) {
 | 
						|
                if (($line =~ /^([^\s]+)$/) && ($uid eq $1)) {
 | 
						|
                    $user = $uid;
 | 
						|
                    last;
 | 
						|
                }
 | 
						|
            }
 | 
						|
        }
 | 
						|
    }
 | 
						|
    if (!$user) {
 | 
						|
        return ([ 1, "Cannot find user: '$uid' on MM" ]);
 | 
						|
    }
 | 
						|
    $user =~ /^(\d+)./;
 | 
						|
    my $id = $1;
 | 
						|
 | 
						|
    # Determine is key already exists on MM
 | 
						|
    if ($mptype =~ /^[a]?mm$/) {
 | 
						|
        @data = $t->cmd("users -$id -pk all -T system:$mm");
 | 
						|
    } elsif ($mptype eq "cmm") {
 | 
						|
        @data = $t->cmd("users -n $uid -ki all -T system:$mm");
 | 
						|
    }
 | 
						|
 | 
						|
    # Query if enabled/disabled
 | 
						|
    if (!$value) {
 | 
						|
        my @ddata = $t->cmd("sshcfg -T system:$mm");
 | 
						|
 | 
						|
        if (my ($d) = grep(/^-cstatus\s+(\S+)$/, @ddata)) {
 | 
						|
            if ($d =~ /\s(\S+)$/) {
 | 
						|
                if ($1 =~ /^disabled/i) {
 | 
						|
                    return ([ 0, "SSH: disabled" ]);
 | 
						|
                }
 | 
						|
            }
 | 
						|
        }
 | 
						|
 | 
						|
        # Find login
 | 
						|
        foreach (split(/Key\s+/, join('', @data))) {
 | 
						|
            if (/-cm\s+$login/) {
 | 
						|
                return ([ 0, "SSH: enabled" ]);
 | 
						|
            }
 | 
						|
        }
 | 
						|
        return ([ 0, "SSH: disabled" ]);
 | 
						|
    }
 | 
						|
 | 
						|
    # Remove existing keys for this login
 | 
						|
    foreach (split(/Key\s+/, join('', @data))) {
 | 
						|
        if (/-cm\s+$login/) {
 | 
						|
            /^(\d+)/;
 | 
						|
            my $key = $1;
 | 
						|
            if ($mptype =~ /^[a]?mm$/) {
 | 
						|
                @data = $t->cmd("users -$id -pk -$key -remove -T system:$mm");
 | 
						|
            } elsif ($mptype eq "cmm") {
 | 
						|
                @data = $t->cmd("users -n $uid -remove -ki $key -T system:$mm");
 | 
						|
            }
 | 
						|
        }
 | 
						|
    }
 | 
						|
    if ($value =~ /^disable$/i) {
 | 
						|
        if (!grep(/^OK$/i, @data)) {
 | 
						|
            return ([ 1, "SSH Key not found on MM" ]);
 | 
						|
        }
 | 
						|
        return ([ 0, "disabled" ]);
 | 
						|
    }
 | 
						|
 | 
						|
    # Make sure SSH key is generated on MM
 | 
						|
    @data = $t->cmd("sshcfg -hk rsa -T system:$mm");
 | 
						|
 | 
						|
    if (!grep(/ssh-rsa/, @data)) {
 | 
						|
        @data = $t->cmd("sshcfg -hk gen -T system:$mm");
 | 
						|
        if (!grep(/^OK$/i, @data)) {
 | 
						|
            return ([ 1, @data ]);
 | 
						|
        }
 | 
						|
 | 
						|
        # Wait for SSH key generation to complete
 | 
						|
        my $timeout = time + 240;
 | 
						|
 | 
						|
        while (1) {
 | 
						|
            if (time >= $timeout) {
 | 
						|
                return ([ 1, "SSH key generation timeout" ]);
 | 
						|
            }
 | 
						|
            sleep(15);
 | 
						|
            @data = $t->cmd("sshcfg -hk rsa -T system:$mm");
 | 
						|
            if (grep(/ssh-rsa/, @data)) {
 | 
						|
                last;
 | 
						|
            }
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    # Transfer SSH key from Management Node to MM
 | 
						|
    $sshkey =~ s/@/\@/;
 | 
						|
    if ($mptype =~ /^[a]?mm$/) {
 | 
						|
        $t->cmd("users -$id -at set -T system:$mm");
 | 
						|
        @data = $t->cmd("users -$id -pk -T system:$mm -add $sshkey");
 | 
						|
    } elsif ($mptype eq "cmm") {
 | 
						|
        chomp($sshkey);
 | 
						|
        $t->cmd("users -n $uid -at set -T system:$mm");
 | 
						|
        @data = $t->cmd("users -n $uid -add -kf openssh -T system:$mm -key \"$sshkey\"");
 | 
						|
    }
 | 
						|
 | 
						|
    if ($data[0] =~ /Error/i) {
 | 
						|
        if ($data[0] =~ /Error writing data for option -add/i) {
 | 
						|
            return ([ 1, "Maximum number of SSH keys reached for this chassis" ]);
 | 
						|
        }
 | 
						|
        return ([ 1, $data[0] ]);
 | 
						|
    } elsif (!grep /OK/, @data) {
 | 
						|
        return ([ 1, $data[0] ]);
 | 
						|
    }
 | 
						|
 | 
						|
    # Enable ssh on MM
 | 
						|
    @data = $t->cmd("ports -sshe on -T system:$mm");
 | 
						|
    return ([ 0, "SSH $value: OK" ]);
 | 
						|
}
 | 
						|
 | 
						|
sub ntp {
 | 
						|
 | 
						|
    my $value = shift;
 | 
						|
    my @result;
 | 
						|
 | 
						|
    my $data = $session->get([ '1.3.6.1.4.1.2.3.51.2.4.9.3.8.1', 0 ]);
 | 
						|
    if ($data =~ /NOSUCHOBJECT/) {
 | 
						|
        return ([ 1, "NTP Not supported" ]);
 | 
						|
    }
 | 
						|
    if ($value) {
 | 
						|
        my ($ntp, $ip, $f, $v3) = split /,/, $value;
 | 
						|
 | 
						|
        if ($ntp) {
 | 
						|
            if ($ntp !~ /^enable|disable$/i) {
 | 
						|
                return ([ 1, "Invalid argument '$ntp' (enable|disable)" ]);
 | 
						|
            }
 | 
						|
        }
 | 
						|
        if ($v3) {
 | 
						|
            if ($v3 !~ /^enable|disable$/i) {
 | 
						|
                return ([ 1, "Invalid argument '$v3' (enable|disable)" ]);
 | 
						|
            }
 | 
						|
        }
 | 
						|
        if (!$ntp and !$ip and !$f and !$v3) {
 | 
						|
            return ([ 1, "No changes specified" ]);
 | 
						|
        }
 | 
						|
        if ($ntp) {
 | 
						|
            my $d = ($ntp =~ /^enable$/i) ? 1 : 0;
 | 
						|
            setoid('1.3.6.1.4.1.2.3.51.2.4.9.3.8.1', 0, $d, 'INTEGER');
 | 
						|
            push @result, "NTP: $ntp";
 | 
						|
        }
 | 
						|
        if ($ip) {
 | 
						|
            setoid('1.3.6.1.4.1.2.3.51.2.4.9.3.8.2', 0, $ip, 'OCTET');
 | 
						|
            push @result, "NTP Server: $ip";
 | 
						|
        }
 | 
						|
        if ($f) {
 | 
						|
            setoid('1.3.6.1.4.1.2.3.51.2.4.9.3.8.3', 0, $f, 'INTEGER');
 | 
						|
            push @result, "NTP Frequency: $f";
 | 
						|
        }
 | 
						|
        if ($v3) {
 | 
						|
            my $d = ($v3 =~ /^enable$/i) ? 1 : 0;
 | 
						|
            setoid('1.3.6.1.4.1.2.3.51.2.4.9.3.8.7', 0, $d, 'INTEGER');
 | 
						|
            push @result, "NTP v3: $v3";
 | 
						|
        }
 | 
						|
        return ([ 0, @result ]);
 | 
						|
    }
 | 
						|
    my $d = (!$data) ? "disabled" : "enabled";
 | 
						|
    push @result, "NTP: $d";
 | 
						|
 | 
						|
    $data = $session->get([ '1.3.6.1.4.1.2.3.51.2.4.9.3.8.2', 0 ]);
 | 
						|
    push @result, "NTP Server: $data";
 | 
						|
 | 
						|
    $data = $session->get([ '1.3.6.1.4.1.2.3.51.2.4.9.3.8.3', 0 ]);
 | 
						|
    push @result, "NTP Frequency: $data (minutes)";
 | 
						|
 | 
						|
    $data = $session->get([ '1.3.6.1.4.1.2.3.51.2.4.9.3.8.7', 0 ]);
 | 
						|
    $d = (!$data) ? "disabled" : "enabled";
 | 
						|
    push @result, "NTP v3: $d";
 | 
						|
    return ([ 0, @result ]);
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
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;
 | 
						|
        my $responses;
 | 
						|
        eval {
 | 
						|
            $responses = fd_retrieve($rfh);
 | 
						|
        };
 | 
						|
        if ($@ and $@ =~ /^Magic number checking on storable file/) { #this most likely means we ran over the end of available input
 | 
						|
            $fds->remove($rfh);
 | 
						|
            close($rfh);
 | 
						|
        } else {
 | 
						|
            eval { print $rfh "ACK\n"; }; #Ignore ack loss due to child giving up and exiting, we don't actually explicitly care about the acks
 | 
						|
            foreach (@$responses) {
 | 
						|
                $callback->($_);
 | 
						|
            }
 | 
						|
        }
 | 
						|
    }
 | 
						|
    yield;    #Try to avoid useless iterations as much as possible
 | 
						|
    return $rc;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
sub dompa {
 | 
						|
    my $out = shift;
 | 
						|
    $mpa = shift;
 | 
						|
    my $mpahash   = shift;
 | 
						|
    my $command   = shift;
 | 
						|
    my %namedargs = @_;
 | 
						|
    my @exargs    = @{ $namedargs{-args} };
 | 
						|
    my $node;
 | 
						|
    my $args = \@exargs;
 | 
						|
 | 
						|
    #Handle http commands on their own
 | 
						|
    if ($command eq "getrvidparms") {
 | 
						|
        my $user = $mpahash->{$mpa}->{username};
 | 
						|
        my $pass = $mpahash->{$mpa}->{password};
 | 
						|
        my $method;
 | 
						|
        unless ($method = httplogin($mpa, $user, $pass)) {
 | 
						|
            foreach $node (sort (keys %{ $mpahash->{$mpa}->{nodes} })) {
 | 
						|
                my %outh;
 | 
						|
                %outh = (
 | 
						|
                    node => [ {
 | 
						|
                            name  => [$node],
 | 
						|
                            error => ["Unable to perform http login to $mpa"],
 | 
						|
                            errorcode => ['3']
 | 
						|
                    } ]);
 | 
						|
                store_fd([ \%outh ], $out);
 | 
						|
                yield;
 | 
						|
                waitforack($out);
 | 
						|
                %outh = ();
 | 
						|
            }
 | 
						|
            return;
 | 
						|
        }
 | 
						|
        (my $target, my $authtoken, my $fwrev, my $port, my $ba) = get_kvm_params($mpa, $method);
 | 
						|
 | 
						|
        #an http logoff would invalidate the KVM token, so we can't do it here
 | 
						|
        #For the instant in time, banking on the http session timeout to cleanup for us
 | 
						|
        #It may be possible to provide the session id to client so it can logoff when done, but
 | 
						|
        #that would give full AMM access to the KVM client
 | 
						|
        foreach $node (sort (keys %{ $mpahash->{$mpa}->{nodes} })) {
 | 
						|
            my $slot = $mpahash->{$mpa}->{nodes}->{$node};
 | 
						|
            $slot =~ s/-.*//;
 | 
						|
            my @output = ();
 | 
						|
            push(@output, "method:blade");
 | 
						|
            push(@output, "server:$target");
 | 
						|
            push(@output, "authtoken:$authtoken");
 | 
						|
            push(@output, "slot:$slot");
 | 
						|
            push(@output, "fwrev:$fwrev");
 | 
						|
            push(@output, "prefix:$method");
 | 
						|
 | 
						|
            if ($port) {
 | 
						|
                push(@output, "port:$port");
 | 
						|
            }
 | 
						|
 | 
						|
            #if ($ba) { #SECURITY: This exposes AMM credentials, use at own risk
 | 
						|
            #  push(@output,"ba:$ba");
 | 
						|
            #}
 | 
						|
            my %outh;
 | 
						|
            $outh{node}->[0]->{name} = [$node];
 | 
						|
            $outh{node}->[0]->{data} = [];
 | 
						|
            foreach (@output) {
 | 
						|
                (my $tag, my $text) = split /:/, $_, 2;
 | 
						|
                push(@{ $outh{node}->[0]->{data} }, { desc => [$tag], contents => [$text] });
 | 
						|
                store_fd([ \%outh ], $out);
 | 
						|
                yield;
 | 
						|
                waitforack($out);
 | 
						|
                %outh                    = ();
 | 
						|
                $outh{node}->[0]->{name} = [$node];
 | 
						|
                $outh{node}->[0]->{data} = [];
 | 
						|
            }
 | 
						|
 | 
						|
        }
 | 
						|
        return;
 | 
						|
    }
 | 
						|
 | 
						|
    # Handle telnet commands before SNMP
 | 
						|
    if ($command eq "rspconfig") {
 | 
						|
        foreach $node (sort (keys %{ $mpahash->{$mpa}->{nodes} })) {
 | 
						|
            @cfgtext = ();
 | 
						|
            my $slot = $mpahash->{$mpa}->{nodes}->{$node}; #this should preserve '-' in multi-blade configs
 | 
						|
            my $user = $mpahash->{$mpa}->{username};
 | 
						|
            my $pass = $mpahash->{$mpa}->{password};
 | 
						|
            $mptype = $mpahash->{$mpa}->{nodetype}->{$node};
 | 
						|
            my $rc;
 | 
						|
            my $result;
 | 
						|
            if ($mpa eq $node && $mptype && $mptype !~ /^mm|cmm$/) {
 | 
						|
                push @cfgtext, "Hardware type $mptype is not supported. Valid types(mm,cmm).\n";
 | 
						|
                $rc   = 1;
 | 
						|
                $args = [];
 | 
						|
            } elsif ($mpa ne $node && grep /(updateBMC|USERID)/, @exargs) {
 | 
						|
                push @cfgtext, "The option $1 only supported for the CMM";
 | 
						|
                $rc   = 1;
 | 
						|
                $args = [];
 | 
						|
            } else {
 | 
						|
                my $ipmiflag = 0;
 | 
						|
                if ($mpahash->{$mpa}->{ipminodes}->{$node}) { $node .= "--ipmi"; }
 | 
						|
                $result = clicmds($mpa, $user, $pass, $node, $slot, cmds => \@exargs);
 | 
						|
                $node =~ s/--ipmi//;
 | 
						|
                $rc |= @$result[0];
 | 
						|
                $args = @$result[1];
 | 
						|
            }
 | 
						|
 | 
						|
            foreach (@cfgtext) {
 | 
						|
                my %output;
 | 
						|
                (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;
 | 
						|
 | 
						|
                # Don't use the {error} keyword to avoid the auto added 'Error'
 | 
						|
                # in the output especially for part of the nodes failed.
 | 
						|
                $output{node}->[0]->{data}->[0]->{contents}->[0] = $text;
 | 
						|
 | 
						|
                #if ($rc) {
 | 
						|
                #    $output{node}->[0]->{error}->[0]=$text;
 | 
						|
                #} else {
 | 
						|
                #    $output{node}->[0]->{data}->[0]->{contents}->[0]=$text;
 | 
						|
                #}
 | 
						|
 | 
						|
                store_fd([ \%output ], $out);
 | 
						|
                yield;
 | 
						|
                waitforack($out);
 | 
						|
            }
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    if ($command eq "rscan") {
 | 
						|
        foreach $node (sort (keys %{ $mpahash->{$mpa}->{nodes} })) {
 | 
						|
            @cfgtext = ();
 | 
						|
            my $slot = $mpahash->{$mpa}->{nodes}->{$node}; #this should preserve '-' in multi-blade configs
 | 
						|
            my $user = $mpahash->{$mpa}->{username};
 | 
						|
            my $pass = $mpahash->{$mpa}->{password};
 | 
						|
            $mptype = $mpahash->{$mpa}->{nodetype}->{$node};
 | 
						|
            my $rc;
 | 
						|
            my $result;
 | 
						|
            if ($mptype eq "cmm") {
 | 
						|
 | 
						|
                # For the cmm, call the rscanfsp to discover the fsp for ppc blade
 | 
						|
                my @telargs = ("rscanfsp");
 | 
						|
                clicmds($mpa, $user, $pass, $node, $slot, cmds => \@telargs);
 | 
						|
            }
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    # Only telnet commands
 | 
						|
    unless (@$args) {
 | 
						|
        if (($command ne "getmacs") && ($command ne "rbeacon")) {
 | 
						|
            return;
 | 
						|
        }
 | 
						|
    }
 | 
						|
    verbose_message("start deal with SNMP session.");
 | 
						|
    $mpauser = $mpahash->{$mpa}->{username};
 | 
						|
    $mpapass = $mpahash->{$mpa}->{password};
 | 
						|
    $session = new SNMP::Session(
 | 
						|
        DestHost   => $mpa,
 | 
						|
        Version    => '3',
 | 
						|
        SecName    => $mpauser,
 | 
						|
        AuthProto  => 'SHA',
 | 
						|
        AuthPass   => $mpapass,
 | 
						|
        PrivProto  => 'DES',
 | 
						|
        SecLevel   => 'authPriv',
 | 
						|
        UseNumeric => 1,
 | 
						|
        Retries    => 1,           # Give up sooner to make commands go smoother
 | 
						|
        Timeout => 10000000, #Beacon, for one, takes a bit over a second to return
 | 
						|
        PrivPass => $mpapass);
 | 
						|
    if ($session->{ErrorStr}) { return 1, $session->{ErrorStr}; }
 | 
						|
    unless ($session and keys %$session) {
 | 
						|
        my %err = (node => []);
 | 
						|
        foreach (keys %{ $mpahash{$mpa}->{nodes} }) {
 | 
						|
            push(@{ $err{node} }, { name => [$_], error => ["Cannot communicate with $mpa"], errorcode => [1] });
 | 
						|
        }
 | 
						|
        store_fd([ \%err ], $out);
 | 
						|
        yield;
 | 
						|
        waitforack($out);
 | 
						|
        return 1, "General error establishing SNMP communication";
 | 
						|
    }
 | 
						|
    my $tmp = $session->get([ $mmprimoid . ".1" ]);
 | 
						|
    if ($session->{ErrorStr}) { print $session->{ErrorStr}; }
 | 
						|
    $activemm = ($tmp ? 1 : 2);
 | 
						|
    my @outhashes;
 | 
						|
    if ($command eq "reventlog" and isallchassis) {
 | 
						|
 | 
						|
        #Add a dummy node for eventlog to get non-blade events
 | 
						|
        $mpahash{$mpa}->{nodes}->{$mpa} = -1;
 | 
						|
    }
 | 
						|
 | 
						|
    #get new node status
 | 
						|
    my %oldnodestatus = ();    #saves the old node status
 | 
						|
    my @allerrornodes = ();
 | 
						|
    my $check         = 0;
 | 
						|
    my $global_check  = 1;
 | 
						|
    my @entries    = xCAT::TableUtils->get_site_attribute("nodestatus");
 | 
						|
    my $site_entry = $entries[0];
 | 
						|
    if (defined($site_entry)) {
 | 
						|
        if ($site_entry =~ /0|n|N/) { $global_check = 0; }
 | 
						|
    }
 | 
						|
 | 
						|
    #my $sitetab = xCAT::Table->new('site');
 | 
						|
    #if ($sitetab) {
 | 
						|
    #  (my $ref) = $sitetab->getAttribs({key => 'nodestatus'}, 'value');
 | 
						|
    #  if ($ref) {
 | 
						|
    #     if ($ref->{value} =~ /0|n|N/) { $global_check=0; }
 | 
						|
    #  }
 | 
						|
    #}
 | 
						|
 | 
						|
 | 
						|
    if ($command eq 'rpower') {
 | 
						|
        %newnodestatus = ();
 | 
						|
    }
 | 
						|
 | 
						|
    if ($command eq "rvitals") {
 | 
						|
        if ((scalar(@$args) == 1 and $args->[0] eq '') or grep (/all/, @$args)) {
 | 
						|
            $vitals_info = &get_blades_for_mpa($mpa);
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    foreach $node (sort (keys %{ $mpahash->{$mpa}->{nodes} })) {
 | 
						|
        $curn    = $node;
 | 
						|
        $mptype  = $mpahash->{$mpa}->{nodetype}->{$node};
 | 
						|
        $mpatype = $mpahash->{$mpa}->{mpatype};
 | 
						|
        my ($rc, @output) = bladecmd($mpa, $node, $mpahash->{$mpa}->{nodes}->{$node}, $mpahash->{$mpa}->{username}, $mpahash->{$mpa}->{password}, $command, @$args);
 | 
						|
 | 
						|
        #print "output=@output\n";
 | 
						|
        my $no_op = 0;
 | 
						|
        if ($rc) { $no_op = 1; }
 | 
						|
        elsif (@output > 0) {
 | 
						|
            if ($output[0] =~ /$status_noop/) {
 | 
						|
                $no_op = 1;
 | 
						|
                $output[0] =~ s/ $status_noop//; #remove the simbols that meant for use by node statu
 | 
						|
            }
 | 
						|
        }
 | 
						|
 | 
						|
        #print "output=@output\n";
 | 
						|
 | 
						|
        #update the node status
 | 
						|
        if (($check) && ($no_op)) {
 | 
						|
            push(@allerrornodes, $node);
 | 
						|
        }
 | 
						|
 | 
						|
        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;
 | 
						|
                if ($rc) {
 | 
						|
                    $output{node}->[0]->{error}->[0] = $text;
 | 
						|
                } else {
 | 
						|
                    $output{node}->[0]->{data}->[0]->{contents}->[0] = $text;
 | 
						|
                }
 | 
						|
            }
 | 
						|
            store_fd([ \%output ], $out);
 | 
						|
            yield;
 | 
						|
            waitforack($out);
 | 
						|
        }
 | 
						|
        yield;
 | 
						|
    }
 | 
						|
 | 
						|
    if ($command eq 'rpower' and %newnodestatus) {
 | 
						|
        xCAT_monitoring::monitorctrl::setNodeStatusAttributes(\%newnodestatus, 1);
 | 
						|
    }
 | 
						|
 | 
						|
    verbose_message("SNMP session completed.");
 | 
						|
 | 
						|
    #my $msgtoparent=freeze(\@outhashes); # = XMLout(\%output,RootName => 'xcatresponse');
 | 
						|
    #print $out $msgtoparent; #$node.": $_\n";
 | 
						|
}
 | 
						|
 | 
						|
##########################################################################
 | 
						|
# generate hardware tree, called from lstree.
 | 
						|
##########################################################################
 | 
						|
sub genhwtree
 | 
						|
{
 | 
						|
    my $nodelist = shift;    # array ref
 | 
						|
    my $callback = shift;
 | 
						|
    my %hwtree;
 | 
						|
 | 
						|
    # get mm and bladeid
 | 
						|
    my $mptab = xCAT::Table->new('mp');
 | 
						|
    unless ($mptab)
 | 
						|
    {
 | 
						|
        my $rsp = {};
 | 
						|
        $rsp->{data}->[0] = "Can not open mp table.\n";
 | 
						|
        xCAT::MsgUtils->message("E", $rsp, $callback, 1);
 | 
						|
    }
 | 
						|
 | 
						|
    my @entries = $mptab->getAllNodeAttribs([ 'node', 'mpa', 'id' ]);
 | 
						|
 | 
						|
    foreach my $node (@$nodelist)
 | 
						|
    {
 | 
						|
 | 
						|
        # read mp.mpa, mp.id.
 | 
						|
        my $mpent = $mptab->getNodeAttribs($node, [ 'mpa', 'id' ]);
 | 
						|
        if ($mpent)
 | 
						|
        {
 | 
						|
            if ($mpent->{mpa} eq $node)
 | 
						|
            {
 | 
						|
                # it's mm, need to list all blades managed by this mm
 | 
						|
                foreach my $ent (@entries)
 | 
						|
                {
 | 
						|
                    # need to exclude mm if needed.
 | 
						|
                    if ($ent->{mpa} eq $ent->{node})
 | 
						|
                    {
 | 
						|
                        next;
 | 
						|
                    }
 | 
						|
                    elsif ($ent->{mpa} =~ /$node/)
 | 
						|
                    {
 | 
						|
                        $hwtree{$node}{ $ent->{id} } = $ent->{node};
 | 
						|
                    }
 | 
						|
                }
 | 
						|
            }
 | 
						|
            else
 | 
						|
            {
 | 
						|
                # it's blade
 | 
						|
                $hwtree{ $mpent->{mpa} }{ $mpent->{id} } = $node;
 | 
						|
            }
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    return \%hwtree;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
 | 
						|
 | 
						|
 | 
						|
1;
 | 
						|
 | 
						|
 | 
						|
 | 
						|
 | 
						|
 | 
						|
 | 
						|
 | 
						|
 | 
						|
 | 
						|
 | 
						|
 | 
						|
 | 
						|
 | 
						|
 | 
						|
 |