Added osTicket report sections
This commit is contained in:
parent
2372fb0d2f
commit
57572c7527
2 changed files with 162 additions and 0 deletions
|
|
@ -102,6 +102,7 @@ class CpuObj():
|
||||||
self.tests = OrderedDict()
|
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')
|
||||||
|
self.description = self.name
|
||||||
|
|
||||||
def get_details(self):
|
def get_details(self):
|
||||||
"""Get CPU details from lscpu."""
|
"""Get CPU details from lscpu."""
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,11 @@ import mysql.connector as mariadb
|
||||||
from functions.common import *
|
from functions.common import *
|
||||||
from settings.osticket import *
|
from settings.osticket import *
|
||||||
|
|
||||||
|
# Regex
|
||||||
|
REGEX_BLOCK_GRAPH = re.compile(r'(▁|▂|▃|▄|▅|▆|▇|█)')
|
||||||
|
REGEX_NVME_SMART_ATTRIBUTES = re.compile(r'^\s*(\d+) / (\w+): (.{28})(.*)$')
|
||||||
|
REGEX_TEMPS = re.compile(r'^\s*(.*?)\s+(idle.*)$')
|
||||||
|
|
||||||
# Classes
|
# Classes
|
||||||
class osTicket():
|
class osTicket():
|
||||||
"""Class to track osTicket data and functions."""
|
"""Class to track osTicket data and functions."""
|
||||||
|
|
@ -171,6 +176,162 @@ class osTicket():
|
||||||
self.disconnect()
|
self.disconnect()
|
||||||
|
|
||||||
# Functions
|
# Functions
|
||||||
|
def convert_report(name, test):
|
||||||
|
"""Convert report into an osTicket friendly format, returns list."""
|
||||||
|
out_report = []
|
||||||
|
source_report = test.source_report
|
||||||
|
status = strip_colors(test.status)
|
||||||
|
status = status.replace(test.label, '').strip()
|
||||||
|
|
||||||
|
# Header
|
||||||
|
index = 1
|
||||||
|
if name == 'NVMe / SMART':
|
||||||
|
out_report.append('{} ({})'.format(name, status))
|
||||||
|
if not source_report:
|
||||||
|
index = 0
|
||||||
|
source_report = test.dev.generate_attribute_source_report()
|
||||||
|
else:
|
||||||
|
out_report.append('{} ({})'.format(strip_colors(source_report[0]), status))
|
||||||
|
|
||||||
|
# Body
|
||||||
|
for line in source_report[index:]:
|
||||||
|
# Remove colors and leading spaces
|
||||||
|
line = strip_colors(line)
|
||||||
|
if line[:2] == ' ':
|
||||||
|
line = line[2:]
|
||||||
|
|
||||||
|
# Test-specific modifications
|
||||||
|
if name == 'Prime95':
|
||||||
|
r = REGEX_TEMPS.match(line)
|
||||||
|
if r:
|
||||||
|
_sensor = '{:<20}'.format(r.group(1))
|
||||||
|
_temps = r.group(2)
|
||||||
|
line = '{} {}'.format(
|
||||||
|
pad_with_dots(_sensor, pad_right=True),
|
||||||
|
_temps)
|
||||||
|
elif name == 'NVMe / SMART':
|
||||||
|
r = REGEX_NVME_SMART_ATTRIBUTES.match(line)
|
||||||
|
if r:
|
||||||
|
_dec = '{:>3}'.format(r.group(1))
|
||||||
|
_hex = r.group(2)
|
||||||
|
_atr = r.group(3).strip()
|
||||||
|
_val = '{:<20}'.format(r.group(4))
|
||||||
|
line = '{}/{}: {} {}'.format(
|
||||||
|
_hex,
|
||||||
|
pad_with_dots(_dec),
|
||||||
|
pad_with_dots(_val, pad_right=True),
|
||||||
|
_atr)
|
||||||
|
elif name == 'I/O Benchmark':
|
||||||
|
line = REGEX_BLOCK_GRAPH.sub('', line)
|
||||||
|
line = line.strip()
|
||||||
|
if not line:
|
||||||
|
continue
|
||||||
|
|
||||||
|
# Remove extra spaces
|
||||||
|
line = line.strip()
|
||||||
|
line = re.sub(r'(\s+)', ' ', line)
|
||||||
|
|
||||||
|
# Add line to report
|
||||||
|
out_report.append(line)
|
||||||
|
|
||||||
|
# Done
|
||||||
|
return out_report
|
||||||
|
|
||||||
|
def get_device_overall_results(dev):
|
||||||
|
"""Get overall results from tests for device, returns dict."""
|
||||||
|
results = {
|
||||||
|
'Dev Type': 'Unknown',
|
||||||
|
'Full Diag': False,
|
||||||
|
'Asterisk': None,
|
||||||
|
'Failed': 0,
|
||||||
|
'N/A': 0,
|
||||||
|
'Passed': 0,
|
||||||
|
'Status': 'Unknown',
|
||||||
|
}
|
||||||
|
|
||||||
|
# Get test list for device type
|
||||||
|
test_list = []
|
||||||
|
if isinstance(dev, CpuObj):
|
||||||
|
results['Dev Type'] = 'CPU'
|
||||||
|
test_list = TESTS_CPU
|
||||||
|
elif isinstance(dev, DiskObj):
|
||||||
|
results['Dev Type'] = 'Disk'
|
||||||
|
test_list = TESTS_DISK
|
||||||
|
else:
|
||||||
|
raise GenericError('Unrecognized device type.')
|
||||||
|
|
||||||
|
# Check if a full diag was run (i.e. all dev tests were enabled)
|
||||||
|
results['Full Diag'] = len(dev.tests) == len(test_list)
|
||||||
|
|
||||||
|
# Tally test results
|
||||||
|
for test in dev.tests.value():
|
||||||
|
if test.failed:
|
||||||
|
results['Failed'] += 1
|
||||||
|
if test.passed:
|
||||||
|
results['Passed'] += 1
|
||||||
|
if 'N/A' in test.status:
|
||||||
|
results['N/A'] += 1
|
||||||
|
|
||||||
|
# Set overall status
|
||||||
|
if results['Failed'] > 0:
|
||||||
|
dev.checkbox = False
|
||||||
|
results['Status'] = 'FAILED'
|
||||||
|
elif results['Passed'] + results['N/A'] == len(dev.tests):
|
||||||
|
dev.checkbox = True
|
||||||
|
results['Status'] = 'PASSED'
|
||||||
|
else:
|
||||||
|
results['Status'] = 'UNKNOWN'
|
||||||
|
if results['Full Diag'] and results['N/A'] > 0:
|
||||||
|
results['Asterisk'] = True
|
||||||
|
results['Status'] += '*'
|
||||||
|
|
||||||
|
# Done
|
||||||
|
return results
|
||||||
|
|
||||||
|
def generate_osticket_report(dev):
|
||||||
|
"""Generate device report for osTicket, returns list."""
|
||||||
|
report = []
|
||||||
|
results = get_device_overall_results(dev)
|
||||||
|
|
||||||
|
# Header
|
||||||
|
if results['Full Diag']:
|
||||||
|
report.append(
|
||||||
|
'{Dev Type} hardware diagnostic tests: {Status}'.format(**results))
|
||||||
|
report.append(' ')
|
||||||
|
|
||||||
|
# Device
|
||||||
|
report.append(dev.description)
|
||||||
|
report.append(' ')
|
||||||
|
|
||||||
|
# Test reports
|
||||||
|
for name, test in dev.tests.items():
|
||||||
|
report.extend(convert_report(name, test))
|
||||||
|
if name == 'I/O Benchmark':
|
||||||
|
# TODO: Create PNG graph and upload to imgur/Nextcloud
|
||||||
|
report.append('Imgur: TODO')
|
||||||
|
report.append('Nextcloud: TODO')
|
||||||
|
report.append(' ')
|
||||||
|
|
||||||
|
# Volumes
|
||||||
|
if results['Dev Type'] == 'Disk':
|
||||||
|
# TODO: Mount all volumes and extend report
|
||||||
|
report.append('Volumes:')
|
||||||
|
report.append('TODO')
|
||||||
|
report.append(' ')
|
||||||
|
|
||||||
|
# Asterisk
|
||||||
|
if results['Asterisk']:
|
||||||
|
report.append('* NOTE: One or more tests were not run on this device')
|
||||||
|
|
||||||
|
def pad_with_dots(s, pad_right=False):
|
||||||
|
"""Replace space padding with dots, returns str."""
|
||||||
|
s = str(s).replace(' ', '..')
|
||||||
|
if '.' in s:
|
||||||
|
if pad_right:
|
||||||
|
s = s + '.'
|
||||||
|
else:
|
||||||
|
s = '.' + s
|
||||||
|
return s
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
print("This file is not meant to be called directly.")
|
print("This file is not meant to be called directly.")
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue