hwraid/wrapper-scripts/aacraid-status

309 lines
11 KiB
Plaintext
Raw Normal View History

2013-08-14 22:56:33 +02:00
#!/usr/bin/python
import os
import re
import sys
from argparse import ArgumentParser
2013-08-14 22:56:33 +02:00
# Argument parser
# My own ArgumentParser with single-line stdout output and unknown state Nagios retcode
class NagiosArgumentParser(ArgumentParser):
2016-09-19 10:58:00 +02:00
def error(self, message):
sys.stdout.write('UNKNOWN: Bad arguments (see --help): %s\n' % message)
sys.exit(3)
2013-08-14 22:56:33 +02:00
def parse_args():
2016-09-19 10:58:00 +02:00
parser = NagiosArgumentParser(description='Adaptec AACRAID status script')
parser.add_argument('-d', '--disks-only', action="store_true", help='Only disply disk statuses')
parser.add_argument('-n', '--nagios', action="store_true", help='Use Nagios-like output and return code')
return parser.parse_args()
2013-08-14 22:56:33 +02:00
def which(program):
2016-09-19 10:58:00 +02:00
fpath, fname = os.path.split(program)
if fpath:
if is_exe(program):
return program
else:
# Add some defaults
os.environ["PATH"] += os.pathsep + '/usr/StorMan/arcconf'
os.environ["PATH"] += os.pathsep + os.path.dirname(os.path.realpath(sys.argv[0]))
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
2013-08-14 22:56:33 +02:00
def is_exe(fpath):
2016-09-19 10:58:00 +02:00
return os.path.isfile(fpath) and os.access(fpath, os.X_OK)
2013-08-14 22:56:33 +02:00
# Get command output
def getOutput(cmd):
output = os.popen('%s 2>%s' % (cmd, os.devnull))
2013-08-14 22:56:33 +02:00
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'^Controllers found: [0-9]+$',line.strip()):
return int(line.split(':')[1].strip().strip('.'))
def returnControllerModel(output):
for line in output:
if re.match(r'^Controller Model.*$',line.strip()):
return line.split(':')[1].strip()
def returnControllerStatus(output):
for line in output:
if re.match(r'^Controller Status.*$',line.strip()):
return line.split(':')[1].strip()
def returnArrayIds(output):
ids = []
for line in output:
if re.match(r'^Logical device number [0-9]+$',line.strip()):
ids.append(line.strip('Logical device number').strip())
return ids
def returnArrayInfo(output):
members = []
for line in output:
# RAID level may be either N or Simple_Volume
# (a disk connected to the card, not hotspare, not part of any array)
if re.match(r'^RAID level\s+: .+$',line.strip()):
type = line.split(':')[1].strip()
if re.match(r'^Status of logical device\s+: .*$',line.strip()):
status = line.split(':')[1].strip()
if re.match(r'^Size\s+: [0-9]+ MB$',line.strip()):
size = str(int(line.strip('MB').split(':')[1].strip()) / 1000)
if re.match(r'^(Group\s[0-9]+,\s)?Segment [0-9]+\s+: .*$',line.strip()):
splitter = re.compile('(\(.*\))')
# The line can be either
# Segment 0 : Present (Controller:1,Enclosure:0,Slot:0) JPW9J0N00RWMUV
# Or
# Segment 0 : Present (Controller:1,Channel:0,Device:0) S13PJ1CQ719255
# Or
# Segment 0 : Present (Controller:1,Connector:1,Device:2) 9QJ7D0MJ
line = re.sub('Controller:','',line)
line = re.sub('(Channel|Enclosure|Connector):','',line)
line = re.sub('(Device|Slot):','',line)
line = line.split(':')[1]
if re.match(r'^ Missing',line):
members.append('?,?')
else:
members.append(splitter.split(line)[1].strip('(').strip(')'))
if re.match(r'^Group [0-9], Segment [0-9]+\s+: .*$',line.strip()):
splitter = re.compile('(\(.*\))')
line = line.split(':')[1]
if re.match(r'^ Missing',line):
members.append('?,?')
else:
members.append(splitter.split(line)[1].strip('(').strip(')'))
return [type,status,size,members]
def returnControllerTasks(output):
arrayid = False
type = False
state = False
tasks = []
for line in output:
if re.match(r'^Logical device\s+: [0-9]+$',line.strip()):
arrayid = line.split(':')[1].strip()
if re.match(r'^Current operation\s+: .*$',line.strip()):
type = line.split(':')[1].strip()
if re.match(r'^Percentage complete\s+: [0-9]+$',line.strip()):
state = line.split(':')[1].strip()
if arrayid != False and type != False and state != False:
tasks.append([arrayid,type,state])
arrayid = False
type = False
state = False
return tasks
def returnDisksInfo(output,controllerid):
diskid = False
vendor = False
model = False
state = False
disks = []
for line in output:
if re.match(r'^Reported Channel,Device(\(T:L\))?\s+: [0-9]+,[0-9]+(\([0-9]+:[0-9]+\))?$',line.strip()):
diskid = re.split('\s:\s',line)[1].strip()
diskid = re.sub('\(.*\)','',diskid)
diskid = str(controllerid)+','+diskid
if re.match(r'^State\s+:.*$',line.strip()):
2013-08-14 22:56:33 +02:00
state = line.split(':')[1].strip()
if re.match(r'^Vendor\s+:.*$',line.strip()):
2013-08-14 22:56:33 +02:00
vendor = line.split(':')[1].strip()
if re.match(r'^Model\s+:.*$',line.strip()):
2013-08-14 22:56:33 +02:00
model = line.split(':')[1].strip()
if diskid != False and vendor != False and model != False and state != False:
disks.append([diskid,state,vendor,model])
diskid = False
vendor = False
model = False
state = False
return disks
config = parse_args()
if config.disks_only:
2016-09-19 10:58:00 +02:00
printarray = False
printcontroller = False
else:
2016-09-19 10:58:00 +02:00
printarray = True
printcontroller = True
nagiosoutput=''
nagiosgoodctrl = 0
nagiosbadctrl = 0
nagiosctrlbadarray = 0
nagiosgoodarray = 0
nagiosbadarray = 0
nagiosgooddisk = 0
nagiosbaddisk = 0
bad = False
# Find arcconf
for arcconfbin in "arcconf","arcconf.exe":
2016-09-19 10:58:00 +02:00
arcconfpath = which(arcconfbin)
if (arcconfpath != None):
break
# Check binary exists (and +x), if not print an error message
if (arcconfpath != None):
2016-09-19 10:58:00 +02:00
if is_exe(arcconfpath):
pass
else:
if config.nagios:
print 'UNKNOWN - Cannot find '+arcconfpath
else:
print 'Cannot find ' + arcconfpath + 'in your PATH. Please install it.'
sys.exit(3)
else:
2016-09-19 10:58:00 +02:00
print 'Cannot find "arcconf, "arcconf.exe" in your PATH. Please install it.'
sys.exit(3)
cmd = '"%s" GETVERSION' % arcconfpath
2013-08-14 22:56:33 +02:00
output = getOutput(cmd)
controllernumber = returnControllerNumber(output)
# List controllers
if printcontroller:
2016-09-19 10:58:22 +02:00
if not config.nagios:
print '-- Controller informations --'
print '-- ID | Model | Status'
2013-08-14 22:56:33 +02:00
controllerid = 1
while controllerid <= controllernumber:
cmd = '"%s" GETCONFIG %d' % (arcconfpath, controllerid)
2013-08-14 22:56:33 +02:00
output = getOutput(cmd)
controllermodel = returnControllerModel(output)
controllerstatus = returnControllerStatus(output)
if controllerstatus != 'Optimal':
bad = True
2016-09-19 10:58:22 +02:00
nagiosbadctrl += 1
else:
nagiosgoodctrl += 1
if not config.nagios:
print 'c'+str(controllerid-1)+' | '+controllermodel+' | '+controllerstatus
2013-08-14 22:56:33 +02:00
controllerid += 1
2016-09-19 10:58:22 +02:00
if not config.nagios:
print ''
2013-08-14 22:56:33 +02:00
# List arrays
if printarray:
controllerid = 1
2016-09-19 10:58:22 +02:00
if not config.nagios:
print '-- Arrays informations --'
print '-- ID | Type | Size | Status | Task | Progress'
2013-08-14 22:56:33 +02:00
while controllerid <= controllernumber:
arrayid = 0
cmd = '"%s" GETCONFIG %s' % (arcconfpath, controllerid)
2013-08-14 22:56:33 +02:00
output = getOutput(cmd)
arrayids = returnArrayIds(output)
for arrayid in arrayids:
cmd = '"%s" GETCONFIG %s LD %s' % (arcconfpath, controllerid, arrayid)
2013-08-14 22:56:33 +02:00
output = getOutput(cmd)
arrayinfo = returnArrayInfo(output)
if arrayinfo[1] != 'Optimal':
2016-09-19 10:58:22 +02:00
nagiosbadarray += 1
2013-08-14 22:56:33 +02:00
bad = True
2016-09-19 10:58:22 +02:00
else:
nagiosgoodarray += 1
cmd = '"%s" GETSTATUS %s', (arcconfpath, controllerid)
2013-08-14 22:56:33 +02:00
output = getOutput(cmd)
tasksinfo = returnControllerTasks(output)
done = False
# Usually it should return either [0-9] or Simple_Volume but...
# It can also return "6 Reed-Solomon" so we need to handle this too...
# So let's match [0-9] followed by a space or EOL.
if re.match('^[0-9]+(\s|$)',arrayinfo[0]):
raidtype = re.sub('^','RAID',arrayinfo[0])
else:
raidtype = arrayinfo[0]
for tasks in tasksinfo:
if int(tasks[0]) == int(arrayid):
2016-09-19 10:58:22 +02:00
if not config.nagios:
print 'c'+str(controllerid-1)+'u'+str(arrayid)+' | '+raidtype+' | '+arrayinfo[2]+'G | '+arrayinfo[1]+' | '+tasks[1]+' | '+tasks[2]+'%'
2013-08-14 22:56:33 +02:00
done = True
break
if done == False:
2016-09-19 10:58:22 +02:00
if not config.nagios:
print 'c'+str(controllerid-1)+'u'+str(arrayid)+' | '+raidtype+' | '+arrayinfo[2]+'G | '+arrayinfo[1]
2013-08-14 22:56:33 +02:00
controllerid += 1
2016-09-19 10:58:22 +02:00
if not config.nagios:
print ''
2013-08-14 22:56:33 +02:00
# List disks
controllerid = 1
2016-09-19 10:58:22 +02:00
if not config.nagios:
print '-- Disks informations'
print '-- ID | Model | Status'
2013-08-14 22:56:33 +02:00
while controllerid <= controllernumber:
arrayid = 0
cmd = '"%s" GETCONFIG %s' % (arcconfpath, controllerid)
2013-08-14 22:56:33 +02:00
output = getOutput(cmd)
arrayids = returnArrayIds(output)
for arrayid in arrayids:
cmd = '"%s" GETCONFIG %s LD %s' % (arcconfpath, controllerid, arrayid)
2013-08-14 22:56:33 +02:00
output = getOutput(cmd)
arrayinfo = returnArrayInfo(output)
cmd = '"%s" GETCONFIG %d PD' % (arcconfpath, controllerid)
2013-08-14 22:56:33 +02:00
output = getOutput(cmd)
diskinfo = returnDisksInfo(output,controllerid)
for member in arrayinfo[3]:
i = 0
for disk in diskinfo:
2016-09-19 10:58:22 +02:00
if disk[1] != 'Online' and disk[1] != 'Hot Spare' and disk[1] != 'Ready' and disk[1] != 'Global Hot-Spare':
2013-08-14 22:56:33 +02:00
bad = True
2016-09-19 10:58:22 +02:00
nagiosbaddisk += 1
else:
nagiosgooddisk += 1
2013-08-14 22:56:33 +02:00
if disk[0] == member:
2016-09-19 10:58:22 +02:00
if not config.nagios:
print 'c'+str(controllerid-1)+'u'+str(arrayid)+'d'+str(i)+' | '+disk[2]+' '+disk[3]+' | '+disk[1]
# Some disks may not be attached to an array (ie: global hot spare)
else:
if not config.nagios:
print 'c'+str(controllerid-1)+'uX'+'d'+str(i)+' | '+disk[2]+' '+disk[3]+' | '+disk[1]
2013-08-14 22:56:33 +02:00
i += 1
controllerid += 1
2016-09-19 10:58:22 +02:00
if config.nagios:
if bad:
print('RAID ERROR - Controllers OK:%d Bad:%d - Arrays OK:%d Bad:%d - Disks OK:%d Bad:%d' % (nagiosgoodctrl, nagiosbadctrl, nagiosgoodarray, nagiosbadarray, nagiosgooddisk, nagiosbaddisk))
sys.exit(2)
else:
print('RAID OK - Controllers OK:%d Bad:%d - Arrays OK:%d Bad:%d - Disks OK:%d Bad:%d' % (nagiosgoodctrl, nagiosbadctrl, nagiosgoodarray, nagiosbadarray, nagiosgooddisk, nagiosbaddisk))
else:
if bad:
print '\nThere is at least one disk/array in a NOT OPTIMAL state.'
print '\nUse "arcconf GETCONFIG [1-9]" to get details.'
sys.exit(1)