Group results by device instead of test

This commit is contained in:
2Shirt 2018-12-16 22:06:03 -07:00
parent 503e6f2b42
commit 4c0bb1c9b7
Signed by: 2Shirt
GPG key ID: 152FAC923B0E132C

View file

@ -79,7 +79,7 @@ class CpuObj():
"""Object for tracking CPU specific data.""" """Object for tracking CPU specific data."""
def __init__(self): def __init__(self):
self.lscpu = {} self.lscpu = {}
self.tests = {} self.tests = OrderedDict()
self.get_details() self.get_details()
self.name = self.lscpu.get('Model name', 'Unknown CPU') self.name = self.lscpu.get('Model name', 'Unknown CPU')
@ -102,6 +102,18 @@ class CpuObj():
continue continue
self.lscpu[_field] = _data self.lscpu[_field] = _data
def generate_cpu_report(self):
"""Generate CPU report with data from all tests."""
report = []
report.append('{BLUE}Device{CLEAR}'.format(**COLORS))
report.append(' {}'.format(self.name))
# Tests
for test in self.tests.values():
report.extend(test.report)
return report
class DiskObj(): class DiskObj():
"""Object for tracking disk specific data.""" """Object for tracking disk specific data."""
def __init__(self, disk_path): def __init__(self, disk_path):
@ -115,9 +127,10 @@ class DiskObj():
self.smart_self_test = {} self.smart_self_test = {}
self.smartctl = {} self.smartctl = {}
self.tests = OrderedDict() self.tests = OrderedDict()
self.warnings = []
self.get_details() self.get_details()
self.get_smart_details() self.get_smart_details()
self.description = '{size:>6} ({tran}) {model} {serial}'.format( self.description = '{size} ({tran}) {model} {serial}'.format(
**self.lsblk) **self.lsblk)
def check_attributes(self, silent=False): def check_attributes(self, silent=False):
@ -159,8 +172,8 @@ class DiskObj():
print_standard(' (Have you tried swapping the disk cable?)') print_standard(' (Have you tried swapping the disk cable?)')
else: else:
# Override? # Override?
show_report(self.generate_report()) show_report(self.generate_attribute_report(description=True))
print_warning('{} error(s) detected.'.format(attr_type)) print_warning(' {} error(s) detected.'.format(attr_type))
if override_disabled: if override_disabled:
print_standard('Tests disabled for this device') print_standard('Tests disabled for this device')
pause() pause()
@ -172,13 +185,15 @@ class DiskObj():
if self.nvme_attributes or not self.smart_attributes: if self.nvme_attributes or not self.smart_attributes:
# i.e. only leave enabled for SMART short-tests # i.e. only leave enabled for SMART short-tests
self.tests['NVMe / SMART'].disabled = True self.tests['NVMe / SMART'].disabled = True
print_standard(' ')
def generate_report(self, brief=False, short_test=False): def generate_attribute_report(
self, description=False, short_test=False, timestamp=False):
"""Generate NVMe / SMART report, returns list.""" """Generate NVMe / SMART report, returns list."""
report = [] report = []
if not brief: if description:
report.append('{BLUE}Device: {dev_path}{CLEAR}'.format( report.append('{BLUE}Device ({name}){CLEAR}'.format(
dev_path=self.path, **COLORS)) name=self.name, **COLORS))
report.append(' {}'.format(self.description)) report.append(' {}'.format(self.description))
# Warnings # Warnings
@ -203,8 +218,8 @@ class DiskObj():
# Attributes # Attributes
report.append('{BLUE}{a} Attributes{YELLOW}{u:>23} {t}{CLEAR}'.format( report.append('{BLUE}{a} Attributes{YELLOW}{u:>23} {t}{CLEAR}'.format(
a=attr_type, a=attr_type,
u='Updated:' if brief else '', u='Updated:' if timestamp else '',
t=time.strftime('%Y-%m-%d %H:%M %Z') if brief else '', t=time.strftime('%Y-%m-%d %H:%M %Z') if timestamp else '',
**COLORS)) **COLORS))
if self.nvme_attributes: if self.nvme_attributes:
attr_type = 'NVMe' attr_type = 'NVMe'
@ -259,6 +274,21 @@ class DiskObj():
# Done # Done
return report return report
def generate_disk_report(self):
"""Generate disk report with data from all tests."""
report = []
report.append('{BLUE}Device ({name}){CLEAR}'.format(
name=self.name, **COLORS))
report.append(' {}'.format(self.description))
for w in self.warnings:
report.append(' {YELLOW}{w}{CLEAR}'.format(w=w, **COLORS))
# Tests
for test in self.tests.values():
report.extend(test.report)
return report
def get_details(self): def get_details(self):
"""Get data from lsblk.""" """Get data from lsblk."""
cmd = ['lsblk', '--json', '--output-all', '--paths', self.path] cmd = ['lsblk', '--json', '--output-all', '--paths', self.path]
@ -338,14 +368,14 @@ class DiskObj():
# Check if a self-test is currently running # Check if a self-test is currently running
if 'remaining_percent' in self.smart_self_test['status']: if 'remaining_percent' in self.smart_self_test['status']:
_msg='SMART self-test in progress, all tests disabled' _msg = 'SMART self-test in progress, all tests disabled'
if not silent: if not silent:
print_warning('WARNING: {}'.format(_msg)) print_warning('WARNING: {}'.format(_msg))
print_standard(' ') print_standard(' ')
if ask('Abort HW Diagnostics?'): if ask('Abort HW Diagnostics?'):
exit_script() exit_script()
if 'NVMe / SMART' in self.tests: if 'NVMe / SMART' in self.tests:
self.tests['NVMe / SMART'].report = self.generate_report() self.tests['NVMe / SMART'].report = self.generate_attribute_report()
self.tests['NVMe / SMART'].report.append( self.tests['NVMe / SMART'].report.append(
'{YELLOW}WARNING: {msg}{CLEAR}'.format(msg=_msg, **COLORS)) '{YELLOW}WARNING: {msg}{CLEAR}'.format(msg=_msg, **COLORS))
for t in self.tests.values(): for t in self.tests.values():
@ -359,17 +389,20 @@ class DiskObj():
if silent: if silent:
self.disk_ok = HW_OVERRIDES_FORCED self.disk_ok = HW_OVERRIDES_FORCED
else: else:
print_warning( _msg = 'No NVMe or SMART data available'
' WARNING: No NVMe or SMART attributes available for: {}'.format( self.warnings.append(_msg)
self.path)) print_info('Device ({})'.format(self.name))
print_standard(' {}'.format(self.description))
print_warning(' {}'.format(_msg))
self.disk_ok = HW_OVERRIDES_FORCED or ask( self.disk_ok = HW_OVERRIDES_FORCED or ask(
'Run tests on this device anyway?') 'Run tests on this device anyway?')
print_standard(' ')
if not self.disk_ok: if not self.disk_ok:
if 'NVMe / SMART' in self.tests: if 'NVMe / SMART' in self.tests:
# NOTE: This will not overwrite the existing status if set # NOTE: This will not overwrite the existing status if set
if not self.tests['NVMe / SMART'].report: if not self.tests['NVMe / SMART'].report:
self.tests['NVMe / SMART'].report = self.generate_report() self.tests['NVMe / SMART'].report = self.generate_attribute_report()
self.tests['NVMe / SMART'].update_status('NS') self.tests['NVMe / SMART'].update_status('NS')
self.tests['NVMe / SMART'].disabled = True self.tests['NVMe / SMART'].disabled = True
for t in ['badblocks', 'I/O Benchmark']: for t in ['badblocks', 'I/O Benchmark']:
@ -743,7 +776,7 @@ def run_badblocks_test(state, test):
# Show disk details # Show disk details
clear_screen() clear_screen()
show_report(test.dev.generate_report()) show_report(test.dev.generate_attribute_report())
print_standard(' ') print_standard(' ')
# Start badblocks # Start badblocks
@ -757,6 +790,7 @@ def run_badblocks_test(state, test):
raise GenericAbort('Aborted') raise GenericAbort('Aborted')
# Check result and create report # Check result and create report
test.report.append('{BLUE}badblocks{CLEAR}'.format(**COLORS))
try: try:
test.badblocks_out = test.badblocks_proc.stdout.read().decode() test.badblocks_out = test.badblocks_proc.stdout.read().decode()
except Exception as err: except Exception as err:
@ -787,7 +821,6 @@ def run_badblocks_test(state, test):
# Cleanup # Cleanup
tmux_kill_pane(state.panes['badblocks']) tmux_kill_pane(state.panes['badblocks'])
pause()
def run_hw_tests(state): def run_hw_tests(state):
"""Run enabled hardware tests.""" """Run enabled hardware tests."""
@ -825,15 +858,6 @@ def run_hw_tests(state):
for disk in state.disks: for disk in state.disks:
disk.safety_check(silent=state.quick_mode) disk.safety_check(silent=state.quick_mode)
# TODO Remove
clear_screen()
print_info('Running tests:')
for k, v in state.tests.items():
if v['Enabled']:
print_standard(' {}'.format(k))
update_progress_pane(state)
pause()
# Run tests # Run tests
## Because state.tests is an OrderedDict and the disks were added ## Because state.tests is an OrderedDict and the disks were added
## in order, the tests will be run in order. ## in order, the tests will be run in order.
@ -1010,6 +1034,7 @@ def run_mprime_test(state, test):
global_vars['LogDir'])) global_vars['LogDir']))
# Check results and build report # Check results and build report
test.report.append('{BLUE}Prime95{CLEAR}'.format(**COLORS))
test.logs = {} test.logs = {}
for log in ['results.txt', 'prime.log']: for log in ['results.txt', 'prime.log']:
lines = [] lines = []
@ -1026,20 +1051,18 @@ def run_mprime_test(state, test):
# results.txt (NS check) # results.txt (NS check)
if log == 'results.txt': if log == 'results.txt':
_tmp = []
for line in lines: for line in lines:
line = line.strip()
if re.search(r'(error|fail)', line, re.IGNORECASE): if re.search(r'(error|fail)', line, re.IGNORECASE):
test.failed = True test.failed = True
test.update_status('NS') test.update_status('NS')
_tmp.append(' {YELLOW}{line}{CLEAR}'.format(line=line, **COLORS)) test.report.append(' {YELLOW}{line}{CLEAR}'.format(line=line, **COLORS))
if _tmp:
test.report.append('{BLUE}Log: results.txt{CLEAR}'.format(**COLORS))
test.report.extend(_tmp)
# prime.log (CS check) # prime.log (CS check)
if log == 'prime.log': if log == 'prime.log':
_tmp = {'Pass': {}, 'Warn': {}} _tmp = {'Pass': {}, 'Warn': {}}
for line in lines: for line in lines:
line = line.strip()
_r = re.search( _r = re.search(
r'(completed.*(\d+) errors, (\d+) warnings)', r'(completed.*(\d+) errors, (\d+) warnings)',
line, line,
@ -1059,18 +1082,19 @@ def run_mprime_test(state, test):
elif len(_tmp['Pass']) > 0: elif len(_tmp['Pass']) > 0:
test.passed = True test.passed = True
test.update_status('CS') test.update_status('CS')
if len(_tmp['Pass']) + len(_tmp['Warn']) > 0:
test.report.append('{BLUE}Log: prime.log{CLEAR}'.format(**COLORS))
for line in sorted(_tmp['Pass'].keys()): for line in sorted(_tmp['Pass'].keys()):
test.report.append(' {}'.format(line)) test.report.append(' {}'.format(line))
for line in sorted(_tmp['Warn'].keys()): for line in sorted(_tmp['Warn'].keys()):
test.report.append(' {YELLOW}{line}{CLEAR}'.format(line=line, **COLORS)) test.report.append(' {YELLOW}{line}{CLEAR}'.format(line=line, **COLORS))
# Finalize report # Unknown result
if not (test.aborted or test.failed or test.passed): if not (test.aborted or test.failed or test.passed):
test.report.append(' {YELLOW}Unknown result{CLEAR}'.format(**COLORS))
test.update_status('Unknown') test.update_status('Unknown')
# Add temps to report
test.report.append('{BLUE}Temps{CLEAR}'.format(**COLORS)) test.report.append('{BLUE}Temps{CLEAR}'.format(**COLORS))
for line in generate_report( for line in generate_sensor_report(
test.sensor_data, 'Idle', 'Max', 'Cooldown', core_only=True): test.sensor_data, 'Idle', 'Max', 'Cooldown', core_only=True):
test.report.append(' {}'.format(line)) test.report.append(' {}'.format(line))
@ -1144,10 +1168,10 @@ def run_nvme_smart_tests(state, test):
# Show attributes # Show attributes
clear_screen() clear_screen()
for line in test.dev.generate_report(): print_info('Device ({})'.format(test.dev.name))
# Not saving to log; that will happen after all tests have been run print_standard(' {}'.format(test.dev.description))
print(line) show_report(test.dev.generate_attribute_report())
print(' ') print_standard(' ')
# Start short test # Start short test
print_standard('Running self-test...') print_standard('Running self-test...')
@ -1203,7 +1227,7 @@ def run_nvme_smart_tests(state, test):
tmux_kill_pane(state.panes['smart']) tmux_kill_pane(state.panes['smart'])
# Save report # Save report
test.report = test.dev.generate_report( test.report = test.dev.generate_attribute_report(
short_test=_include_short_test) short_test=_include_short_test)
# Done # Done
@ -1231,13 +1255,24 @@ def show_results(state):
tmux_update_pane( tmux_update_pane(
state.panes['Top'], text='{}\n{}'.format( state.panes['Top'], text='{}\n{}'.format(
TOP_PANE_TEXT, 'Results')) TOP_PANE_TEXT, 'Results'))
for k, v in state.tests.items():
# Skip disabled tests # CPU tests
if not v['Enabled']: _enabled = False
continue for k in TESTS_CPU:
print_success('{}:'.format(k)) _enabled |= state.tests[k]['Enabled']
for obj in v['Objects']: if _enabled:
show_report(obj.report) print_success('CPU:'.format(k))
show_report(state.cpu.generate_cpu_report())
print_standard(' ')
# Disk tests
for k in TESTS_DISK:
_enabled |= state.tests[k]['Enabled']
if _enabled:
print_success('Disk{}:'.format(
'' if len(state.disks) == 1 else 's'))
for disk in state.disks:
show_report(disk.generate_disk_report())
print_standard(' ') print_standard(' ')
def update_main_options(state, selection, main_options): def update_main_options(state, selection, main_options):