diff --git a/wrapper-scripts/megaclisas-status b/wrapper-scripts/megaclisas-status index af55941..7d716b7 100755 --- a/wrapper-scripts/megaclisas-status +++ b/wrapper-scripts/megaclisas-status @@ -1,5 +1,5 @@ #!/usr/bin/python -# $Id: megaclisas-status,v 1.58 2016/02/11 12:55:49 root Exp root $ +# $Id: megaclisas-status,v 1.62 2016/03/09 14:22:59 root Exp root $ # # Written by Adam Cecile # Modified by Vincent S. Cojot @@ -28,7 +28,8 @@ totaldrivenumber = 0 # Hardcode a max of 16 HBA for now. LDTable must be initialized to accept populating list of LD's into each ctlr's list. LDTable = [ [] * 16 for i in range(16) ] -NestedLDTable = [ [] * 16 for i in range(16) ] +NestedLDTable = [[False for i in range(16)] for j in range(16)] + # Outputs is a 'dict' of all MegaCLI outputs so we can re-use them during loops.. Outputs = {} @@ -90,18 +91,21 @@ for megabin in "MegaCli64","MegaCli","megacli": dbgprint ('Looking for '+str(megabin)+' in PATH next..') megaclipath = which(megabin) if (megaclipath != None): + dbgprint ('Will use MegaCLI from here: '+str(megaclipath)) break - else: - dbgprint ('Found MegaCLI here: '+str(megaclipath)) # Check binary exists (and +x), if not print an error message -if os.path.exists(megaclipath) and os.access(megaclipath, os.X_OK): - pass -else: - if nagiosmode: - print 'UNKNOWN - Cannot find '+megaclipath +if (megaclipath != None): + if os.path.exists(megaclipath) and os.access(megaclipath, os.X_OK): + pass else: - print 'Cannot find ' + megaclipath + 'in your PATH. Please install it.' + 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" in your PATH. Please install it.' sys.exit(3) @@ -212,7 +216,7 @@ def returnBBUStatus(output): def returnArrayNumber(output): i = 0 for line in output: - if re.match(r'^Virtual Drive:.*$',line.strip()): + if re.match(r'^(CacheCade )?Virtual Drive:.*$',line.strip()): i += 1 return i @@ -268,14 +272,16 @@ def returnArrayInfo(output,controllerid,arrayid,arrayindex): properties = '' spandepth = 0 diskperspan = 0 + cachecade_info = 'None' + for line in output: - if re.match(r'^Virtual Drive:.*(Target Id: [0-9]+).*$',line.strip()): + 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() - if re.match(r'^RAID Level.*?:.*$',line.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()) - if re.match(r'^Size.*?:.*$',line.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() @@ -291,16 +297,16 @@ def returnArrayInfo(output,controllerid,arrayid,arrayindex): else: size = line.strip().split(':')[1].strip('GB').strip() size = str(int(round((float(size)))))+'G' - if re.match(r'^Span Depth.*?:.*$',line.strip()): + 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() - if re.match(r'^State.*?:.*$',line.strip()): + elif re.match(r'^State.*?:.*$',line.strip()): state = line.strip().split(':')[1].strip() - if re.match(r'^Strip Size.*?:.*$',line.strip()): + elif re.match(r'^Strip Size.*?:.*$',line.strip()): strpsz = line.strip().split(':')[1].strip() - if re.match(r'^Number Of Drives per span.*:.*$',line.strip()): + elif re.match(r'^Number Of Drives per span.*:.*$',line.strip()): diskperspan = int(line.strip().split(':')[1].strip()) - if re.match(r'^Current Cache Policy.*?:.*$',line.strip()): + elif re.match(r'^Current Cache Policy.*?:.*$',line.strip()): props = line.strip().split(':')[1].strip() if re.search('ReadAdaptive', props): properties += 'ADRA' @@ -312,7 +318,7 @@ def returnArrayInfo(output,controllerid,arrayid,arrayindex): properties += ',WB' if re.match('WriteThrough', props): properties += ',WT' - if re.match(r'^Disk Cache Policy.*?:.*$',line.strip()): + elif re.match(r'^Disk Cache Policy.*?:.*$',line.strip()): props = line.strip().split(':')[1].strip() if re.search('Disabled', props): dskcache = 'Disabled' @@ -320,22 +326,34 @@ def returnArrayInfo(output,controllerid,arrayid,arrayindex): dskcache = 'Default' if re.search('Enabled', props): dskcache = 'Enabled' - if re.match(r'^Ongoing Progresses.*?:.*$',line.strip()): + 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(','): + associated.append('c%du%d' % (controllerid, int(array))) + cachecade_info = "Associated : %s" %(', '.join(associated)) + linenumber += 1 - if operationlinennumber: - inprogress = output[operationlinennumber+1] - else: - inprogress = 'None' + + # 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 (int(spandepth) >= 2): raidtype = str('RAID-' + str(raidlvl) + '0') - NestedLDTable[controllerid][arrayindex] = True + NestedLDTable[controllerid][int(arrayindex)] = True else: if(raidlvl == 1): if(diskperspan > 2): raidtype = str('RAID-10') - NestedLDTable[controllerid][arrayindex] = True + NestedLDTable[controllerid][int(arrayindex)] = True else: raidtype = str('RAID-' + str(raidlvl)) else: @@ -345,7 +363,7 @@ def returnArrayInfo(output,controllerid,arrayid,arrayindex): + ' Span Depth: ' + str(spandepth) + ' Disk Per Span: ' + str(diskperspan) + ' Raid Type: ' + str(raidtype)) - return [id,raidtype,size,strpsz,properties,dskcache,state,targetid,inprogress] + return [id,raidtype,size,strpsz,properties,dskcache,state,targetid,cachecade_info,inprogress] def returnDiskInfo(output,controllerid): arrayid = False @@ -369,7 +387,7 @@ def returnDiskInfo(output,controllerid): if re.match(r'^Span: [0-9]+ - Number of PDs:',line.strip()): spanid = line.split(':')[1].strip() spanid = re.sub(' - Number of PDs.*', '', spanid) - if re.match(r'Enclosure Device ID: .*$',line.strip()): + 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() @@ -380,23 +398,23 @@ def returnDiskInfo(output,controllerid): temp = 'Unk0C' slotid = False lsidid = 'Unknown' - if re.match(r'^Coerced Size: ',line.strip()): + 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) - if re.match(r'^Virtual Drive: [0-9]+.*$',line.strip()): + elif re.match(r'^(CacheCade )?Virtual (Disk|Drive): [0-9]+.*$',line.strip()): arrayindex += 1 arrayid = line.split('(')[0].split(':')[1].strip() - if re.match(r'PD: [0-9]+ Information.*$',line.strip()): + elif re.match(r'PD: [0-9]+ Information.*$',line.strip()): diskid = line.split()[1].strip() - if re.match(r'^Device Id: .*$',line.strip()): + elif re.match(r'^Device Id: .*$',line.strip()): lsidid = line.split(':')[1].strip() - if re.match(r'Slot Number: .*$',line.strip()): + elif re.match(r'Slot Number: .*$',line.strip()): slotid = line.split(':')[1].strip() - if re.match(r'Firmware state: .*$',line.strip()): + elif re.match(r'Firmware state: .*$',line.strip()): fstate = line.split(':')[1].strip() subfstate = re.sub('\(.*', '', fstate) - if re.match(r'Inquiry Data: .*$',line.strip()): + elif re.match(r'Inquiry Data: .*$',line.strip()): model = line.split(':')[1].strip() model = re.sub(' +', ' ', model) # Sub code @@ -404,7 +422,7 @@ def returnDiskInfo(output,controllerid): dtype = re.sub(manuf+' ', '', model) dtype = re.sub(' .*', '', dtype) hwserial = re.sub('.*'+dtype+' *', '', model) - if re.match(r'^Media Type: .*$',line.strip()): + elif re.match(r'^Media Type: .*$',line.strip()): mtype = line.split(':')[1].strip() if mtype == 'Hard Disk Device': mtype = 'HDD' @@ -413,9 +431,9 @@ def returnDiskInfo(output,controllerid): mtype = 'SSD' else: mtype = 'N/A' - if re.match(r'Device Speed: .*$',line.strip()): + elif re.match(r'Device Speed: .*$',line.strip()): speed = line.split(':')[1].strip() - if re.match(r'Drive Temperature :.*$',line.strip()): + elif re.match(r'Drive Temperature :.*$',line.strip()): # 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) @@ -464,29 +482,29 @@ def returnUnconfDiskInfo(output,controllerid): slotid = False lsidid = 'Unknown' - if re.match(r'^Coerced Size: ',line.strip()): + 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) - if re.match(r'^Drive.s position: DiskGroup: [0-9]+,.*$',line.strip()): + elif re.match(r'^Drive.s position: DiskGroup: [0-9]+,.*$',line.strip()): arrayid = line.split(',')[1].split(':')[1].strip() - if re.match(r'^Device Id: [0-9]+.*$',line.strip()): + elif re.match(r'^Device Id: [0-9]+.*$',line.strip()): diskid = line.split(':')[1].strip() - if re.match(r'^Device Id: .*$',line.strip()): + elif re.match(r'^Device Id: .*$',line.strip()): lsidid = line.split(':')[1].strip() - if re.match(r'Slot Number: .*$',line.strip()): + elif re.match(r'Slot Number: .*$',line.strip()): slotid = line.split(':')[1].strip() - if re.match(r'Firmware state: .*$',line.strip()): + elif re.match(r'Firmware state: .*$',line.strip()): fstate = line.split(':')[1].strip() subfstate = re.sub('\(.*', '', fstate) - if re.match(r'Inquiry Data: .*$',line.strip()): + 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) - if re.match(r'^Media Type: .*$',line.strip()): + elif re.match(r'^Media Type: .*$',line.strip()): mtype = line.split(':')[1].strip() if mtype == 'Hard Disk Device': mtype = 'HDD' @@ -495,16 +513,16 @@ def returnUnconfDiskInfo(output,controllerid): mtype = 'SSD' else: mtype = 'N/A' - if re.match(r'Device Speed: .*$',line.strip()): + elif re.match(r'Device Speed: .*$',line.strip()): speed = line.split(':')[1].strip() - if re.match(r'Drive Temperature :.*$',line.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)) - if subfstate == 'Online, Spun Up': + 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 @@ -562,8 +580,7 @@ if printarray: pcipath = '' diskpath = '' i = 0 ; j = 0 - mlen = 0 - rlen = 0 + mlen = 0 ; rlen = 0 ; clen = 0 while controllerid < controllernumber: arrayindex = 0 @@ -578,9 +595,9 @@ if printarray: for line in output: if re.match(r'^Adapter.*Virtual Drive .* Does not Exist',line.strip()): ldid += 1 - if re.match(r'^Virtual Drive:',line.strip()): + elif re.match(r'^(CacheCade )?Virtual Drive:',line.strip()): LDTable[controllerid].append ( ldid ) - NestedLDTable[controllerid].append ( False ) + #NestedLDTable[controllerid][int(arrayindex)] = False ldcount += 1 ldid += 1 @@ -589,10 +606,12 @@ if printarray: cmd = '%s -LDInfo -l%d -a%d -NoLog' % (megaclipath, ldid, controllerid) output = getOutput(cmd) arrayinfo = returnArrayInfo(output, controllerid, ldid, arrayindex) - if ( len(arrayinfo[4]) > mlen): - mlen = len(arrayinfo[4]) 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 @@ -622,11 +641,19 @@ if printarray: else: arrayinfo[7] = 'N/A' - ldfmt = str('%-5s | %-'+str(rlen)+'s | %7s | %7s | %'+str(mlen)+'s | %8s | %8s | %8s | %-12s ') + # 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", "InProgress" ) + print ldfmt % ("-- ID", "Type", "Size", "Strpsz", "Flags", "DskCache", "Status", "OS Path", "CacheCade", "InProgress" ) if not nagiosmode: print ldfmt % ( arrayinfo[0], @@ -637,7 +664,8 @@ if printarray: arrayinfo[5], arrayinfo[6], arrayinfo[7], - arrayinfo[8]) + arrayinfo[8], + arrayinfo[9]) dbgprint("Array state : "+arrayinfo[6]) if not arrayinfo[6] == 'Optimal': bad = True @@ -662,9 +690,7 @@ if totaldrivenumber: print '-- Disk information --' i = 0 - dlen = 0 - mlen = 0 - flen = 0 + dlen = 0 ; mlen = 0 ; flen = 0 controllerid = 0 while controllerid < controllernumber: arrayid = 0 @@ -678,7 +704,7 @@ if totaldrivenumber: arraydisk = returnDiskInfo(output,controllerid) for array in arraydisk: dbgprint('Disk c'+str(controllerid)+'u'+array[0]+'p'+array[1] + ' status : ' + array[5]) - if not array[5] == 'Online' and not array[5] == 'Online, Spun Up': + if array[5] not in [ 'Online', 'Online, Spun Up' ]: bad = True nagiosbaddisk=nagiosbaddisk+1 else: @@ -766,7 +792,7 @@ if totalunconfdrivenumber: 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', 'JBOD','Hotspare, Spun Up','Hotspare, Spun down' ]: + 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: