This commit is contained in:
William Mantly 2020-07-01 16:11:27 -04:00
commit 6482e77af3
4 changed files with 236 additions and 0 deletions

68
db.py Normal file
View File

@ -0,0 +1,68 @@
import sqlite3, datetime
class SQLite():
def __init__(self, file='sqlite.db'):
self.file=file
def __enter__(self):
self.conn = sqlite3.connect(self.file)
self.conn.row_factory = sqlite3.Row
return self.conn.cursor()
def __exit__(self, type, value, traceback):
self.conn.commit()
self.conn.close()
def create_status_table():
with SQLite() as cur:
cur.execute("""
CREATE TABLE `status` (
`ID` INTEGER PRIMARY KEY AUTOINCREMENT,
`drive` TEXT,
`date` NUMERIC,
`type` TEXT,
`fast` INTEGER,
`delayed` INTEGER,
`re` INTEGER,
`total_e_cottect` INTEGER,
`correction` INTEGER,
`proc_gb` INTEGER,
`total_u_errors` INTEGER,
`Non-medium error count` INTEGER
);
""")
def table_exist(name):
with SQLite() as cur:
cur.execute('''
SELECT name FROM sqlite_master WHERE type='table' AND name='{}';
'''.format(name))
return True if cur.fetchone() else False
def add_status(drive, type, status, NM_count):
now = int(datetime.datetime.now().timestamp())
with SQLite() as cur:
cur.execute(
'''
INSERT INTO status (drive, date, type, fast, delayed, re, total_e_cottect, correction, proc_gb, total_u_errors, "Non-medium error count") VALUES (?,?,?,?,?,?,?,?,?,?,?)
''',(drive, now, type, *status, NM_count)
)
def get_status(drive):
with SQLite() as cur:
cur.execute('''
SELECT * FROM status WHERE drive=(?)
''',(drive,))
return cur.fetchall()
if __name__ == '__main__':
if not table_exist('status'):
print("Creating table")
create_status_table()
else:
print('Table table exist!')
test = {'read': ['314277204', '9', '0', '314277213', '9', '229503.982', '0'], 'write': ['0', '0', '0', '0', '0', '47762.811', '0'], 'verify': ['64', '0', '0', '64', '0', '0.000', '0'], 'Non-medium error count': '10'}

108
parse.py Normal file
View File

@ -0,0 +1,108 @@
#!/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')

60
smart.txt Normal file
View File

@ -0,0 +1,60 @@
smartctl 6.5 2016-01-24 r4214 [x86_64-linux-4.4.0-165-generic] (local build)
Copyright (C) 2002-16, Bruce Allen, Christian Franke, www.smartmontools.org
=== START OF INFORMATION SECTION ===
Vendor: SEAGATE
Product: ST6000NM0034
Revision: E005
Compliance: SPC-4
User Capacity: 6,001,175,126,016 bytes [6.00 TB]
Logical block size: 512 bytes
Physical block size: 4096 bytes
Formatted with type 2 protection
LB provisioning type: unreported, LBPME=0, LBPRZ=0
Rotation Rate: 7200 rpm
Form Factor: 3.5 inches
Logical Unit id: 0x5000c50062502b8b
Serial number: Z4D0C1EV0000S440NQKX
Device type: disk
Transport protocol: SAS (SPL-3)
Local Time is: Tue Nov 5 19:56:43 2019 EST
SMART support is: Available - device has SMART capability.
SMART support is: Enabled
Temperature Warning: Enabled
=== START OF READ SMART DATA SECTION ===
SMART Health Status: OK
Current Drive Temperature: 50 C
Drive Trip Temperature: 60 C
Manufactured in week 36 of year 2014
Specified cycle count over device lifetime: 10000
Accumulated start-stop cycles: 46
Specified load-unload count over device lifetime: 300000
Accumulated load-unload cycles: 5971
Elements in grown defect list: 7
Vendor (Seagate) cache information
Blocks sent to initiator = 3267148336
Blocks received from initiator = 1629969808
Blocks read from cache and sent to initiator = 3854095152
Number of read and write commands whose size <= segment size = 300541123
Number of read and write commands whose size > segment size = 3892
Vendor (Seagate/Hitachi) factory information
number of hours powered up = 28080.92
number of minutes until next internal SMART test = 54
Error counter log:
Errors Corrected by Total Correction Gigabytes Total
ECC rereads/ errors algorithm processed uncorrected
fast | delayed rewrites corrected invocations [10^9 bytes] errors
read: 314277204 9 0 314277213 9 229503.982 0
write: 0 0 0 0 0 47762.811 0
verify: 64 0 0 64 0 0.000 0
Non-medium error count: 10
No self-tests have been logged

BIN
sqlite.db Normal file

Binary file not shown.