From a909153deaf2d0d18f60f28c73aeb6fd9493d44e Mon Sep 17 00:00:00 2001 From: Simon Rettberg Date: Mon, 4 Feb 2019 15:05:44 +0100 Subject: Sanitize file names --- bwLpStatus.py | 273 ---------------------------------------------- bwlpMonitor_template.html | 155 -------------------------- main.py | 273 ++++++++++++++++++++++++++++++++++++++++++++++ template.html | 155 ++++++++++++++++++++++++++ 4 files changed, 428 insertions(+), 428 deletions(-) delete mode 100755 bwLpStatus.py delete mode 100644 bwlpMonitor_template.html create mode 100755 main.py create mode 100644 template.html diff --git a/bwLpStatus.py b/bwLpStatus.py deleted file mode 100755 index 59f37b8..0000000 --- a/bwLpStatus.py +++ /dev/null @@ -1,273 +0,0 @@ -#!/usr/bin/python3 -import subprocess -import urllib.request -import urllib.error -import thriftpy -from thriftpy.rpc import make_client -from thriftpy.transport import TFramedTransportFactory -import shutil -import datetime -import os -import tftpy -import logging - -# Global variables -statusList = [] -logEntries = [] -newLogIndex = 0 - -# Class of the status objects -class Status: - def __init__(self, name, host, state, status, service, msg = '', data = []): - # Name of the service. - self.name = name - - # Hostname (Domain, ip, ...) - self.host = host - - # State of the response. (success, warning, error) <-- This class is responsible for the coloring (green, orange, red) - self.state = state - - # Status of the check. (Online, Offline, Temporaily not available, Some services unavailable, ...) <-- This text is shown on the website - self.status = status - - # Type of the service. (ping, https, tftp, thrift, ...) - self.service = service - - # Message e.g. error message - self.msg = msg - - # Data the request return e.g. organisation list from the thrift client. - self.data = data - -class LogEntry: - def __init__(self, date, service, state, host, msg = '', data = []): - self.date = date - self.host = host - self.service = service - self.state = state - self.msg = msg - self.data = data - -class Organisation: - def __init__(self, id, name): - self.id = id - self.name = name - - def __repr__(self): - return str(self.__dict__) - -# Check connection functions. -def ping(name, hostname): - # Ping a hostname and tell if the server is up or down. - print('Ping request ' + hostname + ' ... ', end='') - response = subprocess.Popen( - ['ping', '-c', '1', hostname], - stdout=subprocess.PIPE, - stderr=subprocess.PIPE - ) - response = response.communicate() - error = response[1].decode('utf-8') - - # Error happend - if error != '': - print('\033[91m' + 'error' + '\033[0m') - statusList.append(Status(name, hostname, 'error', 'Offline', 'ping', error.rstrip())) - else: - print('\033[92m' + 'success' + '\033[0m') - statusList.append(Status(name, hostname, 'success', 'Online', 'ping')) - - logStatus(statusList[-1]) - -def https(name, url): - print('HTTPS request ' + url + ' ... ', end='') - try: - r = urllib.request.urlopen(url) - if r.getcode() == 200: - statusList.append(Status(name, url, 'success', 'Online', 'https')) - print('\033[92m' + 'success' + '\033[0m') - else: - statusList.append(Status(name, url, 'error', 'Offline', 'https')) - print('\033[91m' + 'error' + '\033[0m') - - except urllib.error.URLError as e: - statusList.append(Status(name, url, 'error', 'Offline', 'https', msg=str(e))) - print('\033[91m' + 'error' + '\033[0m') - except ValueError: - statusList.append(Status(name, url, 'error', 'Offline', 'https', msg="Unknown url type")) - print('\033[91m' + 'error' + '\033[0m') - finally: - logStatus(statusList[-1]) - -def tftp(name, host, port, filename): - print('TFTP request ' + host + ' ...', end='') - hostname = host + ':' + str(port) + ':' + filename - try: - client = tftpy.TftpClient(host, port) - client.download(filename, 'tmp_tftp_file') - print('\033[92m' + 'success' + '\033[0m') - # Delete tmp tftp file - os.remove('tmp_tftp_file') - statusList.append(Status(name, hostname, 'success', 'Online', 'tftp', msg='File ' + filename + ' downloaded successfully.')) - except Exception as e: - print('\033[91m' + 'error' + '\033[0m') - statusList.append(Status(name, hostname, 'error', 'Offline', 'tftp', msg=str(e))) - finally: - logStatus(statusList[-1]) - -# Creates the thrift client and prwlp-pxe.ruf.uni-freiburg.de .ceeds the get Organisations call. Server can either be SAT or MASTER -def thrift(name, ip, port, server): - host = ip + ':' + str(port) - print('THRIFT request ' + host + ' ...', end='') - bwlp_thrift = thriftpy.load('bwlp.thrift', module_name='bwlp_thrift') - - organisations = [] - # Different clients for SAT / Master is needed. - try: - if server == 'SAT': - satserver = make_client(bwlp_thrift.SatelliteServer, ip, port, trans_factory=TFramedTransportFactory()) - organisations = satserver.getAllOrganizations() - - elif server == 'MASTER': - masterserver = make_client(bwlp_thrift.MasterServer, ip, port, trans_factory=TFramedTransportFactory()) - organisations = masterserver.getOrganizations() - - organisationList = [] - for org in organisations: - organisationList.append(Organisation(org.organizationId, org.displayName)) - - if len(organisationList) == 0: - statusList.append(Status(name, host, 'warning', 'Online (' + str(len(organisationList)) + ')', 'thrift', msg=str(len(organisationList)) + " organizations found",data=organisationList)) - else: - statusList.append(Status(name, host, 'success', 'Online (' + str(len(organisationList)) + ')', 'thrift', msg=str(len(organisationList)) + " organizations found",data=organisationList)) - print('\033[92m' + 'success' + '\033[0m') - except ConnectionResetError: - statusList.append(Status(name, host, 'error', 'Offline', 'thrift', msg="ConnectionResetError: [Errno 104] Connection reset by peer")) - print('\033[91m' + 'error' + '\033[0m') - finally: - logStatus(statusList[-1]) - -# Parses the log from the logfile. Fills the logEntries array. -def parseLog(): - global logEntries - if not (os.path.exists('bwLpStatusLog.txt')): - return - with open('bwLpStatusLog.txt', 'r') as log: - for line in log: - line = line.strip() - entry = line.split('\t') - if len(entry) < 4: continue - logEntries.append(LogEntry(entry[0], entry[1], entry[2], entry[3], '' if len(entry) < 5 else entry[4], [] if len(entry) < 6 else entry[5])) - - global newLogIndex - newLogIndex = len(logEntries) - -# Writes updated log in the logfile. -def writeLog(): - with open('bwLpStatusLog.txt', 'a') as log: - for entry in logEntries[newLogIndex:]: - log_string = entry.date + '\t' + entry.service + '\t' + entry.state + '\t' + entry.host - log_string += '\t' + str(entry.msg) - log_string += '\t' + str(entry.data) - log.write(log_string + '\n') - -# Returns the most recent log object to a given status. None if there is none. -def getLogEntry(status): - return next((x for x in reversed(logEntries) if (x.host == status.host) and (x.service == status.service)), None) - -# Checks weather the status has to be logged or not. (Does the status has changes from the last time?) -def logStatus(status): - obj = getLogEntry(status) - if (obj is None) or (status.state != obj.state): - date = datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S') - logEntries.append(LogEntry(date, status.service, status.state, status.host, status.msg, status.data)) - -# Reads the config and executes the calls. -def readConfig(): - if not (os.path.exists('bwlp.config')): - return - with open('bwlp.config', 'r') as config: - for line in config: - line = line.strip() - entry = line.split('\t') - if entry[0] == '#': continue - check(entry) - -# Calls the check method. -def check(entry): - if entry[0] == 'ping': - if (len(entry) < 3): return - ping(entry[1], entry[2]) - elif entry[0] == 'https': - if (len(entry) < 3): return - https(entry[1], entry[2]) - elif entry[0] == 'thrift': - if (len(entry) < 5): return - thrift(entry[1], entry[2], int(entry[3]), entry[4]) - elif entry[0] == 'tftp': - if (len(entry) < 5): return - tftp(entry[1], entry[2], int(entry[3]), entry[4]) - -# Parse the logfile. -parseLog() - -# Call the checks. -readConfig() - -# Write the new logfile. -writeLog() - -# HTML Processing to generate the website. -code = '\r\n' -for status in statusList: - # Prepare and calculate the time since the server is online / offline - obj = getLogEntry(status) - now = datetime.datetime.now() - date = datetime.datetime.strptime(obj.date, '%Y-%m-%d %H:%M:%S') - time = now - date - days = time.days - hours = time.seconds // 3600 - minutes = (time.seconds // 60) % 60 - timeString = '' - if days > 0: - timeString += str(days) + ' days ' - if hours > 0: - timeString += str(hours) + ' hours ' - if minutes > 0: - timeString += str(minutes) + ' minutes' - - code += ('
' - + status.name + '
' - + status.host + '
' - + status.status + '
' - + timeString + '
\r\n') - -# Generate the html code for the log. -log = '\r\n' - -# Cut the log to the last n entries -n = 500 -cut_amount = 0 -if len(logEntries) >= n: - cut_amount = len(logEntries) - n -for entry in reversed(logEntries[cut_amount:]): - log += ('
[' - + entry.date + ']
[' - + entry.service + ']
[' - + entry.state + ']
[' - + entry.host +']
' - + entry.msg + '
') - -# Copy the .html file and replace the %CONTENT% to generate the final html file. -shutil.copyfile('bwlpMonitor_template.html', 'bwlpMonitor.html') - -# Replace the %CONTENT% in the template with the actual html code. -html = open('bwlpMonitor_template.html') -html2 = open('bwlpMonitor.html', 'w') -for line in html: - html2.write(line.replace('%CONTENT%', code).replace('%LOG%', log)) - -html.close() -html2.close() diff --git a/bwlpMonitor_template.html b/bwlpMonitor_template.html deleted file mode 100644 index f05c233..0000000 --- a/bwlpMonitor_template.html +++ /dev/null @@ -1,155 +0,0 @@ - - - - - - - bwLp Status Monitor - - - -
-
-%CONTENT% -
-
-
-%LOG% -
-
-
- - - - - - \ No newline at end of file diff --git a/main.py b/main.py new file mode 100755 index 0000000..489c1cc --- /dev/null +++ b/main.py @@ -0,0 +1,273 @@ +#!/usr/bin/python3 +import subprocess +import urllib.request +import urllib.error +import thriftpy +from thriftpy.rpc import make_client +from thriftpy.transport import TFramedTransportFactory +import shutil +import datetime +import os +import tftpy +import logging + +# Global variables +statusList = [] +logEntries = [] +newLogIndex = 0 + +# Class of the status objects +class Status: + def __init__(self, name, host, state, status, service, msg = '', data = []): + # Name of the service. + self.name = name + + # Hostname (Domain, ip, ...) + self.host = host + + # State of the response. (success, warning, error) <-- This class is responsible for the coloring (green, orange, red) + self.state = state + + # Status of the check. (Online, Offline, Temporaily not available, Some services unavailable, ...) <-- This text is shown on the website + self.status = status + + # Type of the service. (ping, https, tftp, thrift, ...) + self.service = service + + # Message e.g. error message + self.msg = msg + + # Data the request return e.g. organisation list from the thrift client. + self.data = data + +class LogEntry: + def __init__(self, date, service, state, host, msg = '', data = []): + self.date = date + self.host = host + self.service = service + self.state = state + self.msg = msg + self.data = data + +class Organisation: + def __init__(self, id, name): + self.id = id + self.name = name + + def __repr__(self): + return str(self.__dict__) + +# Check connection functions. +def ping(name, hostname): + # Ping a hostname and tell if the server is up or down. + print('Ping request ' + hostname + ' ... ', end='') + response = subprocess.Popen( + ['ping', '-c', '1', hostname], + stdout=subprocess.PIPE, + stderr=subprocess.PIPE + ) + response = response.communicate() + error = response[1].decode('utf-8') + + # Error happend + if error != '': + print('\033[91m' + 'error' + '\033[0m') + statusList.append(Status(name, hostname, 'error', 'Offline', 'ping', error.rstrip())) + else: + print('\033[92m' + 'success' + '\033[0m') + statusList.append(Status(name, hostname, 'success', 'Online', 'ping')) + + logStatus(statusList[-1]) + +def https(name, url): + print('HTTPS request ' + url + ' ... ', end='') + try: + r = urllib.request.urlopen(url) + if r.getcode() == 200: + statusList.append(Status(name, url, 'success', 'Online', 'https')) + print('\033[92m' + 'success' + '\033[0m') + else: + statusList.append(Status(name, url, 'error', 'Offline', 'https')) + print('\033[91m' + 'error' + '\033[0m') + + except urllib.error.URLError as e: + statusList.append(Status(name, url, 'error', 'Offline', 'https', msg=str(e))) + print('\033[91m' + 'error' + '\033[0m') + except ValueError: + statusList.append(Status(name, url, 'error', 'Offline', 'https', msg="Unknown url type")) + print('\033[91m' + 'error' + '\033[0m') + finally: + logStatus(statusList[-1]) + +def tftp(name, host, port, filename): + print('TFTP request ' + host + ' ...', end='') + hostname = host + ':' + str(port) + ':' + filename + try: + client = tftpy.TftpClient(host, port) + client.download(filename, 'tmp_tftp_file') + print('\033[92m' + 'success' + '\033[0m') + # Delete tmp tftp file + os.remove('tmp_tftp_file') + statusList.append(Status(name, hostname, 'success', 'Online', 'tftp', msg='File ' + filename + ' downloaded successfully.')) + except Exception as e: + print('\033[91m' + 'error' + '\033[0m') + statusList.append(Status(name, hostname, 'error', 'Offline', 'tftp', msg=str(e))) + finally: + logStatus(statusList[-1]) + +# Creates the thrift client and prwlp-pxe.ruf.uni-freiburg.de .ceeds the get Organisations call. Server can either be SAT or MASTER +def thrift(name, ip, port, server): + host = ip + ':' + str(port) + print('THRIFT request ' + host + ' ...', end='') + bwlp_thrift = thriftpy.load('bwlp.thrift', module_name='bwlp_thrift') + + organisations = [] + # Different clients for SAT / Master is needed. + try: + if server == 'SAT': + satserver = make_client(bwlp_thrift.SatelliteServer, ip, port, trans_factory=TFramedTransportFactory()) + organisations = satserver.getAllOrganizations() + + elif server == 'MASTER': + masterserver = make_client(bwlp_thrift.MasterServer, ip, port, trans_factory=TFramedTransportFactory()) + organisations = masterserver.getOrganizations() + + organisationList = [] + for org in organisations: + organisationList.append(Organisation(org.organizationId, org.displayName)) + + if len(organisationList) == 0: + statusList.append(Status(name, host, 'warning', 'Online (' + str(len(organisationList)) + ')', 'thrift', msg=str(len(organisationList)) + " organizations found",data=organisationList)) + else: + statusList.append(Status(name, host, 'success', 'Online (' + str(len(organisationList)) + ')', 'thrift', msg=str(len(organisationList)) + " organizations found",data=organisationList)) + print('\033[92m' + 'success' + '\033[0m') + except ConnectionResetError: + statusList.append(Status(name, host, 'error', 'Offline', 'thrift', msg="ConnectionResetError: [Errno 104] Connection reset by peer")) + print('\033[91m' + 'error' + '\033[0m') + finally: + logStatus(statusList[-1]) + +# Parses the log from the logfile. Fills the logEntries array. +def parseLog(): + global logEntries + if not (os.path.exists('history.txt')): + return + with open('history.txt', 'r') as log: + for line in log: + line = line.strip() + entry = line.split('\t') + if len(entry) < 4: continue + logEntries.append(LogEntry(entry[0], entry[1], entry[2], entry[3], '' if len(entry) < 5 else entry[4], [] if len(entry) < 6 else entry[5])) + + global newLogIndex + newLogIndex = len(logEntries) + +# Writes updated log in the logfile. +def writeLog(): + with open('history.txt', 'a') as log: + for entry in logEntries[newLogIndex:]: + log_string = entry.date + '\t' + entry.service + '\t' + entry.state + '\t' + entry.host + log_string += '\t' + str(entry.msg) + log_string += '\t' + str(entry.data) + log.write(log_string + '\n') + +# Returns the most recent log object to a given status. None if there is none. +def getLogEntry(status): + return next((x for x in reversed(logEntries) if (x.host == status.host) and (x.service == status.service)), None) + +# Checks weather the status has to be logged or not. (Does the status has changes from the last time?) +def logStatus(status): + obj = getLogEntry(status) + if (obj is None) or (status.state != obj.state): + date = datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S') + logEntries.append(LogEntry(date, status.service, status.state, status.host, status.msg, status.data)) + +# Reads the config and executes the calls. +def readConfig(): + if not (os.path.exists('bwlp.config')): + return + with open('bwlp.config', 'r') as config: + for line in config: + line = line.strip() + entry = line.split('\t') + if entry[0] == '#': continue + check(entry) + +# Calls the check method. +def check(entry): + if entry[0] == 'ping': + if (len(entry) < 3): return + ping(entry[1], entry[2]) + elif entry[0] == 'https': + if (len(entry) < 3): return + https(entry[1], entry[2]) + elif entry[0] == 'thrift': + if (len(entry) < 5): return + thrift(entry[1], entry[2], int(entry[3]), entry[4]) + elif entry[0] == 'tftp': + if (len(entry) < 5): return + tftp(entry[1], entry[2], int(entry[3]), entry[4]) + +# Parse the logfile. +parseLog() + +# Call the checks. +readConfig() + +# Write the new logfile. +writeLog() + +# HTML Processing to generate the website. +code = '\r\n' +for status in statusList: + # Prepare and calculate the time since the server is online / offline + obj = getLogEntry(status) + now = datetime.datetime.now() + date = datetime.datetime.strptime(obj.date, '%Y-%m-%d %H:%M:%S') + time = now - date + days = time.days + hours = time.seconds // 3600 + minutes = (time.seconds // 60) % 60 + timeString = '' + if days > 0: + timeString += str(days) + ' days ' + if hours > 0: + timeString += str(hours) + ' hours ' + if minutes > 0: + timeString += str(minutes) + ' minutes' + + code += ('
' + + status.name + '
' + + status.host + '
' + + status.status + '
' + + timeString + '
\r\n') + +# Generate the html code for the log. +log = '\r\n' + +# Cut the log to the last n entries +n = 500 +cut_amount = 0 +if len(logEntries) >= n: + cut_amount = len(logEntries) - n +for entry in reversed(logEntries[cut_amount:]): + log += ('
[' + + entry.date + ']
[' + + entry.service + ']
[' + + entry.state + ']
[' + + entry.host +']
' + + entry.msg + '
') + +# Copy the .html file and replace the %CONTENT% to generate the final html file. +shutil.copyfile('template.html', 'status.html') + +# Replace the %CONTENT% in the template with the actual html code. +html = open('template.html') +html2 = open('status.html', 'w') +for line in html: + html2.write(line.replace('%CONTENT%', code).replace('%LOG%', log)) + +html.close() +html2.close() diff --git a/template.html b/template.html new file mode 100644 index 0000000..f05c233 --- /dev/null +++ b/template.html @@ -0,0 +1,155 @@ + + + + + + + bwLp Status Monitor + + + +
+
+%CONTENT% +
+
+
+%LOG% +
+
+
+ + + + + + \ No newline at end of file -- cgit v1.2.3-55-g7522