hwraid/wrapper-scripts/megaclisas-status
2015-09-23 16:21:32 -04:00

454 lines
14 KiB
Python
Executable File

#!/usr/bin/python
# $Id: megaclisas-status,v 1.19 2015/03/27 03:06:04 root Exp $
import os
import re
import sys
import pdb
# Sane defaults
tabwdth = 4
#megaclipath = "/opt/MegaRAID/MegaCli/MegaCli64"
def which(program):
import os
def is_exe(fpath):
return os.path.isfile(fpath) and os.access(fpath, os.X_OK)
fpath, fname = os.path.split(program)
if fpath:
if is_exe(program):
return program
else:
for path in os.environ["PATH"].split(os.pathsep):
path = path.strip('"')
exe_file = os.path.join(path, program)
if is_exe(exe_file):
return exe_file
return None
# Find MegaCli
if which("MegaCli64") == None:
if which("MegaCli") == None:
if is_exe("/opt/MegaRAID/MegaCli/MegaCli64"):
megaclipath = "/opt/MegaRAID/MegaCli/MegaCli64"
else:
if is_exe("/opt/MegaRAID/MegaCli/MegaCli"):
megaclipath = "/opt/MegaRAID/MegaCli/MegaCli"
else:
megaclipath = str(which("MegaCli"))
else:
megaclipath = str(which("MegaCli64"))
# Adding a quick check to see if we're root, because on most cards I've tried this on
# We need root access to query
if __name__ == '__main__':
if os.getenv('USER') != 'root':
print 'You can only run this script as root or with sudo, sucks I know. Blame the RAID card'
sys.exit(5)
# Check command line arguments to enable nagios or not
if len(sys.argv) > 2:
print 'Usage: megaraid-status [-d]'
sys.exit(1)
# Check binary exists (and +x), if not print an error message
# or return UNKNOWN nagios error code
if os.path.exists(megaclipath) and os.access(megaclipath, os.X_OK):
pass
else:
print 'Cannot find ' + megaclipath + '. Please install it.'
sys.exit(3)
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 = []
fstate = 'Offline'
model = 'Unknown'
speed = '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:
fstate = 'Offline'
model = 'Unknown'
speed = 'Unknown'
temp = 'Unk0C'
slotid = False
lsidid = 'Unknown'
if 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()):
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()):
fstate = line.split(':')[1].strip()
if 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)
if 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'
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), 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'
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'
if 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()):
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()):
fstate = line.split(':')[1].strip()
subfstate = re.sub('\(.*', '', fstate)
if 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()):
mtype = line.split(':')[1].strip()
if mtype == 'Hard Disk Device':
mtype = 'HDD'
else:
if mtype == 'Solid State Device':
mtype = 'SSD'
else:
mtype = 'N/A'
if re.match(r'Device Speed: .*$',line.strip()):
speed = line.split(':')[1].strip()
if 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':
### print str(arrayid)+' '+str(diskid)+' '+str(olddiskid)+' '+str(state)
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:
print '-- Controller information --'
print '-- ID\t| Model'
controllerid = 0
while controllerid < controllernumber:
cmd = '%s -AdpAllInfo -a%d -NoLog' % (megaclipath, controllerid)
output = getOutput(cmd)
controllermodel = returnControllerModel(output)
controllerram = returnMemorySize(output)
controllerrev = returnFirmwareVersion(output)
print 'c'+str(controllerid)+'\t| '+controllermodel+' ('+controllerram+') FW: '+controllerrev
controllerid += 1
print ''
else:
print "No MegaRAID or PERC adapter detected on your system!"
exit(1)
if printarray:
controllerid = 0
print '-- Arrays information --'
print '-- ID\t| Type | Size | Status | InProgress'
while controllerid < controllernumber:
arrayid = 0
cmd = '%s -LDInfo -lall -a%d -NoLog' % (megaclipath, controllerid)
output = getOutput(cmd)
arraynumber = returnArrayNumber(output)
while arrayid < arraynumber:
cmd = '%s -LDInfo -l%d -a%d -NoLog' % (megaclipath, arrayid, controllerid)
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 = '%s -PDGetNum -a%d -NoLog' % (megaclipath, controllerid)
output = getOutput(cmd)
totaldrivenumber += returnTotalDriveNumber(output)
controllerid += 1
if totaldrivenumber:
print '-- Disks information --'
# print '-- ID\t| Type\t| Model\t\t\t\t\t| Size\t\t| Status\t\t| Speed\t\t| Temp\t| Slot ID\t| LSI Device ID '.expandtabs(tabwdth)
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)
mlen = 0
flen = 0
for array in arraydisk:
if( len(array[3]) >= mlen):
mlen = len(array[3])
if( len(array[5]) >= flen):
flen = len(array[5])
# Adjust print format with widths computed above
drvfmt = "%-8s | %-4s | %-"+str(mlen)+"s | %-8s | %-"+str(flen)+"s | %-8s | %-4s | %-8s | %-8s"
i = 0
for array in arraydisk:
# Header
if ( i == 0 ):
print drvfmt % (
"-- ID", "Type", "Model", "Size", "Status", "Speed", "Temp", "Slot ID", "LSI Device ID")
# Drive information
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
print ''
controllerid = 0
while controllerid < controllernumber:
cmd = '%s -LdPdInfo -a%d -NoLog' % (megaclipath, controllerid)
output = getOutput(cmd)
totalunconfdrivenumber += returnUnconfDriveNumber(output)
controllerid += 1
if totalunconfdrivenumber:
print '-- Unconfigured Disks 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 said LD..
#### while arrayid <= arraynumber:
cmd = '%s -PDList -a%d -NoLog' % (megaclipath, controllerid)
output = getOutput(cmd)
arraydisk = returnUnconfDiskInfo(output,controllerid)
mlen = 0
flen = 0
for array in arraydisk:
if( len(array[3]) >= mlen):
mlen = len(array[3])
if( len(array[5]) >= flen):
flen = len(array[5])
# Adjust print format with widths computed above
drvfmt = "%-8s | %-4s | %-"+str(mlen)+"s | %-8s | %-"+str(flen)+"s | %-8s | %-4s | %-8s | %-8s"
i = 0
for array in arraydisk:
# Header
if ( i == 0 ):
print drvfmt % (
"-- ID", "Type", "Model", "Size", "Status", "Speed", "Temp", "Slot ID", "LSI Device ID")
# Drive information
print drvfmt % (
str('c'+str(controllerid)+'uXpY\t| '+array[0]), # cXpY
array[1], # HDD/SDD
array[2], # Model Information (Variable len)
array[3], # Size
array[4], # Status (Variable len)
str('['+array[5]+':'+array[6]+']'), # Slot ID
array[7]) # LSI ID
i = i + 1
controllerid += 1
print ''
if bad:
print '\nThere is at least one disk/array in a NOT OPTIMAL state.'
sys.exit(1)