186 lines
4.4 KiB
Python
186 lines
4.4 KiB
Python
# 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, reason='Crash'):
|
|
"""Upload compressed LogDir to CRASH_SERVER."""
|
|
source = global_vars['LogDir']
|
|
source = source[source.rfind('/')+1:]
|
|
dest = 'HW-Diags_{reason}_{Date-Time}.txz'.format(
|
|
reason=reason,
|
|
**global_vars,
|
|
)
|
|
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 = '{}/{}'.format(CRASH_SERVER['Url'], dest)
|
|
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
|