Added Disk().generate_report()

* Uses new merged ATTRIBUTES config
This commit is contained in:
2Shirt 2019-10-28 20:15:58 -06:00
parent fbb480dae6
commit c7090e77c2
Signed by: 2Shirt
GPG key ID: 152FAC923B0E132C
3 changed files with 116 additions and 4 deletions

View file

@ -1,5 +1,6 @@
"""WizardKit: cfg module init""" """WizardKit: cfg module init"""
from wk.cfg import hw
from wk.cfg import log from wk.cfg import log
from wk.cfg import main from wk.cfg import main
from wk.cfg import net from wk.cfg import net

34
scripts/wk/cfg/hw.py Normal file
View file

@ -0,0 +1,34 @@
"""WizardKit: Config - Hardware"""
# pylint: disable=bad-whitespace,line-too-long
# vim: sts=2 sw=2 ts=2
ATTRIBUTES = {
# NVMe
'critical_warning': {'Critical': True, 'Ignore': False, 'Warning': None, 'Error': 1, 'Maximum': None, },
'media_errors': {'Critical': False, 'Ignore': False, 'Warning': None, 'Error': 1, 'Maximum': None, },
'power_on_hours': {'Critical': False, 'Ignore': True, 'Warning': 17532, 'Error': 26298, 'Maximum': None, },
'unsafe_shutdowns': {'Critical': False, 'Ignore': True, 'Warning': 1, 'Error': None, 'Maximum': None, },
# SMART
5: {'Hex': '05', 'Critical': True, 'Ignore': False, 'Warning': None, 'Error': 1, 'Maximum': None, },
9: {'Hex': '09', 'Critical': False, 'Ignore': True, 'Warning': 17532, 'Error': 26298, 'Maximum': None, },
10: {'Hex': '10', 'Critical': False, 'Ignore': False, 'Warning': 1, 'Error': 10, 'Maximum': 10000, },
184: {'Hex': 'B8', 'Critical': False, 'Ignore': False, 'Warning': 1, 'Error': 10, 'Maximum': 10000, },
187: {'Hex': 'BB', 'Critical': False, 'Ignore': False, 'Warning': 1, 'Error': 10, 'Maximum': 10000, },
188: {'Hex': 'BC', 'Critical': False, 'Ignore': False, 'Warning': 1, 'Error': 10, 'Maximum': 10000, },
196: {'Hex': 'C4', 'Critical': False, 'Ignore': False, 'Warning': 1, 'Error': 10, 'Maximum': 10000, },
197: {'Hex': 'C5', 'Critical': True, 'Ignore': False, 'Warning': None, 'Error': 1, 'Maximum': None, },
198: {'Hex': 'C6', 'Critical': True, 'Ignore': False, 'Warning': None, 'Error': 1, 'Maximum': None, },
199: {'Hex': 'C7', 'Critical': False, 'Ignore': True, 'Warning': None, 'Error': 1, 'Maximum': None, },
201: {'Hex': 'C9', 'Critical': False, 'Ignore': False, 'Warning': None, 'Error': 1, 'Maximum': 10000, },
}
ATTRIBUTE_COLORS = (
# NOTE: Ordered by ascending importance
('Warning', 'YELLOW'),
('Error', 'RED'),
('Maximum', 'PURPLE'),
)
if __name__ == '__main__':
print("This file is not meant to be called directly.")

View file

@ -1,4 +1,4 @@
"""WizardKit: Hardware objects (mostly).""" """WizardKit: Hardware objects (mostly)"""
# vim: sts=2 sw=2 ts=2 # vim: sts=2 sw=2 ts=2
import logging import logging
@ -9,6 +9,7 @@ import re
from collections import OrderedDict from collections import OrderedDict
from wk.cfg.hw import ATTRIBUTES, ATTRIBUTE_COLORS
from wk.exe import get_json_from_command, run_program from wk.exe import get_json_from_command, run_program
from wk.std import bytes_to_string, color_string, string_to_bytes from wk.std import bytes_to_string, color_string, string_to_bytes
@ -93,8 +94,8 @@ class CpuRam():
f'{count}x {desc}' for desc, count in sorted(details.items()) f'{count}x {desc}' for desc, count in sorted(details.items())
] ]
def generate_cpu_report(self): def generate_report(self):
"""Generate CPU report with data from all tests.""" """Generate CPU & RAM report, returns list."""
report = [] report = []
report.append(color_string('Device', 'BLUE')) report.append(color_string('Device', 'BLUE'))
report.append(f' {self.description}') report.append(f' {self.description}')
@ -116,7 +117,7 @@ class Disk():
self.attributes = {} self.attributes = {}
self.description = 'Unknown' self.description = 'Unknown'
self.details = {} self.details = {}
self.nvme_smart_notes = {} self.notes = {}
self.path = pathlib.Path(path).resolve() self.path = pathlib.Path(path).resolve()
self.smartctl = {} self.smartctl = {}
self.tests = OrderedDict() self.tests = OrderedDict()
@ -137,6 +138,77 @@ class Disk():
] ]
run_program(cmd, check=False) run_program(cmd, check=False)
def generate_attribute_report(self):
"""Generate attribute report, returns list."""
report = []
for attr, value in sorted(self.attributes.items()):
note = ''
value_color = 'GREEN'
# Skip attributes not in our list
if attr not in ATTRIBUTES:
continue
# ID / Name
label = f'{attr:>3}'
if isinstance(attr, int):
# Assuming SMART, include hex ID and name
label += f' / {str(hex(attr))[2:].upper():0>2}: {value["name"]}'
label = f' {label.replace("_", " "):38}'
# Value color
for threshold, color in ATTRIBUTE_COLORS:
if value['raw'] >= ATTRIBUTES.get(threshold, float('inf')):
value_color = color
if threshold == 'Maximum':
note = '(invalid?)'
# 199/C7 warning
if str(attr) == '199' and value['raw'] > 0:
note = '(bad cable?)'
# Build colored string and append to report
line = color_string(
[label, value['raw_str'], note],
[None, value_color, 'YELLOW'],
)
report.append(line)
# Done
return report
def generate_report(self):
"""Generate Disk report, returns list."""
report = []
report.append(color_string(f'Device {self.path.name}', 'BLUE'))
report.append(f' {self.description}')
# Attributes
if self.attributes:
report.append(color_string('Attributes', 'BLUE'))
report.extend(self.generate_attribute_report())
else:
report.append(
color_string(' No NVMe or SMART data available', 'YELLOW'))
# Notes
if self.notes:
report.append(color_string('Notes', 'BLUE'))
for note in sorted(self.notes.keys()):
report.append(f' {note}')
# 4K alignment check
if not self.is_4k_aligned():
report.append(color_string('Warning', 'YELLOW'))
report.append(' One or more partitions are not 4K aligned')
# Tests
for test in self.tests.values():
report.extend(test.report)
return report
def get_details(self): def get_details(self):
"""Get disk details using OS specific methods. """Get disk details using OS specific methods.
@ -187,6 +259,11 @@ class Disk():
# Done # Done
return labels return labels
def is_4k_aligned(self):
"""Check that all disk partitions are aligned, returns bool."""
#TODO: Make real
return True
def update_smart_details(self): def update_smart_details(self):
"""Update SMART details via smartctl.""" """Update SMART details via smartctl."""
self.attributes = {} self.attributes = {}