summaryrefslogblamecommitdiffstats
path: root/bwLpStatus.py
blob: a0642a87ce2a06ad8f61f2d86440be24695fafc7 (plain) (tree)



















































































































































































































                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                         
import subprocess
import urllib.request
import urllib.error
#import mysql.connector
import thriftpy
from thriftpy.rpc import make_client
from thriftpy.transport import TFramedTransportFactory
import shutil
import datetime
import os

# 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, http, mysql, ...)
    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, host, service, state, 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 ... ', end='')
  response = subprocess.Popen(
    ['ping', '-c', '1', hostname],
    stdout=subprocess.PIPE,
    stderr=subprocess.PIPE
  )
  response = response.communicate()
  output = response[0].decode('utf-8')
  error = response[1].decode('utf-8')

  # Error happend
  if error != '':
    print('error: ', end='')
    print(error)
    statusList.append(Status(name, hostname, 'error', 'Offline', 'ping', error.rstrip()))
  else:
    print('success')
    statusList.append(Status(name, hostname, 'success', 'Online', 'ping'))
    
  logStatus(statusList[-1])

def https(name, url):
  print('HTTPS request')
  try:
    r = urllib.request.urlopen(url)
    if r.getcode() == 200:
      statusList.append(Status(name, url, 'success', 'Online', 'https'))
    else:
      statusList.append(Status(name, url, 'error', 'Offline', 'https'))

  except urllib.error.URLError as e:
    statusList.append(Status(name, url, 'error', 'Offline', 'https'))

  logStatus(statusList[-1])

def mysql(self, host, user, passwd, db):
  print('MYSQL request start ...')
  #db = mysql.connector.connect(
  #  host='localhost',
  #  user='openslx',
  #  passwd='geheim',
  #  database='openslx'
  #)
  #cursor = db.cursor()
  #cursor.execute('SELECT * FROM user')
  #result = cursor.fetchall()
  #for user in result:
  #  print(user[1])

def thrift(name, ip, port):
  print('THRIFT request start ...')
  bwlp_thrift = thriftpy.load('bwlp.thrift', module_name='bwlp_thrift')
  # masterserver = make_client(bwlp_thrift.MasterServer, '132.230.4.16', 9090, trans_factory=TFramedTransportFactory())
  # TODO: TRY CATCH
  satserver = make_client(bwlp_thrift.SatelliteServer, ip, port, trans_factory=TFramedTransportFactory())
  organisations = satserver.getAllOrganizations()
  organisationList = []
  for org in organisations:
    organisationList.append(Organisation(org.organizationId, org.displayName))

  host = ip + ':' + str(port)
  statusList.append(Status(name, host, 'success', 'Online (' + str(len(organisationList)) + ')', 'thrift', data=organisationList))
  logStatus(statusList[-1])

# Parses the log from the logfile. Fills the logEntries array.
def parseLog():
  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
      if entry.msg != '': log_string += '\t' + entry.msg
      if entry.data != []: 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):
  # for entry in reversed(logEntries):
  #   if status.host == entry.host and status.service == entry.service: return entry
  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.host, status.service, status.state, status.msg, status.data))

# Parse the logfile.
parseLog()

# Call the checks.
https('Masterserver HTTPS Service', 'https://bwlp-masterserver.ruf.uni-freiburg.de')
ping('Masterserver IP Ping', '132.230.4.16')
ping('Fileserver Ping', 'files.bwlp.ks.uni-freiburg.de')
ping('Backup fileserver Ping', 'bwlp-backup.ruf.uni-freiburg.de')
thrift('Thrift SAT', '132.230.8.192', 9090)
ping('BAS Ping', 'bas.intra.uni-freiburg.de')
ping('yc', '127.0.0.2')
ping('yx', '127.0.0.3')

# 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 += '<div class="content_item"><div class="content_item_part"><div class="content_item_part_title">' + status.name + '</div><div class="content_item_part_subtitle">' + status.host + '</div></div><div class="content_item_part ' + status.state  + '"><div class="content_item_part_title">' + status.status + '</div><div class="content_item_part_subtitle">' + timeString  + '</div></div></div>\r\n'

# Generate the html code for the log.
log = '\r\n'
for entry in reversed(logEntries):
  log += '<div class="log_item"><div class="log_item_part time"><div class="content_item_part_title">[' + entry.date + ']</div></div><div class="log_item_part service"><div class="content_item_part_title">[' + entry.service + ']</div></div><div class="log_item_part ' +  entry.state + '"><div class="content_item_part_title">[' + entry.state + ']</div></div><div class="log_item_part"><div class="content_item_part_title">[' + entry.host +']</div></div><div class="log_item_part"><div class="content_item_part_title">' + entry.msg + '</div></div></div>'

# 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()