Added debug mode for HW Diagnostics
* Uses alternative major exception * Saves State, CpuObj, and DiskObj data after traceback * Uploads the whole LogDir folder (compressed) instead of just the main log
This commit is contained in:
parent
7381547b27
commit
122bbfb157
4 changed files with 216 additions and 1 deletions
183
.bin/Scripts/debug/hw_diags.py
Normal file
183
.bin/Scripts/debug/hw_diags.py
Normal file
|
|
@ -0,0 +1,183 @@
|
||||||
|
# Wizard Kit: Debug - HW Diagnostics
|
||||||
|
|
||||||
|
import base64
|
||||||
|
import requests
|
||||||
|
|
||||||
|
from functions.common import *
|
||||||
|
|
||||||
|
def debug_report_cpu(cpu_obj):
|
||||||
|
"""Generate report for CpuObj, returns list."""
|
||||||
|
report = []
|
||||||
|
|
||||||
|
# CPU Info
|
||||||
|
report.append('CPU: {}'.format(cpu_obj.name))
|
||||||
|
report.append('lscpu:')
|
||||||
|
for k, v in sorted(cpu_obj.lscpu.items()):
|
||||||
|
report.append(' {}: {}'.format(k, v))
|
||||||
|
|
||||||
|
# Tests
|
||||||
|
report.append('Tests:')
|
||||||
|
for k, v in cpu_obj.tests.items():
|
||||||
|
report.extend(debug_report_test(v, k))
|
||||||
|
|
||||||
|
# Done
|
||||||
|
return report
|
||||||
|
|
||||||
|
|
||||||
|
def debug_report_disk(disk_obj):
|
||||||
|
"""Generate report for DiskObj, returns list."""
|
||||||
|
report = []
|
||||||
|
expand = [
|
||||||
|
'lsblk',
|
||||||
|
'nvme_attributes',
|
||||||
|
'nvme_smart_notes',
|
||||||
|
'smart_attributes',
|
||||||
|
'smart_self_test',
|
||||||
|
'smartctl',
|
||||||
|
]
|
||||||
|
skip = [
|
||||||
|
'add_nvme_smart_note',
|
||||||
|
'calc_io_dd_values',
|
||||||
|
'check_attributes',
|
||||||
|
'check_smart_self_test',
|
||||||
|
'description',
|
||||||
|
'disable_test',
|
||||||
|
'generate_attribute_report',
|
||||||
|
'generate_disk_report',
|
||||||
|
'get_details',
|
||||||
|
'get_size',
|
||||||
|
'get_smart_details',
|
||||||
|
'name',
|
||||||
|
'safety_check',
|
||||||
|
'tests',
|
||||||
|
]
|
||||||
|
|
||||||
|
# Disk Info
|
||||||
|
report.append('Disk: {} {}'.format(
|
||||||
|
disk_obj.name, disk_obj.description))
|
||||||
|
for a in dir(disk_obj):
|
||||||
|
if a.startswith('_') or a in skip:
|
||||||
|
continue
|
||||||
|
if a in expand:
|
||||||
|
report.append('{}:'.format(a))
|
||||||
|
attr = getattr(disk_obj, a)
|
||||||
|
try:
|
||||||
|
for k, v in sorted(attr.items()):
|
||||||
|
report.append(' {}: {}'.format(k, v))
|
||||||
|
except Exception:
|
||||||
|
# Ignore
|
||||||
|
pass
|
||||||
|
else:
|
||||||
|
report.append('{}: {}'.format(a, getattr(disk_obj, a)))
|
||||||
|
|
||||||
|
# Tests
|
||||||
|
report.append('Tests:')
|
||||||
|
for k, v in disk_obj.tests.items():
|
||||||
|
report.extend(debug_report_test(v, k))
|
||||||
|
|
||||||
|
# Done
|
||||||
|
return report
|
||||||
|
|
||||||
|
|
||||||
|
def debug_report_state(state):
|
||||||
|
"""Generate report for State, returns list."""
|
||||||
|
report = []
|
||||||
|
|
||||||
|
# Devs
|
||||||
|
report.append('CPU: {}'.format(state.cpu))
|
||||||
|
report.append('Disks: {}'.format(state.disks))
|
||||||
|
|
||||||
|
# Settings
|
||||||
|
report.append('Progress Out: {}'.format(state.progress_out))
|
||||||
|
report.append('Quick Mode: {}'.format(state.quick_mode))
|
||||||
|
|
||||||
|
# Tests
|
||||||
|
report.append('Tests:')
|
||||||
|
for k, v in state.tests.items():
|
||||||
|
report.append(' {}:'.format(k))
|
||||||
|
for k2, v2 in sorted(v.items()):
|
||||||
|
report.append(' {}: {}'.format(k2, v2))
|
||||||
|
|
||||||
|
# tmux
|
||||||
|
if hasattr(state, 'tmux_layout'):
|
||||||
|
report.append('tmux Layout:')
|
||||||
|
for k, v in state.tmux_layout.items():
|
||||||
|
report.append(' {}: {}'.format(k, str(v)))
|
||||||
|
if hasattr(state, 'panes'):
|
||||||
|
report.append('tmux Panes:')
|
||||||
|
for k, v in state.panes.items():
|
||||||
|
report.append(' {}: {}'.format(k, str(v)))
|
||||||
|
|
||||||
|
# Done
|
||||||
|
return report
|
||||||
|
|
||||||
|
|
||||||
|
def debug_report_test(test_obj, test_name):
|
||||||
|
"""Generate report for TestObj, returns list."""
|
||||||
|
report = [' {}:'.format(test_name)]
|
||||||
|
skip = ['update_status']
|
||||||
|
|
||||||
|
# Attributes
|
||||||
|
for a in [a for a in dir(test_obj) if not a.startswith('_')]:
|
||||||
|
if a in skip:
|
||||||
|
continue
|
||||||
|
report.append(' {}: {}'.format(a, getattr(test_obj, a)))
|
||||||
|
|
||||||
|
# Done
|
||||||
|
return report
|
||||||
|
|
||||||
|
|
||||||
|
def save_debug_reports(state, global_vars):
|
||||||
|
"""Save debug reports if possible."""
|
||||||
|
debug_dest = '{}/debug'.format(global_vars['LogDir'])
|
||||||
|
os.makedirs(debug_dest, exist_ok=True)
|
||||||
|
|
||||||
|
# State
|
||||||
|
with open('{}/state.report'.format(debug_dest), 'a') as f:
|
||||||
|
for line in debug_report_state(state):
|
||||||
|
f.write('{}\n'.format(line))
|
||||||
|
|
||||||
|
# CPU
|
||||||
|
with open('{}/cpu.report'.format(debug_dest), 'a') as f:
|
||||||
|
for line in debug_report_cpu(state.cpu):
|
||||||
|
f.write('{}\n'.format(line))
|
||||||
|
|
||||||
|
# Disk(s)
|
||||||
|
for disk in state.disks:
|
||||||
|
with open('{}/disk_{}.report'.format(debug_dest, disk.name), 'a') as f:
|
||||||
|
for line in debug_report_disk(disk):
|
||||||
|
f.write('{}\n'.format(line))
|
||||||
|
|
||||||
|
|
||||||
|
def upload_logdir(global_vars):
|
||||||
|
"""Upload compressed LogDir to CRASH_SERVER."""
|
||||||
|
source = global_vars['LogDir']
|
||||||
|
source = source[source.rfind('/')+1:]
|
||||||
|
dest = '{}.txz'.format(source)
|
||||||
|
data = None
|
||||||
|
|
||||||
|
# Compress LogDir
|
||||||
|
os.chdir('{}/..'.format(global_vars['LogDir']))
|
||||||
|
cmd = ['tar', 'caf', dest, source]
|
||||||
|
run_program(cmd)
|
||||||
|
|
||||||
|
# Read file
|
||||||
|
with open(dest, 'rb') as f:
|
||||||
|
data = f.read()
|
||||||
|
|
||||||
|
# Upload data
|
||||||
|
url = '{}/Crash_{}.txz'.format(CRASH_SERVER['Url'], source)
|
||||||
|
r = requests.put(
|
||||||
|
url,
|
||||||
|
data=data,
|
||||||
|
headers={'X-Requested-With': 'XMLHttpRequest'},
|
||||||
|
auth=(CRASH_SERVER['User'], CRASH_SERVER['Pass']))
|
||||||
|
# Raise exception if upload NS
|
||||||
|
if not r.ok:
|
||||||
|
raise GenericError
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
print("This file is not meant to be called directly.")
|
||||||
|
|
||||||
|
# vim: sts=2 sw=2 ts=2
|
||||||
|
|
@ -9,6 +9,8 @@ from functions.sensors import *
|
||||||
from functions.threading import *
|
from functions.threading import *
|
||||||
from functions.tmux import *
|
from functions.tmux import *
|
||||||
from settings.hw_diags import *
|
from settings.hw_diags import *
|
||||||
|
if DEBUG_MODE:
|
||||||
|
from debug.hw_diags import *
|
||||||
|
|
||||||
|
|
||||||
# Fix settings
|
# Fix settings
|
||||||
|
|
|
||||||
|
|
@ -26,8 +26,37 @@ if __name__ == '__main__':
|
||||||
# Normal exit
|
# Normal exit
|
||||||
pass
|
pass
|
||||||
except:
|
except:
|
||||||
|
# Cleanup
|
||||||
tmux_kill_all_panes()
|
tmux_kill_all_panes()
|
||||||
major_exception()
|
|
||||||
|
if DEBUG_MODE:
|
||||||
|
# Custom major exception
|
||||||
|
print_standard(' ')
|
||||||
|
print_error('Major exception')
|
||||||
|
print_warning(SUPPORT_MESSAGE)
|
||||||
|
print(traceback.format_exc())
|
||||||
|
print_log(traceback.format_exc())
|
||||||
|
|
||||||
|
# Save debug reports and upload data
|
||||||
|
try_and_print(
|
||||||
|
message='Saving debug reports...',
|
||||||
|
function=save_debug_reports,
|
||||||
|
state=state, global_vars=global_vars)
|
||||||
|
question = 'Upload crash details to {}?'.format(CRASH_SERVER['Name'])
|
||||||
|
if ENABLED_UPLOAD_DATA and ask(question):
|
||||||
|
try_and_print(
|
||||||
|
message='Uploading Data...',
|
||||||
|
function=upload_logdir,
|
||||||
|
global_vars=global_vars)
|
||||||
|
|
||||||
|
# Done
|
||||||
|
sleep(10)
|
||||||
|
pause('Press Enter to exit...')
|
||||||
|
exit_script(1)
|
||||||
|
|
||||||
|
else:
|
||||||
|
# "Normal" major exception
|
||||||
|
major_exception()
|
||||||
|
|
||||||
# Done
|
# Done
|
||||||
tmux_kill_all_panes()
|
tmux_kill_all_panes()
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,7 @@
|
||||||
from collections import OrderedDict
|
from collections import OrderedDict
|
||||||
|
|
||||||
# General
|
# General
|
||||||
|
DEBUG_MODE = False
|
||||||
OVERRIDES_FORCED = False
|
OVERRIDES_FORCED = False
|
||||||
OVERRIDES_LIMITED = True # If True this disables OVERRIDE_FORCED
|
OVERRIDES_LIMITED = True # If True this disables OVERRIDE_FORCED
|
||||||
STATUSES = {
|
STATUSES = {
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue