#!/usr/bin/python # $Id: megaclisas-status,v 1.68 2016/10/21 14:38:56 root Exp root $ # # Written by Adam Cecile # Modified by Vincent S. Cojot # import os import re import sys import pdb if sys.platform == 'win32': import ctypes def_megaclipath = "/opt/MegaRAID/MegaCli/MegaCli64" # Non-Nagios Mode defaults nagiosmode = False nagiosoutput='' nagiosgoodarray = 0 nagiosbadarray = 0 nagiosgooddisk = 0 nagiosbaddisk = 0 # Sane defaults printarray = True printcontroller = True debugmode = False notempmode = False totaldrivenumber = 0 # Hardcode a max of 16 HBA and 128 LDs for now. LDTable must be initialized to accept populating list of LD's into each ctlr's list. MaxNumHBA = 16 MaxNumLD = 128 LDTable = [ [] * MaxNumHBA for i in range(MaxNumLD) ] NestedLDTable = [[False for i in range(MaxNumHBA)] for j in range(MaxNumLD)] # Outputs is a 'dict' of all MegaCLI outputs so we can re-use them during loops.. Outputs = {} # Startup def print_usage(): print 'Usage: megaraid-status [--nagios|--debug|--notemp]' # We need root access to query if __name__ == '__main__': try: root_or_admin = os.geteuid() == 0 except AttributeError: root_or_admin = ctypes.windll.shell32.IsUserAnAdmin() !=0 if not root_or_admin: print '# This script requires Administrator privileges' sys.exit(5) # Check command line arguments to enable nagios or not if len(sys.argv) > 2: print_usage() sys.exit(1) if len(sys.argv) > 1: if sys.argv[1] == '--nagios': nagiosmode = True elif sys.argv[1] == '--debug': debugmode = True elif sys.argv[1] == '--notemp': notempmode = True else: print_usage() sys.exit(1) # Functions def dbgprint(msg): if (debugmode): sys.stderr.write ( str('# DEBUG : '+msg+'\n')) def is_exe(fpath): return os.path.isfile(fpath) and os.access(fpath, os.X_OK) def which(program): import os fpath, fname = os.path.split(program) if fpath: if is_exe(program): return program else: # Add some defaults os.environ["PATH"] += os.pathsep + '/opt/MegaRAID/MegaCli' os.environ["PATH"] += os.pathsep + '/ms/dist/hwmgmt/bin' os.environ["PATH"] += os.pathsep + os.path.dirname(os.path.realpath(sys.argv[0])) for path in os.environ["PATH"].split(os.pathsep): dbgprint ('Looking in PATH '+str(path)) path = path.strip('"') exe_file = os.path.join(path, program) if is_exe(exe_file): dbgprint ('Found "'+program+'" at '+exe_file) return exe_file return None # Find MegaCli for megabin in "MegaCli64","MegaCli","megacli", "MegaCli.exe": dbgprint ('Looking for '+str(megabin)+' in PATH next..') megaclipath = which(megabin) if (megaclipath != None): dbgprint ('Will use MegaCLI from here: '+str(megaclipath)) break # Check binary exists (and +x), if not print an error message if (megaclipath != None): if os.path.exists(megaclipath) and os.access(megaclipath, os.X_OK): pass else: if nagiosmode: print 'UNKNOWN - Cannot find '+megaclipath else: print 'Cannot find ' + megaclipath + 'in your PATH. Please install it.' sys.exit(3) else: print 'Cannot find "MegaCli64","MegaCli" or "megacli" or "MegaCli.exe" in your PATH. Please install it.' sys.exit(3) #### pdb.set_trace() def returnWdthFromArrayCol(glarray,idx): maxwdth = 0 for glrow in glarray: if ( len(glrow[idx]) > maxwdth): maxwdth = len(glrow[idx]) return maxwdth # Get command output def getOutput(cmd): lines = [] if ( Outputs.has_key(cmd) ): dbgprint ("Got Cached value: "+str(cmd)) lines = Outputs[cmd] else: dbgprint ("Not a Cached value: "+str(cmd)) output = os.popen(cmd) for line in output: if not re.match(r'^$',line.strip()): lines.append(line.strip()) Outputs[cmd] = lines return lines def returnControllerNumber(output): for line in output: if re.match(r'^Controller Count.*$',line.strip()): return int(line.split(':')[1].strip().strip('.')) def returnTotalDriveNumber(output): for line in output: if re.match(r'Number of Physical Drives on Adapter.*$',line.strip()): return int(line.split(':')[1].strip()) def returnRebuildProgress(output): percent = 0 tmpstr = '' for line in output: if re.match(r'^Rebuild Progress on Device at Enclosure.*, Slot .* Completed ',line.strip()): tmpstr = line.split('Completed')[1].strip() percent = int(tmpstr.split('%')[0].strip()) return percent def returnConfDriveNumber(output): # Count the configured drives confdrives = 0 for line in output: if re.match(r'.*Number of PDs:.*$',line.strip()): confdrives += int(line.split(':')[2].strip()) return int(confdrives) def returnUnConfDriveNumber(output): # Count the configured drives confdrives = 0 for line in output: if re.match(r'^Firmware state: Unconfigured.*$',line.strip()): confdrives += 1 return int(confdrives) def returnControllerModel(output): for line in output: if re.match(r'^Product Name.*$',line.strip()): return line.split(':')[1].strip() def returnMemorySize(output): for line in output: if re.match(r'^Memory Size.*$',line.strip()): return line.split(':')[1].strip() def returnFirmwareVersion(output): for line in output: if re.match(r'^FW Package Build.*$',line.strip()): return line.split(':')[1].strip() def returnROCTemp(output): ROCtemp = '' tmpstr = '' if (notempmode): return str('N/A') else: for line in output: if re.match(r'^ROC temperature :.*$',line.strip()): tmpstr = line.split(':')[1].strip() ROCtemp = re.sub(' +.*$', '', tmpstr) if ( ROCtemp != '' ): return str(str(ROCtemp)+'C') else: return str('N/A') def returnBBUPresence(output): BBU = '' tmpstr = '' for line in output: if re.match(r'^BBU +:.*$',line.strip()): tmpstr = line.split(':')[1].strip() BBU = re.sub(' +.*$', '', tmpstr) break if ( BBU != '' ): return str(BBU) else: return str('N/A') def returnBBUStatus(output): BBUStatus = '' tmpstr = '' for line in output: if re.match(r'^ *Battery Replacement required +:.*$',line.strip()): tmpstr = line.split(':')[1].strip() BBUStatus = re.sub(' +.*$', '', tmpstr) break if ( BBUStatus == 'Yes' ): return str('REPL') else: return str('Good') def returnArrayNumber(output): i = 0 for line in output: if re.match(r'^(CacheCade )?Virtual Drive:.*$',line.strip()): i += 1 return i def returnHBAPCIInfo(output): busprefix = '0000' busid = '' devid = '' functionid = '' pcipath = '' for line in output: if re.match(r'^Bus Number.*:.*$',line.strip()): busid = str(line.strip().split(':')[1].strip()).zfill(2) if re.match(r'^Device Number.*:.*$',line.strip()): devid = str(line.strip().split(':')[1].strip()).zfill(2) if re.match(r'^Function Number.*:.*$',line.strip()): functionid = str(line.strip().split(':')[1].strip()).zfill(1) if busid: pcipath = str(busprefix + ':' + busid + ':' + devid + '.' + functionid) dbgprint("Array PCI path : "+pcipath) return str(pcipath) else: return None def returnHBAInfo(table,output,controllerid): controllermodel = 'Unknown' controllerram = 'Unknown' controllerrev = 'Unknown' controllertemp = '' controllermodel = returnControllerModel(output) controllerram = returnMemorySize(output) controllerrev = returnFirmwareVersion(output) controllertemp = returnROCTemp(output) controllerbbu = returnBBUPresence(output) if controllerbbu == 'Present': cmd = '%s -AdpBbuCmd -GetBbuStatus -a%d -NoLog' % (megaclipath, controllerid) output = getOutput(cmd) controllerbbu = returnBBUStatus(output) if controllermodel != 'Unknown': table.append([ 'c'+str(controllerid), controllermodel, controllerram, str(controllertemp), str(controllerbbu), str('FW: '+controllerrev) ]) def returnArrayInfo(output,controllerid,arrayid,arrayindex): id = 'c'+str(controllerid)+'u'+str(arrayid) operationlinennumber = False linenumber = 0 targetid = '' raidtype = '' raidlvl = '' size = '' state = 'N/A' strpsz = '' dskcache = 'N/A' properties = '' spandepth = 0 diskperspan = 0 cachecade_info = 'None' for line in output: if re.match(r'^(CacheCade )?Virtual Drive:.*(Target Id: [0-9]+).*$',line.strip()): # Extract the SCSI Target ID targetid = line.strip().split(':')[2].split(')')[0].strip() elif re.match(r'^RAID Level.*?:.*$',line.strip()): # Extract the primary raid type, decide on X0 RAID level later when we hit Span Depth raidlvl = int(line.strip().split(':')[1].split(',')[0].split('-')[1].strip()) elif re.match(r'^Size.*?:.*$',line.strip()): # Size reported in MB if re.match(r'^.*MB$',line.strip().split(':')[1]): size = line.strip().split(':')[1].strip('MB').strip() if ( float(size) > 1000): size = str(int(round((float(size) / 1000))))+'G' else: size = str(int(round(float(size))))+'M' # Size reported in TB elif re.match(r'^.*TB$',line.strip().split(':')[1]): size = line.strip().split(':')[1].strip('TB').strip() size = str(int(round((float(size) * 1000))))+'G' # Size reported in GB (default) else: size = line.strip().split(':')[1].strip('GB').strip() size = str(int(round((float(size)))))+'G' elif re.match(r'^Span Depth.*?:.*$',line.strip()): # If Span Depth is greater than 1 chances are we have a RAID 10, 50 or 60 spandepth = line.strip().split(':')[1].strip() elif re.match(r'^State.*?:.*$',line.strip()): state = line.strip().split(':')[1].strip() elif re.match(r'^Strip Size.*?:.*$',line.strip()): strpsz = line.strip().split(':')[1].strip() elif re.match(r'^Number Of Drives per span.*:.*$',line.strip()): diskperspan = int(line.strip().split(':')[1].strip()) elif re.match(r'^Current Cache Policy.*?:.*$',line.strip()): props = line.strip().split(':')[1].strip() if re.search('ReadAdaptive', props): properties += 'ADRA' if re.search('ReadAhead', props): properties += 'RA' if re.match('ReadAheadNone', props): properties += 'NORA' if re.search('WriteBack', props): properties += ',WB' if re.match('WriteThrough', props): properties += ',WT' elif re.match(r'^Disk Cache Policy.*?:.*$',line.strip()): props = line.strip().split(':')[1].strip() if re.search('Disabled', props): dskcache = 'Disabled' if re.search('Disk.s Default', props): dskcache = 'Default' if re.search('Enabled', props): dskcache = 'Enabled' elif re.match(r'^Ongoing Progresses.*?:.*$',line.strip()): operationlinennumber = linenumber elif re.match(r'Cache Cade Type\s*:.*$', line): cachecade_info = "Type : " + line.strip().split(':')[1].strip() elif re.match(r'^Target Id of the Associated LDs\s*:.*$', line): associated=[] for array in line.split(':')[1].strip().split(','): if array.isdigit(): associated.append('c%du%d' % (controllerid, int(array))) if len(associated) >= 1: cachecade_info = "Associated : %s" %(', '.join(associated)) linenumber += 1 # If there was an ongoing operation, find the relevant line in the previous output if operationlinennumber: inprogress = output[operationlinennumber + 1] else: inprogress = 'None' # Compute the RAID level NestedLDTable[int(controllerid)][int(arrayindex)] = False if raidlvl == '': raidtype = str('N/A') else: if (int(spandepth) >= 2): raidtype = str('RAID-' + str(raidlvl) + '0') NestedLDTable[controllerid][int(arrayindex)] = True else: if(raidlvl == 1): if(diskperspan > 2): raidtype = str('RAID-10') NestedLDTable[controllerid][int(arrayindex)] = True else: raidtype = str('RAID-' + str(raidlvl)) else: raidtype = str('RAID-' + str(raidlvl)) dbgprint('RAID Level: ' + str(raidlvl) + ' Span Depth: ' + str(spandepth) + ' Disk Per Span: ' + str(diskperspan) + ' Raid Type: ' + str(raidtype)) return [id,raidtype,size,strpsz,properties,dskcache,state,targetid,cachecade_info,inprogress] def returnDiskInfo(output,controllerid): arrayid = False arrayindex = -1 sarrayid = 'Unknown' diskid = False oldenclid = False enclid = False spanid = False slotid = False lsidid = 'Unknown' table = [] fstate = 'Offline' substate = 'Unknown' model = 'Unknown' speed = 'Unknown' dsize = 'Unknown' temp = 'Unk0C' percent = 0 for line in output: if re.match(r'^Span: [0-9]+ - Number of PDs:',line.strip()): spanid = line.split(':')[1].strip() spanid = re.sub(' - Number of PDs.*', '', spanid) elif re.match(r'Enclosure Device ID: .*$',line.strip()): # We match here early in the analysis so reset the vars if this is a new disk we're reading.. oldenclid = enclid enclid = line.split(':')[1].strip() if oldenclid != False: fstate = 'Offline' model = 'Unknown' speed = 'Unknown' temp = 'Unk0C' slotid = False lsidid = 'Unknown' elif re.match(r'^Coerced Size: ',line.strip()): dsize = line.split(':')[1].strip() dsize = re.sub(' \[.*\.*$', '', dsize) dsize = re.sub('[0-9][0-9] GB', ' Gb', dsize) elif re.match(r'^(CacheCade )?Virtual (Disk|Drive): [0-9]+.*$',line.strip()): arrayindex += 1 arrayid = line.split('(')[0].split(':')[1].strip() elif re.match(r'PD: [0-9]+ Information.*$',line.strip()): diskid = line.split()[1].strip() elif re.match(r'^Device Id: .*$',line.strip()): lsidid = line.split(':')[1].strip() elif re.match(r'Slot Number: .*$',line.strip()): slotid = line.split(':')[1].strip() elif re.match(r'Firmware state: .*$',line.strip()): fstate = line.split(':')[1].strip() subfstate = re.sub('\(.*', '', fstate) dbgprint('Firmware State: '+str(fstate)+' '+str(subfstate)) elif re.match(r'Inquiry Data: .*$',line.strip()): model = line.split(':')[1].strip() model = re.sub(' +', ' ', model) # Sub code manuf = re.sub(' .*', '', model) dtype = re.sub(manuf+' ', '', model) dtype = re.sub(' .*', '', dtype) hwserial = re.sub('.*'+dtype+' *', '', model) elif re.match(r'^Media Type: .*$',line.strip()): mtype = line.split(':')[1].strip() if mtype == 'Hard Disk Device': mtype = 'HDD' else: if mtype == 'Solid State Device': mtype = 'SSD' else: mtype = 'N/A' elif re.match(r'Device Speed: .*$',line.strip()): speed = line.split(':')[1].strip() elif re.match(r'Drive Temperature :.*$',line.strip()): if (notempmode): temp = 'N/A' else: # Drive temp is amongst the last few lines matched, decide here if we add information to the table.. temp = line.split(':')[1].strip() temp = re.sub(' \(.*\)', '', temp) if model != 'Unknown': dbgprint('Disk Info: '+str(arrayid)+' '+str(diskid)+' '+str(oldenclid)) if subfstate == 'Rebuild': cmd = '%s pdrbld -showprog -physdrv\[%s:%s\] -a%d -NoLog' % (megaclipath, enclid, slotid, controllerid) output = getOutput(cmd) percent = returnRebuildProgress(output) fstate = str('Rebuilding (%d%%)' % (percent)) if (( NestedLDTable[controllerid][int(arrayindex)] == True) and (spanid != False)): sarrayid = str(arrayid)+"s"+spanid else: sarrayid = str(arrayid) table.append([sarrayid, str(diskid), mtype, model, dsize, fstate , speed, temp, enclid, slotid, lsidid]) return table def returnUnconfDiskInfo(output,controllerid): arrayid = False diskid = False olddiskid = False enclid = False slotid = False lsidid = 'Unknown' table = [] fstate = 'Offline' substate = 'Unknown' model = 'Unknown' speed = 'Unknown' mtype = 'Unknown' dsize = 'Unknown' temp = 'Unk0C' for line in output: if re.match(r'Enclosure Device ID: .*$',line.strip()): # We match here early in the analysis so reset the vars if this is a new disk we're reading.. oldenclid = enclid enclid = line.split(':')[1].strip() if oldenclid != False: arrayid = False fstate = 'Offline' model = 'Unknown' speed = 'Unknown' temp = 'Unk0C' slotid = False lsidid = 'Unknown' elif re.match(r'^Coerced Size: ',line.strip()): dsize = line.split(':')[1].strip() dsize = re.sub(' \[.*\.*$', '', dsize) dsize = re.sub('[0-9][0-9] GB', ' Gb', dsize) elif re.match(r'^Drive.s position: DiskGroup: [0-9]+,.*$',line.strip()): arrayid = line.split(',')[1].split(':')[1].strip() elif re.match(r'^Device Id: [0-9]+.*$',line.strip()): diskid = line.split(':')[1].strip() elif re.match(r'^Device Id: .*$',line.strip()): lsidid = line.split(':')[1].strip() elif re.match(r'Slot Number: .*$',line.strip()): slotid = line.split(':')[1].strip() elif re.match(r'Firmware state: .*$',line.strip()): fstate = line.split(':')[1].strip() subfstate = re.sub('\(.*', '', fstate) dbgprint('Firmware State: '+str(fstate)+' '+str(subfstate)) elif re.match(r'Inquiry Data: .*$',line.strip()): model = line.split(':')[1].strip() model = re.sub(' +', ' ', model) manuf = re.sub(' .*', '', model) dtype = re.sub(manuf+' ', '', model) dtype = re.sub(' .*', '', dtype) hwserial = re.sub('.*'+dtype+' *', '', model) elif re.match(r'^Media Type: .*$',line.strip()): mtype = line.split(':')[1].strip() if mtype == 'Hard Disk Device': mtype = 'HDD' else: if mtype == 'Solid State Device': mtype = 'SSD' else: mtype = 'N/A' elif re.match(r'Device Speed: .*$',line.strip()): speed = line.split(':')[1].strip() elif re.match(r'Drive Temperature :.*$',line.strip()): temp = line.split(':')[1].strip() temp = re.sub('\(.*\)', '', temp) # Drive temp is amongst the last few lines matched, decide here if we add information to the table.. if arrayid == False: if subfstate == 'Unconfigured': dbgprint('Unconfigured Disk: Arrayid: '+str(arrayid)+' DiskId: '+str(diskid)+' '+str(olddiskid)+' '+str(fstate)) elif subfstate == 'Online, Spun Up': dbgprint('Online Disk: Arrayid: '+str(arrayid)+' DiskId: '+str(diskid)+' '+str(olddiskid)+' '+str(fstate)) table.append([ mtype, model, dsize, fstate, speed, temp, enclid, slotid, lsidid]) return table cmd = '%s -adpCount -NoLog' % (megaclipath) output = getOutput(cmd) controllernumber = returnControllerNumber(output) bad = False # List available controller if printcontroller: if controllernumber: if not nagiosmode: print '-- Controller information --' i = 0 controllerid = 0 mlen = 0 hbainfo = [] while controllerid < controllernumber: cmd = '%s -AdpAllInfo -a%d -NoLog' % (megaclipath, controllerid) output = getOutput(cmd) returnHBAInfo(hbainfo, output,controllerid) controllerid += 1 mlen = returnWdthFromArrayCol(hbainfo,1) controllerid = 0 for hba in hbainfo: hbafmt = str('%-5s | %-'+str(mlen)+'s | %-6s | %-4s | %-6s | %-12s ') # Header if ( i == 0 ): if not nagiosmode: print hbafmt % ("-- ID","H/W Model","RAM","Temp","BBU", "Firmware") if not nagiosmode: print hbafmt % ( hba[0], hba[1], hba[2], hba[3], hba[4], hba[5]) i += 1 if not nagiosmode: print '' else: print "No MegaRAID or PERC adapter detected on your system!" exit(1) if printarray: if not nagiosmode: print '-- Array information --' controllerid = 0 pcipath = '' diskpath = '' i = 0 ; j = 0 mlen = 0 ; rlen = 0 ; clen = 0 while controllerid < controllernumber: arrayindex = 0 cmd = '%s -LDInfo -lall -a%d -NoLog' % (megaclipath, controllerid) output = getOutput(cmd) arraynumber = returnArrayNumber(output) # We need to explore each HBA to look for gaps in LD's ldid = 0 ; ldcount = 0 while ldcount < arraynumber: cmd = '%s -LDInfo -l%d -a%d -NoLog' % (megaclipath, ldid, controllerid) output = getOutput(cmd) for line in output: if re.match(r'^Adapter.*Virtual Drive .* Does not Exist',line.strip()): ldid += 1 elif re.match(r'^(CacheCade )?Virtual Drive:',line.strip()): LDTable[controllerid].append ( ldid ) #NestedLDTable[controllerid][int(arrayindex)] = False ldcount += 1 ldid += 1 while arrayindex < arraynumber: ldid = LDTable[controllerid][arrayindex] cmd = '%s -LDInfo -l%d -a%d -NoLog' % (megaclipath, ldid, controllerid) output = getOutput(cmd) arrayinfo = returnArrayInfo(output, controllerid, ldid, arrayindex) if ( len(arrayinfo[1]) > rlen): rlen = len(arrayinfo[1]) if ( len(arrayinfo[4]) > mlen): mlen = len(arrayinfo[4]) if ( len(arrayinfo[8]) > clen): clen = len(arrayinfo[8]) arrayindex += 1 controllerid += 1 controllerid = 0 while controllerid < controllernumber: arrayindex = 0 cmd = '%s -AdpGetPciInfo -a%d -NoLog' % (megaclipath, controllerid) output = getOutput(cmd) pcipath = returnHBAPCIInfo(output) cmd = '%s -LDInfo -lall -a%d -NoLog' % (megaclipath, controllerid) output = getOutput(cmd) arraynumber = returnArrayNumber(output) while arrayindex < arraynumber: ldid = LDTable[controllerid][arrayindex] cmd = '%s -LDInfo -l%d -a%d -NoLog' % (megaclipath, ldid, controllerid) output = getOutput(cmd) arrayinfo = returnArrayInfo(output,controllerid, ldid, arrayindex) if pcipath: diskprefix = str('/dev/disk/by-path/pci-' + pcipath + '-scsi-0:') for j in range (8): diskpath = diskprefix + str(j) + ':' + str(arrayinfo[7]) + ':0' if os.path.exists(diskpath): arrayinfo[7] = os.path.realpath(diskpath) else: arrayinfo[7] = 'N/A' # Pad the string length, just to make sure it's aligned with the headers... if (rlen < len("Type")): rlen = len("Type") if (mlen < len("Flags")): mlen = len("Flags") if (clen < len("CacheCade")): clen = len("CacheCade") ldfmt = str('%-5s | %-'+str(rlen)+'s | %7s | %7s | %'+str(mlen)+'s | %8s | %8s | %8s | %-'+str(clen)+'s |%-12s ') # Header if ( i == 0 ): if not nagiosmode: print ldfmt % ("-- ID", "Type", "Size", "Strpsz", "Flags", "DskCache", "Status", "OS Path", "CacheCade", "InProgress" ) if not nagiosmode: print ldfmt % ( arrayinfo[0], arrayinfo[1], arrayinfo[2], arrayinfo[3], arrayinfo[4], arrayinfo[5], arrayinfo[6], arrayinfo[7], arrayinfo[8], arrayinfo[9]) dbgprint("Array state : "+arrayinfo[6]) if arrayinfo[6] not in [ 'Optimal', 'N/A' ]: bad = True nagiosbadarray=nagiosbadarray+1 else: nagiosgoodarray=nagiosgoodarray+1 arrayindex += 1 i += 1 controllerid += 1 if not nagiosmode: print '' controllerid = 0 while controllerid < controllernumber: cmd = '%s -PDGetNum -a%d -NoLog' % (megaclipath, controllerid) output = getOutput(cmd) totaldrivenumber += returnTotalDriveNumber(output) controllerid += 1 if totaldrivenumber: if not nagiosmode: print '-- Disk information --' i = 0 dlen = 0 ; mlen = 0 ; flen = 0 controllerid = 0 while controllerid < controllernumber: arrayid = 0 cmd = '%s -LDInfo -lall -a%d -NoLog' % (megaclipath, controllerid) output = getOutput(cmd) arraynumber = returnArrayNumber(output) #### BUG: -LdPdInfo shows all PD on the adapter, not just for said LD.. #### while arrayid <= arraynumber: cmd = '%s -LdPdInfo -a%d -NoLog' % (megaclipath, controllerid) output = getOutput(cmd) arraydisk = returnDiskInfo(output,controllerid) for array in arraydisk: dbgprint('Disk c'+str(controllerid)+'u'+array[0]+'p'+array[1] + ' status : ' + array[5]) if array[5] not in [ 'Online', 'Online, Spun Up' ]: bad = True nagiosbaddisk=nagiosbaddisk+1 else: nagiosgooddisk=nagiosgooddisk+1 if ( returnWdthFromArrayCol(arraydisk,0) > dlen): dlen = returnWdthFromArrayCol(arraydisk,0) if ( returnWdthFromArrayCol(arraydisk,3) > mlen): mlen = returnWdthFromArrayCol(arraydisk,3) if ( returnWdthFromArrayCol(arraydisk,5) > flen): flen = returnWdthFromArrayCol(arraydisk,5) controllerid += 1 controllerid = 0 while controllerid < controllernumber: arrayid = 0 cmd = '%s -LDInfo -lall -a%d -NoLog' % (megaclipath, controllerid) output = getOutput(cmd) arraynumber = returnArrayNumber(output) #### BUG: -LdPdInfo shows all PD on the adapter, not just for said LD.. #### while arrayid <= arraynumber: cmd = '%s -LdPdInfo -a%d -NoLog' % (megaclipath, controllerid) output = getOutput(cmd) arraydisk = returnDiskInfo(output,controllerid) # Adjust print format with width computed above drvfmt = "%-"+str(dlen+5)+"s | %-4s | %-"+str(mlen)+"s | %-8s | %-"+str(flen)+"s | %-8s | %-4s | %-8s | %-8s" for array in arraydisk: # Header if ( i == 0 ): if not nagiosmode: print drvfmt % ( "-- ID", "Type", "Drive Model", "Size", "Status", "Speed", "Temp", "Slot ID", "LSI Device ID") # Drive information if not nagiosmode: print drvfmt % ( str('c'+str(controllerid)+'u'+array[0]+'p'+array[1]), # c0p0 array[2], # HDD/SDD array[3], # Model Information (Variable len) array[4], # Size array[5], # Status (Variable len) array[6], # Speed array[7], # Temp str('['+array[8]+':'+array[9]+']'), # Slot ID array[10]) # LSI ID i = i + 1 controllerid += 1 if not nagiosmode: print '' controllerid = 0 totalconfdrivenumber = 0 totalunconfdrivenumber = 0 totaldrivenumber = 0 while controllerid < controllernumber: cmd = '%s -LdPdInfo -a%d -NoLog' % (megaclipath, controllerid) output = getOutput(cmd) totalconfdrivenumber += returnConfDriveNumber(output) cmd = '%s -PDGetNum -a%d -NoLog' % (megaclipath, controllerid) output = getOutput(cmd) totaldrivenumber += returnTotalDriveNumber(output) cmd = '%s -PDList -a%d -NoLog' % (megaclipath, controllerid) output = getOutput(cmd) totalunconfdrivenumber += returnUnConfDriveNumber(output) controllerid += 1 dbgprint('Total Drives in system : ' + str(totaldrivenumber)) dbgprint('Total Configured Drives : ' + str(totalconfdrivenumber)) dbgprint('Total Unconfigured Drives : ' + str(totalunconfdrivenumber)) if totalunconfdrivenumber: if not nagiosmode: print '-- Unconfigured Disk information --' controllerid = 0 while controllerid < controllernumber: arrayid = 0 cmd = '%s -LDInfo -lall -a%d -NoLog' % (megaclipath, controllerid) output = getOutput(cmd) arraynumber = returnArrayNumber(output) #### BUG: -LdPdInfo shows all PD on the adapter, not just for given LD.. #### while arrayid <= arraynumber: cmd = '%s -PDList -a%d -NoLog' % (megaclipath, controllerid) output = getOutput(cmd) arraydisk = returnUnconfDiskInfo(output,controllerid) for array in arraydisk: dbgprint('Disk c'+str(controllerid)+'uXpY status : ' + array[3]) if array[3] not in [ 'Online', 'Unconfigured(good), Spun Up', 'Unconfigured(good), Spun down', 'JBOD','Hotspare, Spun Up','Hotspare, Spun down' ]: bad = True nagiosbaddisk=nagiosbaddisk+1 else: nagiosgooddisk=nagiosgooddisk+1 mlen = returnWdthFromArrayCol(arraydisk,1) flen = returnWdthFromArrayCol(arraydisk,3) # Adjust print format with widths computed above drvfmt = "%-7s | %-4s | %-"+str(mlen)+"s | %-8s | %-"+str(flen+2)+"s | %-8s | %-4s | %-8s | %-8s" i = 0 for array in arraydisk: # Header if ( i == 0 ): if not nagiosmode: print drvfmt % ( "-- ID", "Type", "Drive Model", "Size", "Status", "Speed", "Temp", "Slot ID", "LSI Device ID") # Drive information if not nagiosmode: print drvfmt % ( str('c'+str(controllerid)+'uXpY'), # cXpY array[0], # HDD/SDD array[1], # Model Information (Variable len) array[2], # Size array[3], # Status (Variable len) array[4], # Speed array[5], # Temp str('['+array[6]+':'+array[7]+']'), # Slot ID array[8]) # LSI ID i = i + 1 controllerid += 1 if not nagiosmode: print '' if nagiosmode: if bad: print 'RAID ERROR - Arrays: OK:'+str(nagiosgoodarray)+' Bad:'+str(nagiosbadarray)+' - Disks: OK:'+str(nagiosgooddisk)+' Bad:'+str(nagiosbaddisk) sys.exit(2) else: print 'RAID OK - Arrays: OK:'+str(nagiosgoodarray)+' Bad:'+str(nagiosbadarray)+' - Disks: OK:'+str(nagiosgooddisk)+' Bad:'+str(nagiosbaddisk) else: if bad: print '\nThere is at least one disk/array in a NOT OPTIMAL state.' sys.exit(1)