| Current File : //etc/node_exporter/scripts/megacli |
#!/usr/bin/python
import subprocess
import re
import json
def yesno(state):
states = {
"No": 0
}
return states.get(state, 1)
def state2int(state):
#put remaining states here
states = {
"Online, Spun Up": 255
}
return states.get(state, 0)
def tobytes(inp):
suffix=['kb','mb','gb','tb']
i=0;
out=None
inp=inp.strip().lower()
while i < len(suffix):
if re.search(suffix[i], inp):
return float(inp.replace(suffix[i],'').strip()) * pow(1024,i+1)
else:
i+=1
return inp
def main():
info = subprocess.check_output(['/opt/MegaRAID/MegaCli/MegaCli64', '-AdpAllInfo', '-aAll', '-nolog']).decode('utf-8').splitlines()
pdlist = subprocess.check_output(['/opt/MegaRAID/MegaCli/MegaCli64', '-PdList', '-aAll', '-nolog']).decode('utf-8').splitlines()
out = {}
adapter = None
metrics= [
'out["megacli_controller"]={ "help": "Controler information", "type": "gauge" , "metrics": []}',
'out["megacli_memory_size_bytes"]={ "help": "Controler memory information", "type": "gauge" , "metrics": []}',
'out["megacli_drives"]={ "help": "Drives information", "type": "gauge" , "metrics": []}',
'out["megacli_memory_errors"]={ "help": "Memory errors", "type": "gauge" , "metrics": []}',
'out["megacli_pd_info"]={ "help": "Physical drive detailed info", "type": "gauge" , "metrics": []}',
'out["megacli_pd_temperature"]={ "help": "Physical drive temperature", "type": "gauge" , "metrics": []}',
'out["megacli_pd_errors"]={ "help": "Physical drive error counters", "type": "gauge" , "metrics": []}',
'out["megacli_pd_speed_bits"]={ "help": "Link and drive speed", "type": "gauge" , "metrics": []}'
]
pat_info = [
{
'regex': re.compile('^Adapter\s+#\d+'),
'action': [
'adapter=line.split("#")[1].strip()'
]
},
{
'regex': re.compile('^Product\s+Name\s+:'),
'action': [
'out["megacli_controller"]["metrics"].append({ "labels": { "adapter": adapter, "product_name": line.split(":")[1].strip()}, "val": 1})'
]
},
{
'regex': re.compile('^FW\s+Package\s+Build\s*:'),
'action': [
'out["megacli_controller"]["metrics"].append({ "labels": { "adapter": adapter, "package_build": line.split(":")[1].strip()}, "val": 1 })'
]
},
{
'regex': re.compile('^FW\s+Version\s+:'),
'action': [
'out["megacli_controller"]["metrics"].append({ "labels": { "adapter": adapter, "firmware_version": line.split(":")[1].strip()}, "val": 1 })'
]
},
{
'regex': re.compile('^BIOS\s+Version\s+:'),
'action': [
'out["megacli_controller"]["metrics"].append({ "labels": { "adapter": adapter, "bios_version": line.split(":")[1].strip()}, "val": 1 })'
]
},
{
'regex': re.compile('^Memory\s+Size\s+:'),
'action': [
'out["megacli_memory_size_bytes"]["metrics"].append({ "labels": { "adapter": adapter, "type": "Total memory" }, "val": tobytes(line.split(":")[1].strip()) })'
]
},
{
'regex': re.compile('^Current\s+Size\s+of\s+FW\s+Cache\s+:'),
'action': [
'out["megacli_memory_size_bytes"]["metrics"].append({ "labels": { "adapter": adapter, "type": "Write cache" }, "val": tobytes(line.split(":")[1].strip()) })'
]
},
{
'regex': re.compile('^Virtual\s+Drives\s+:'),
'action': [
'out["megacli_drives"]["metrics"].append({ "labels": { "adapter": adapter, "type": "virtual", "state": "Total" }, "val": line.split(":")[1].strip() })'
]
},
{
'regex': re.compile('^\s+Degraded\s+:'),
'action': [
'out["megacli_drives"]["metrics"].append({ "labels": { "adapter": adapter, "type": "virtual", "state": "Degraded" }, "val": line.split(":")[1].strip() })'
]
},
{
'regex': re.compile('^\s+Offline\s+:'),
'action': [
'out["megacli_drives"]["metrics"].append({ "labels": { "adapter": adapter, "type": "virtual", "state": "Offline" }, "val": line.split(":")[1].strip() })'
]
},
{
'regex': re.compile('^Physical\s+Devices\s+:'),
'action': [
'out["megacli_drives"]["metrics"].append({ "labels": { "adapter": adapter, "type": "physical", "state": "PhysicalTotal" }, "val": line.split(":")[1].strip() })'
]
},
{
'regex': re.compile('^\s+Disks\s+:'),
'action': [
'out["megacli_drives"]["metrics"].append({ "labels": { "adapter": adapter, "type": "physical", "state": "DisksTotal" }, "val": line.split(":")[1].strip() })'
]
},
{
'regex': re.compile('^\s+Critical\s+Disks\s+:'),
'action': [
'out["megacli_drives"]["metrics"].append({ "labels": { "adapter": adapter, "type": "physical", "state": "Critical" }, "val": line.split(":")[1].strip() })'
]
},
{
'regex': re.compile('^\s+Failed\s+Disks\s+:'),
'action': [
'out["megacli_drives"]["metrics"].append({ "labels": { "adapter": adapter, "type": "physical", "state": "Failed" }, "val": line.split(":")[1].strip() })'
]
},
{
'regex': re.compile('^Memory\s+Correctable\s+Errors\s+:'),
'action': [
'out["megacli_memory_errors"]["metrics"].append({ "labels": { "adapter": adapter, "type": "correctable" }, "val": line.split(":")[1].strip() })'
]
},
{
'regex': re.compile('^Memory\s+Uncorrectable\s+Errors\s+:'),
'action': [
'out["megacli_memory_errors"]["metrics"].append({ "labels": { "adapter": adapter, "type": "uncorrectable" }, "val": line.split(":")[1].strip() })'
]
},
]
enclosure=None
slot=None
position=None
device_id=None
wwn=None
pat_pd = [
{
'regex': re.compile('^Adapter\s+#\d+'),
'action': ['adapter=line.split("#")[1].strip()']
},
{
'regex': re.compile('^Enclosure\s+Device\s+ID:'),
'action': ['enclosure=line.split(":")[1].strip()']
},
{
'regex': re.compile('^Slot\s+Number\s*:'),
'action': ['slot=line.split(":")[1].strip()']
},
{
'regex': re.compile('^Drive\'s\s+position:'),
'action': [
'out["megacli_pd_info"]["metrics"].append({ "labels": { "adapter": adapter, "enclosure": enclosure, "slot": slot, "type": "disk_group"}, "val": line.split(":")[2].split(",")[0].strip() })',
'out["megacli_pd_info"]["metrics"].append({ "labels": { "adapter": adapter, "enclosure": enclosure, "slot": slot, "type": "span"}, "val": line.split(":")[3].split(",")[0].strip() })',
'out["megacli_pd_info"]["metrics"].append({ "labels": { "adapter": adapter, "enclosure": enclosure, "slot": slot, "type": "arm"}, "val": line.split(":")[4].split(",")[0].strip() })'
]
},
{
'regex': re.compile('^Device\s+Id\s*:'),
'action': [
'out["megacli_pd_info"]["metrics"].append({ "labels": { "adapter": adapter, "enclosure": enclosure, "slot": slot, "type": "device_id" }, "val": line.split(":")[1].strip() })'
]
},
{
'regex': re.compile('^WWN\s*:'),
'action': [
'out["megacli_pd_info"]["metrics"].append({ "labels": { "adapter": adapter, "enclosure": enclosure, "slot": slot, "type": "wwn" }, "val": int(line.split(":")[1].strip(), 16) })'
]
},
{
'regex': re.compile('^Sequence\s+Number\s*:'),
'action': [
'out["megacli_pd_info"]["metrics"].append({ "labels": { "adapter": adapter, "enclosure": enclosure, "slot": slot, "type": "sequence_number" }, "val": line.split(":")[1].strip() })'
]
},
{
'regex': re.compile('^Media\s+Error\s+Count\s*:'),
'action': [
'out["megacli_pd_errors"]["metrics"].append({ "labels": { "adapter": adapter, "enclosure": enclosure, "slot": slot, "type": "media" }, "val": line.split(":")[1].strip() })'
]
},
{
'regex': re.compile('^Other\s+Error\s+Count\s*:'),
'action': [
'out["megacli_pd_errors"]["metrics"].append({ "labels": { "adapter": adapter, "enclosure": enclosure, "slot": slot, "type": "other" }, "val": line.split(":")[1].strip() })'
]
},
{
'regex': re.compile('^Predictive\s+Failure\s+Count\s*:'),
'action': [
'out["megacli_pd_errors"]["metrics"].append({ "labels": { "adapter": adapter, "enclosure": enclosure, "slot": slot, "type": "predictive" }, "val": line.split(":")[1].strip() })'
]
},
{
'regex': re.compile('^Raw\s+Size\s*:'),
'action': [
'out["megacli_pd_info"]["metrics"].append({ "labels": { "adapter": adapter, "enclosure": enclosure, "slot": slot, "type": "size_raw" }, "val": tobytes(line.split(":")[1].split("[")[0].strip()) })'
]
},
{
'regex': re.compile('^Non\s+Coerced\s+Size\s*:'),
'action': [
'out["megacli_pd_info"]["metrics"].append({ "labels": { "adapter": adapter, "enclosure": enclosure, "slot": slot, "type": "size_non_coerced" }, "val": tobytes(line.split(":")[1].split("[")[0].strip()) })'
]
},
{
'regex': re.compile('^Coerced\s+Size\s*:'),
'action': [
'out["megacli_pd_info"]["metrics"].append({ "labels": { "adapter": adapter, "enclosure": enclosure, "slot": slot, "type": "size_coerced" }, "val": tobytes(line.split(":")[1].split("[")[0].strip()) })'
]
},
{
'regex': re.compile('^Firmware\s+state\s*:'),
'action': [
'out["megacli_pd_info"]["metrics"].append({ "labels": { "adapter": adapter, "enclosure": enclosure, "slot": slot, "type": "state" }, "val": state2int(line.split(":")[1].strip()) })'
]
},
{
'regex': re.compile('^Connected\s+Port\s+Number\s*:'),
'action': [
'out["megacli_pd_info"]["metrics"].append({ "labels": { "adapter": adapter, "enclosure": enclosure, "slot": slot, "type": "port" }, "val": line.split(":")[1].split("(")[0].strip() })',
'out["megacli_pd_info"]["metrics"].append({ "labels": { "adapter": adapter, "enclosure": enclosure, "slot": slot, "type": "path" }, "val": line.split("path")[1].split(")")[0].strip() })'
]
},
{
'regex': re.compile('^Needs\s+EKM\s+Attention\s*:'),
'action': [
'out["megacli_pd_info"]["metrics"].append({ "labels": { "adapter": adapter, "enclosure": enclosure, "slot": slot, "type": "ekm_attention_needed" }, "val": yesno(line.split(":")[1].strip()) })'
]
},
{
'regex': re.compile('^Device\s+Speed\s*:'),
'action': [
'out["megacli_pd_speed_bits"]["metrics"].append({ "labels": { "adapter": adapter, "enclosure": enclosure, "slot": slot, "type": "drive" }, "val": tobytes(line.split(":")[1].split("/")[0].strip()) })'
]
},
{
'regex': re.compile('^Link\s+Speed\s*:'),
'action': [
'out["megacli_pd_speed_bits"]["metrics"].append({ "labels": { "adapter": adapter, "enclosure": enclosure, "slot": slot, "type": "link" }, "val": tobytes(line.split(":")[1].split("/")[0].strip()) })'
]
},
{
'regex': re.compile('^Drive\s+Temperature\s*:'),
'action': [
'out["megacli_pd_temperature"]["metrics"].append({ "labels": { "adapter": adapter, "enclosure": enclosure, "slot": slot, "type": "celsius" }, "val": line.split(":")[1].split("C")[0].strip() })',
'out["megacli_pd_temperature"]["metrics"].append({ "labels": { "adapter": adapter, "enclosure": enclosure, "slot": slot, "type": "barbarians" }, "val": line.split("(")[1].split(" ")[0].strip() })'
]
},
{
'regex': re.compile('^Drive\s+has\s+flagged\s+a\s+S.M.A.R.T\s+alert\s*:'),
'action': [
'out["megacli_pd_info"]["metrics"].append({ "labels": { "adapter": adapter, "enclosure": enclosure, "slot": slot, "type": "smart_alert" }, "val": yesno(line.split(":")[1].strip()) })'
]
},
]
for m in metrics:
exec(m)
for line in info:
for p in pat_info:
if p['regex'].match(line):
for a in p['action']:
exec(a)
continue
for line in pdlist:
for p in pat_pd:
if p['regex'].match(line):
for a in p['action']:
exec(a)
continue
# print json.dumps(out, indent=2, sort_keys=True)
for k,v in out.iteritems():
print("# HELP " + k + " " + v['help'])
print("# TYPE " + k + " " + v['type'])
for m in v['metrics']:
print ( str(k) + '{' + ', '.join([ "{}=\"{}\"".format(str(l),str(m['labels'][l])) for l in sorted(m['labels']) ]) + '} ' + str(m['val']) )
if __name__ == "__main__":
main()