Posting CPU results is working
This commit is contained in:
parent
ad6980f82b
commit
8d6b29be53
2 changed files with 95 additions and 66 deletions
|
|
@ -138,6 +138,7 @@ class CpuObj():
|
||||||
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):
|
||||||
|
self.checkbox = None
|
||||||
self.disk_ok = True
|
self.disk_ok = True
|
||||||
self.labels = []
|
self.labels = []
|
||||||
self.lsblk = {}
|
self.lsblk = {}
|
||||||
|
|
|
||||||
|
|
@ -5,18 +5,24 @@ import mysql.connector as mariadb
|
||||||
from functions.common import *
|
from functions.common import *
|
||||||
from settings.osticket import *
|
from settings.osticket import *
|
||||||
|
|
||||||
|
# STATIC VARIABLES
|
||||||
|
KNOWN_DEV_TYPES = ('CPU', 'Disk')
|
||||||
|
|
||||||
# Regex
|
# Regex
|
||||||
REGEX_BLOCK_GRAPH = re.compile(r'(▁|▂|▃|▄|▅|▆|▇|█)')
|
REGEX_BLOCK_GRAPH = re.compile(r'(▁|▂|▃|▄|▅|▆|▇|█)')
|
||||||
REGEX_NVME_SMART_ATTRIBUTES = re.compile(r'^\s*(\d+) / (\w+): (.{28})(.*)$')
|
REGEX_NVME_SMART_ATTRIBUTES = re.compile(r'^\s*(\d+) / (\w+): (.{28})(.*)$')
|
||||||
REGEX_TEMPS = re.compile(r'^\s*(.*?)\s+(idle.*)$')
|
REGEX_TEMPS = re.compile(r'^\s*(.*?)\s+(idle.*)$')
|
||||||
|
REGEX_SENSOR = re.compile(r'^(.*?)(\s*)$')
|
||||||
|
|
||||||
# Classes
|
# Classes
|
||||||
class osTicket():
|
class osTicket():
|
||||||
"""Class to track osTicket data and functions."""
|
"""Class to track osTicket data and functions."""
|
||||||
def __init__(self):
|
def __init__(self, tests_cpu, tests_disk):
|
||||||
self.db_connection = None
|
self.db_connection = None
|
||||||
self.db_cursor = None
|
self.db_cursor = None
|
||||||
self.errors = False
|
self.errors = False
|
||||||
|
self.tests_cpu = tests_cpu
|
||||||
|
self.tests_disk = tests_disk
|
||||||
self.tunnel_proc = None
|
self.tunnel_proc = None
|
||||||
|
|
||||||
def connect(self):
|
def connect(self):
|
||||||
|
|
@ -49,10 +55,10 @@ class osTicket():
|
||||||
# Connection established
|
# Connection established
|
||||||
break
|
break
|
||||||
|
|
||||||
def convert_report(name, test):
|
def convert_report(self, name, test):
|
||||||
"""Convert report into an osTicket friendly format, returns list."""
|
"""Convert report into an osTicket friendly format, returns list."""
|
||||||
out_report = []
|
out_report = []
|
||||||
source_report = test.source_report
|
source_report = test.report
|
||||||
status = strip_colors(test.status)
|
status = strip_colors(test.status)
|
||||||
status = status.replace(test.label, '').strip()
|
status = status.replace(test.label, '').strip()
|
||||||
|
|
||||||
|
|
@ -62,7 +68,7 @@ class osTicket():
|
||||||
out_report.append('{} ({})'.format(name, status))
|
out_report.append('{} ({})'.format(name, status))
|
||||||
if not source_report:
|
if not source_report:
|
||||||
index = 0
|
index = 0
|
||||||
source_report = test.dev.generate_attribute_source_report()
|
source_report = test.dev.generate_attribute_report()
|
||||||
else:
|
else:
|
||||||
out_report.append('{} ({})'.format(strip_colors(source_report[0]), status))
|
out_report.append('{} ({})'.format(strip_colors(source_report[0]), status))
|
||||||
|
|
||||||
|
|
@ -79,9 +85,10 @@ class osTicket():
|
||||||
if r:
|
if r:
|
||||||
_sensor = '{:<20}'.format(r.group(1))
|
_sensor = '{:<20}'.format(r.group(1))
|
||||||
_temps = r.group(2)
|
_temps = r.group(2)
|
||||||
line = '{} {}'.format(
|
r2 = REGEX_SENSOR.match(_sensor)
|
||||||
pad_with_dots(_sensor, pad_right=True),
|
_sensor = r2.group(1)
|
||||||
_temps)
|
_spacer = pad_with_dots(r2.group(2))
|
||||||
|
line = '{}{} {}'.format(_sensor, _spacer, _temps)
|
||||||
elif name == 'NVMe / SMART':
|
elif name == 'NVMe / SMART':
|
||||||
r = REGEX_NVME_SMART_ATTRIBUTES.match(line)
|
r = REGEX_NVME_SMART_ATTRIBUTES.match(line)
|
||||||
if r:
|
if r:
|
||||||
|
|
@ -110,10 +117,10 @@ class osTicket():
|
||||||
# Done
|
# Done
|
||||||
return out_report
|
return out_report
|
||||||
|
|
||||||
def generate_report(dev):
|
def generate_report(self, dev):
|
||||||
"""Generate device report for osTicket, returns list."""
|
"""Generate device report for osTicket, returns list."""
|
||||||
report = []
|
report = []
|
||||||
results = get_device_overall_results(dev)
|
results = self.get_device_overall_results(dev)
|
||||||
|
|
||||||
# Header
|
# Header
|
||||||
if results['Full Diag']:
|
if results['Full Diag']:
|
||||||
|
|
@ -127,7 +134,7 @@ class osTicket():
|
||||||
|
|
||||||
# Test reports
|
# Test reports
|
||||||
for name, test in dev.tests.items():
|
for name, test in dev.tests.items():
|
||||||
report.extend(convert_report(name, test))
|
report.extend(self.convert_report(name, test))
|
||||||
if name == 'I/O Benchmark':
|
if name == 'I/O Benchmark':
|
||||||
# TODO: Create PNG graph and upload to imgur/Nextcloud
|
# TODO: Create PNG graph and upload to imgur/Nextcloud
|
||||||
report.append('Imgur: TODO')
|
report.append('Imgur: TODO')
|
||||||
|
|
@ -165,11 +172,74 @@ class osTicket():
|
||||||
self.db_cursor = None
|
self.db_cursor = None
|
||||||
self.db_connection = None
|
self.db_connection = None
|
||||||
|
|
||||||
|
def get_device_overall_results(self, dev):
|
||||||
|
"""Get overall results from tests for device, returns dict."""
|
||||||
|
results = {
|
||||||
|
'Dev Type': self.get_device_type(dev),
|
||||||
|
'Full Diag': False,
|
||||||
|
'Asterisk': None,
|
||||||
|
'Failed': 0,
|
||||||
|
'N/A': 0,
|
||||||
|
'Passed': 0,
|
||||||
|
'Status': 'Unknown',
|
||||||
|
}
|
||||||
|
|
||||||
|
# Bail on unknown device type
|
||||||
|
if results['Dev Type'] not in KNOWN_DEV_TYPES:
|
||||||
|
raise GenericError(
|
||||||
|
'Unrecognized device type: {}.'.format(results['Dev Type']))
|
||||||
|
|
||||||
|
# Get test list for device type
|
||||||
|
test_list = []
|
||||||
|
if results['Dev Type'] == 'CPU':
|
||||||
|
test_list = self.tests_cpu
|
||||||
|
elif results['Dev Type'] == 'Disk':
|
||||||
|
test_list = self.tests_disk
|
||||||
|
|
||||||
|
# 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.values():
|
||||||
|
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 get_device_type(self, dev):
|
||||||
|
"""Terrible hack to determine device type, returns str."""
|
||||||
|
# TODO: Fix with proper isinstance() call
|
||||||
|
type_str = str(dev.__class__)
|
||||||
|
if 'CpuObj' in type_str:
|
||||||
|
type_str = 'CPU'
|
||||||
|
elif 'DiskObj' in type_str:
|
||||||
|
type_str = 'Disk'
|
||||||
|
|
||||||
|
return type_str
|
||||||
|
|
||||||
def get_ticket_name(self, ticket_id):
|
def get_ticket_name(self, ticket_id):
|
||||||
"""Lookup ticket and return name as str."""
|
"""Lookup ticket and return name as str."""
|
||||||
name = None
|
name = None
|
||||||
sql_cmd = "SELECT name FROM `{Ticket}`".format(**OSTICKET['Tables'])
|
sql_cmd = "SELECT name FROM `{Ticket}`".format(**OSTICKET['Tables'])
|
||||||
sql_cmd += " WHERE `ticket_id` = `{}`".format(ticket_id)
|
sql_cmd += " WHERE `ticket_id` = {}".format(ticket_id)
|
||||||
sql_cmd += ";"
|
sql_cmd += ";"
|
||||||
# TODO: Is the ';' needed above? It wasn't in the prev version??
|
# TODO: Is the ';' needed above? It wasn't in the prev version??
|
||||||
|
|
||||||
|
|
@ -183,9 +253,13 @@ class osTicket():
|
||||||
# TODO: Fix exception handling
|
# TODO: Fix exception handling
|
||||||
self.errors = True
|
self.errors = True
|
||||||
|
|
||||||
|
# Done
|
||||||
|
return name
|
||||||
|
|
||||||
def get_ticket_number(self):
|
def get_ticket_number(self):
|
||||||
"""Get ticket number and confirm with name from osTicket DB."""
|
"""Get ticket number and confirm with name from osTicket DB."""
|
||||||
ticket_number = None
|
ticket_number = None
|
||||||
|
self.connect()
|
||||||
|
|
||||||
# Main loop
|
# Main loop
|
||||||
while ticket_number is None:
|
while ticket_number is None:
|
||||||
|
|
@ -199,7 +273,7 @@ class osTicket():
|
||||||
break
|
break
|
||||||
|
|
||||||
# Invalid ID entered
|
# Invalid ID entered
|
||||||
if not re.match(r'^([0-9]+)$', _input):
|
if not re.match(r'^(\d+)$', _input):
|
||||||
continue
|
continue
|
||||||
|
|
||||||
# Valid ID entered, lookup name and verify
|
# Valid ID entered, lookup name and verify
|
||||||
|
|
@ -211,17 +285,22 @@ class osTicket():
|
||||||
ticket_number = _input
|
ticket_number = _input
|
||||||
|
|
||||||
# Done
|
# Done
|
||||||
|
self.disconnect()
|
||||||
return ticket_number
|
return ticket_number
|
||||||
|
|
||||||
def post_device_results(self, dev, ticket_id):
|
def post_device_results(self, dev, ticket_id):
|
||||||
"""Generate osTicket friendly report and post as response to ticket."""
|
"""Generate osTicket friendly report and post as response to ticket."""
|
||||||
response = self.generate_report(dev)
|
response = self.generate_report(dev)
|
||||||
post_response(response, ticket_id)
|
self.post_response(response, ticket_id)
|
||||||
|
|
||||||
def post_response(self, response, ticket_id):
|
def post_response(self, response, ticket_id):
|
||||||
"""Post a reply to a ticket in osTicket."""
|
"""Post a reply to a ticket in osTicket."""
|
||||||
self.connect()
|
self.connect()
|
||||||
|
|
||||||
|
# Convert response to string
|
||||||
|
response = '\n'.join(response)
|
||||||
|
response = response.replace('`', '')
|
||||||
|
|
||||||
# Build SQL cmd
|
# Build SQL cmd
|
||||||
sql_cmd = "INSERT INTO `{Name}`.`{Response}`".format(
|
sql_cmd = "INSERT INTO `{Name}`.`{Response}`".format(
|
||||||
**OSTICKET['Database'], **OSTICKET['Tables'])
|
**OSTICKET['Database'], **OSTICKET['Tables'])
|
||||||
|
|
@ -235,7 +314,7 @@ class osTicket():
|
||||||
|
|
||||||
# Run SQL cmd
|
# Run SQL cmd
|
||||||
try:
|
try:
|
||||||
self.cursor.execute(sql_cmd)
|
self.db_cursor.execute(sql_cmd)
|
||||||
except Exception:
|
except Exception:
|
||||||
# TODO: Fix exception handling
|
# TODO: Fix exception handling
|
||||||
self.errors = True
|
self.errors = True
|
||||||
|
|
@ -271,7 +350,7 @@ class osTicket():
|
||||||
|
|
||||||
# Run SQL cmd
|
# Run SQL cmd
|
||||||
try:
|
try:
|
||||||
self.cursor.execute(sql_cmd)
|
self.db_cursor.execute(sql_cmd)
|
||||||
except Exception:
|
except Exception:
|
||||||
# TODO: Fix exception handling
|
# TODO: Fix exception handling
|
||||||
self.errors = True
|
self.errors = True
|
||||||
|
|
@ -280,57 +359,6 @@ class osTicket():
|
||||||
self.disconnect()
|
self.disconnect()
|
||||||
|
|
||||||
# Functions
|
# Functions
|
||||||
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 pad_with_dots(s, pad_right=False):
|
def pad_with_dots(s, pad_right=False):
|
||||||
"""Replace space padding with dots, returns str."""
|
"""Replace space padding with dots, returns str."""
|
||||||
s = str(s).replace(' ', '..')
|
s = str(s).replace(' ', '..')
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue