109 lines
2.7 KiB
Python
109 lines
2.7 KiB
Python
#!/usr/bin/env python3
|
|
|
|
import re, os
|
|
from subprocess import getoutput
|
|
|
|
keys = [
|
|
"ECC corrected fast",
|
|
"ECC corrected delayed",
|
|
"ECC reread/rewrites",
|
|
"Total errors corrected",
|
|
"Correction algorithm invocations",
|
|
"Gigabytes processed [10^9 bytes]",
|
|
"Total uncorrected errors",
|
|
]
|
|
|
|
def log(type, disk, message):
|
|
print("!!LOG", type, disk, message)
|
|
|
|
def get_all_scsi_path():
|
|
disks = os.listdir('/dev/disk/by-id/')
|
|
out = []
|
|
for disk in disks:
|
|
if disk.startswith('scsi') and 'part' not in disk:
|
|
out.append('/dev/disk/by-id/'+disk)
|
|
return out
|
|
|
|
def call_smart(disks):
|
|
out = {}
|
|
for disk in disks:
|
|
content = getoutput('smartctl -a {}'.format(disk))
|
|
content = parse_out(content, disk)
|
|
out[disk] = content
|
|
|
|
return out
|
|
|
|
def save_status(stats):
|
|
for disk in status:
|
|
for key in ['read', 'write', 'verify']:
|
|
if len(disk[key]) == 7:
|
|
db.add_status(disk, key, disk[key], disk['Non-medium error count'])
|
|
else:
|
|
log('missing', disk, '{} is missing values'.fotmat(key))
|
|
|
|
|
|
def parse_out(content, disk=''):
|
|
out = {
|
|
'read': {},
|
|
'write': {},
|
|
'verify': {},
|
|
'Non-medium error count': 0,
|
|
'Elements in grown defect list': 0,
|
|
'SMART Health Status': ''
|
|
}
|
|
|
|
try:
|
|
out['SMART Health Status'] = re.search(
|
|
r'SMART Health Status:\s+(?P<status>.+)', content
|
|
).group('status')
|
|
except AttributeError as error:
|
|
log('missing', disk, "SMART Health Status not found")
|
|
|
|
try:
|
|
out['Elements in grown defect list'] = re.search(
|
|
r'Elements in grown defect list:\s+(?P<number>\d+)', content
|
|
).group('number')
|
|
except AttributeError as error:
|
|
log('missing', disk, "Elements in grown defect list not found")
|
|
|
|
try:
|
|
out['Non-medium error count'] = re.search(
|
|
r'Non-medium error count:\s+(?P<number>\d+)', content
|
|
).group('number')
|
|
except AttributeError as error:
|
|
log('missing', disk, "Non-medium error count not found")
|
|
|
|
try:
|
|
content = content.split("Error counter log:")[1]
|
|
except IndexError:
|
|
log('failed', disk, 'Missing error information section')
|
|
return {}
|
|
|
|
for line in content.split('\n'):
|
|
if line.startswith('read:'):
|
|
line = re.sub(r'^[a-z:\s]+', '', line)
|
|
line = re.split(r'\s+', line)
|
|
out['read'] = dict(zip(keys, line))
|
|
continue
|
|
|
|
if line.startswith('write:'):
|
|
line = re.sub(r'^[a-z:\s]+', '', line)
|
|
line = re.split(r'\s+', line)
|
|
out['write'] = dict(zip(keys, line))
|
|
continue
|
|
|
|
if line.startswith('verify:'):
|
|
line = re.sub(r'^[a-z:\s]+', '', line)
|
|
line = re.split(r'\s+', line)
|
|
out['verify'] = dict(zip(keys, line))
|
|
continue
|
|
|
|
return out
|
|
|
|
if __name__ == "__main__":
|
|
import json
|
|
disks = get_all_scsi_path()
|
|
parsed = call_smart(disks)
|
|
print(json.dumps(parsed, indent=4, sort_keys=True))
|
|
print(*[(i,parsed[i].get('SMART Health Status')) for i in parsed], sep='\n')
|