#!/usr/bin/python # $Id: megaclisas-status,v 1.14 2015/01/14 20:40:09 root Exp $ import os import re import sys import pdb if len(sys.argv) > 2: print 'Usage: megaraid-status [-d]' sys.exit(1) printarray = True printcontroller = True totaldrivenumber = 0 totalunconfdrivenumber = 0 #### pdb.set_trace() if len(sys.argv) > 1: if sys.argv[1] == '-d': printarray = False printcontroller = False else: print 'Usage: megaraid-status [-d]' sys.exit(1) # Get command output def getOutput(cmd): output = os.popen(cmd) lines = [] for line in output: if not re.match(r'^$',line.strip()): lines.append(line.strip()) 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 returnUnconfDriveNumber(output): confdrives = 0 unconfdrives = 0 for line in output: if re.match(r'.*Number of PDs:.*$',line.strip()): confdrives += int(line.split(':')[2].strip()) unconfdrives = totaldrivenumber - confdrives return int(unconfdrives) 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 returnArrayNumber(output): i = 0 for line in output: if re.match(r'^Virtual Drive:.*$',line.strip()): i += 1 return i def returnArrayInfo(output,controllerid,arrayid): id = 'c'+str(controllerid)+'u'+str(arrayid) operationlinennumber = False linenumber = 0 type = '' size = '' state = '' for line in output: if re.match(r'^RAID Level.*?:.*$',line.strip()): type = 'RAID-'+line.strip().split(':')[1].split(',')[0].split('-')[1].strip() # type = 'RAID'+line.strip().split(':')[1] if 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() size = str(int(round((float(size) / 1000))))+'G' # 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' if re.match(r'^State.*?:.*$',line.strip()): state = line.strip().split(':')[1].strip() if re.match(r'^Ongoing Progresses.*?:.*$',line.strip()): operationlinennumber = linenumber linenumber += 1 if operationlinennumber: inprogress = output[operationlinennumber+1] else: inprogress = 'None' return [id,type,size,state,inprogress] def returnDiskInfo(output,controllerid): arrayid = False diskid = False oldenclid = False enclid = False slotid = False lsidid = 'Unknown' table = [] state = 'Offline' model = 'Unknown' speed = '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: state = 'Offline' model = 'Unknown' speed = 'Unknown' temp = 'Unk0C' slotid = False lsidid = 'Unknown' if re.match(r'^Virtual Drive: [0-9]+.*$',line.strip()): arrayid = line.split('(')[0].split(':')[1].strip() if re.match(r'PD: [0-9]+ Information.*$',line.strip()): diskid = line.split()[1].strip() if re.match(r'^Device Id: .*$',line.strip()): lsidid = line.split(':')[1].strip() if re.match(r'Slot Number: .*$',line.strip()): slotid = line.split(':')[1].strip() if re.match(r'Firmware state: .*$',line.strip()): state = line.split(':')[1].strip() if re.match(r'Inquiry Data: .*$',line.strip()): model = line.split(':')[1].strip() model = re.sub(' +', ' ', model) if re.match(r'Device Speed: .*$',line.strip()): speed = line.split(':')[1].strip() if 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) if model != 'Unknown': #### print str(arrayid)+' '+str(diskid)+' '+str(olddiskid) table.append([str(arrayid), str(diskid), state, model, speed, temp, enclid, slotid, lsidid]) return table def returnUnconfDiskInfo(output,controllerid): arrayid = False diskid = False olddiskid = False enclid = False slotid = False lsidid = 'Unknown' table = [] state = 'Offline' model = 'Unknown' speed = '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 state = 'Offline' model = 'Unknown' speed = 'Unknown' temp = 'Unk0C' slotid = False lsidid = 'Unknown' if 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()): diskid = line.split(':')[1].strip() if re.match(r'^Device Id: .*$',line.strip()): lsidid = line.split(':')[1].strip() if re.match(r'Slot Number: .*$',line.strip()): slotid = line.split(':')[1].strip() if re.match(r'Firmware state: .*$',line.strip()): state = line.split(':')[1].strip() if re.match(r'Inquiry Data: .*$',line.strip()): model = line.split(':')[1].strip() model = re.sub(' +', ' ', model) if re.match(r'Device Speed: .*$',line.strip()): speed = line.split(':')[1].strip() if 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) if arrayid == False: ### print str(arrayid)+' '+str(diskid)+' '+str(olddiskid) table.append([state, model, speed, temp, enclid, slotid, lsidid]) return table cmd = 'megacli -adpCount -NoLog' output = getOutput(cmd) controllernumber = returnControllerNumber(output) bad = False # List available controller if printcontroller: print '-- Controller information --' print '-- ID\t| Model' controllerid = 0 while controllerid < controllernumber: cmd = 'megacli -AdpAllInfo -a'+str(controllerid)+' -NoLog' output = getOutput(cmd) controllermodel = returnControllerModel(output) controllerram = returnMemorySize(output) controllerrev = returnFirmwareVersion(output) print 'c'+str(controllerid)+'\t| '+controllermodel+' ('+controllerram+') FW: '+controllerrev controllerid += 1 print '' if printarray: controllerid = 0 print '-- Arrays information --' print '-- ID\t| Type | Size | Status | InProgress' while controllerid < controllernumber: arrayid = 0 cmd = 'megacli -LDInfo -lall -a'+str(controllerid)+' -NoLog' output = getOutput(cmd) arraynumber = returnArrayNumber(output) while arrayid < arraynumber: cmd = 'megacli -LDInfo -l'+str(arrayid)+' -a'+str(controllerid)+' -NoLog' output = getOutput(cmd) arrayinfo = returnArrayInfo(output,controllerid,arrayid) print arrayinfo[0]+'\t| '+arrayinfo[1]+' | '+arrayinfo[2]+' | '+arrayinfo[3]+' | '+arrayinfo[4] if not arrayinfo[3] == 'Optimal': bad = True arrayid += 1 controllerid += 1 print '' controllerid = 0 while controllerid < controllernumber: cmd = 'megacli -PDGetNum -a'+str(controllerid)+' -NoLog' output = getOutput(cmd) totaldrivenumber += returnTotalDriveNumber(output) controllerid += 1 if totaldrivenumber: print '-- Disks information --' print '-- ID\t| Model | Status | Speed | Temperature | Slot ID | LSI Device ID ' controllerid = 0 while controllerid < controllernumber: arrayid = 0 cmd = 'megacli -LDInfo -lall -a'+str(controllerid)+' -NoLog' output = getOutput(cmd) arraynumber = returnArrayNumber(output) #### BUG: -LdPdInfo shows all PD on the adapter, not just for said LD.. #### while arrayid <= arraynumber: cmd = 'megacli -LdPdInfo -a'+str(controllerid)+' -NoLog' output = getOutput(cmd) arraydisk = returnDiskInfo(output,controllerid) for array in arraydisk: print 'c'+str(controllerid)+'u'+array[0]+'p'+array[1]+'\t| '+array[3]+' | '+array[2]+' | '+array[4]+' | '+array[5]+' | ID: \'['+array[6]+':'+array[7]+']\' | '+array[8] controllerid += 1 print '' controllerid = 0 while controllerid < controllernumber: cmd = 'megacli -LdPdInfo -a'+str(controllerid)+' -NoLog' output = getOutput(cmd) totalunconfdrivenumber += returnUnconfDriveNumber(output) controllerid += 1 if totalunconfdrivenumber: print '-- Unconfigured Disks information --' print '-- ID\t| Model | Status | Speed | Temperature | Slot ID | LSI Device ID ' controllerid = 0 while controllerid < controllernumber: arrayid = 0 cmd = 'megacli -LDInfo -lall -a'+str(controllerid)+' -NoLog' output = getOutput(cmd) arraynumber = returnArrayNumber(output) #### BUG: -LdPdInfo shows all PD on the adapter, not just for said LD.. #### while arrayid <= arraynumber: cmd = 'megacli -PDList -a'+str(controllerid)+' -NoLog' output = getOutput(cmd) arraydisk = returnUnconfDiskInfo(output,controllerid) for array in arraydisk: print 'c'+str(controllerid)+'uXpY\t| '+array[1]+' | '+array[0]+' | '+array[2]+' | '+array[3]+' | ID: \'['+array[4]+':'+array[5]+']\' | '+array[6] controllerid += 1 print '' if bad: print '\nThere is at least one disk/array in a NOT OPTIMAL state.' sys.exit(1)