198 lines
6.0 KiB
Python
198 lines
6.0 KiB
Python
import datetime
|
|
import logging
|
|
|
|
from systemd.journal import JournalHandler
|
|
|
|
# Logging
|
|
log = logging.getLogger(__name__)
|
|
log.addHandler(JournalHandler())
|
|
|
|
PRIORITY = {
|
|
"OK":0,
|
|
"UP":0,
|
|
"WARNING":1,
|
|
"CRITICAL":2,
|
|
"UNKNOWN": 2,
|
|
"DOWN": 3,
|
|
}
|
|
|
|
|
|
class ProblemData:
|
|
"""
|
|
Data related to notifications related to a given problem
|
|
"""
|
|
|
|
def __init__(self, name):
|
|
self.name = name
|
|
self.status = "OK"
|
|
self.last_update = datetime.datetime.fromtimestamp(0)
|
|
|
|
|
|
class HostData:
|
|
"""
|
|
Data related to notifications related to a given host
|
|
"""
|
|
|
|
def __init__(self, name):
|
|
self.name = name
|
|
self.status = "OK"
|
|
self.downtime = False
|
|
self.last_update = datetime.datetime.fromtimestamp(0)
|
|
self.worst = None
|
|
self.problems = set()
|
|
|
|
|
|
class DataStore:
|
|
|
|
def __init__(self, linkedBot):
|
|
|
|
log.info("Created DataStore")
|
|
|
|
self.hosts = set()
|
|
self.linkedBot = linkedBot
|
|
|
|
def notify(self, destmuc):
|
|
msg = "```\n"
|
|
msg += "*** Isengard - Statut des services ***\n\n"
|
|
msg += "-"*80 + "\n"
|
|
msg += "| Hôte | Statut | Pire service | Dernière maj |\n"
|
|
msg += "-"*80 + "\n"
|
|
|
|
for host in [x for x in self.hosts]:
|
|
msg += "*"
|
|
msg += " " + str(host.name)[:22] + " "*(23 - len(str(host.name)[:22])) + "|"
|
|
msg += " " + str(host.status)[:8] + " "*(9 - len(str(host.status))) + "|"
|
|
msg += " " + str(host.worst)[:16] + " "*(17 - len(str(host.worst)[:16])) + "|"
|
|
msg += " " + host.last_update.strftime("%m/%d/%Y, %H:%M:%S")[:21] +\
|
|
" "*(22 - len(host.last_update.strftime("%m/%d/%Y, %H:%M:%S"))) +\
|
|
"|\n"
|
|
msg += "-"*80 + "\n"
|
|
|
|
if PRIORITY[host.status] == 0:
|
|
self.hosts.discard(host)
|
|
msg += "```"
|
|
|
|
# Send notification
|
|
log.info("Sending to %s: %s" % (destmuc, msg))
|
|
self.linkedBot.push(destmuc, msg)
|
|
|
|
def get_status(self):
|
|
msg = "```\n"
|
|
msg += "*** Isengard - Statut des services ***\n\n"
|
|
msg += "-"*80 + "\n"
|
|
msg += "| Hôte | Statut | Pire service | Dernière maj |\n"
|
|
msg += "-"*80 + "\n"
|
|
|
|
for host in [x for x in self.hosts]:
|
|
msg += "*"
|
|
msg += " " + str(host.name)[:22] + " "*(23 - len(str(host.name)[:22])) + "|"
|
|
msg += " " + str(host.status)[:8] + " "*(9 - len(str(host.status))) + "|"
|
|
msg += " " + str(host.worst)[:16] + " "*(17 - len(str(host.worst)[:16])) + "|"
|
|
msg += " " + host.last_update.strftime("%m/%d/%Y, %H:%M:%S")[:21] +\
|
|
" "*(22 - len(host.last_update.strftime("%m/%d/%Y, %H:%M:%S"))) +\
|
|
"|\n"
|
|
msg += "-"*80 + "\n"
|
|
|
|
if PRIORITY[host.status] == 0:
|
|
self.hosts.discard(host)
|
|
msg += "```"
|
|
|
|
return msg
|
|
|
|
|
|
def push(self, msg):
|
|
"""
|
|
Process messages like TYPE|HOST/SERVICE|STATE|OUTPUT|SENDER|COMMENT
|
|
"""
|
|
|
|
# Get current time
|
|
curtime = datetime.datetime.now() #.strftime("%m/%d/%Y, %H:%M:%S")
|
|
# Get all params
|
|
destmuc, mtype, location, status, text, sender, comment = msg.split("|")
|
|
mtype = mtype.replace(" ", "")
|
|
status = status.replace(" ", "")
|
|
|
|
# Check if message is about a service or host
|
|
try:
|
|
hostname, service = location.split("/")
|
|
except ValueError:
|
|
hostname = location.split("/")[0]
|
|
service = None
|
|
|
|
cur = None
|
|
|
|
# Look for host
|
|
for host in self.hosts:
|
|
if host.name == hostname:
|
|
cur = host
|
|
|
|
# Host not found
|
|
if not(cur):
|
|
cur = HostData(hostname)
|
|
self.hosts.add(cur)
|
|
log.info("CREATED : %s\n" % cur)
|
|
|
|
|
|
# Retrieve informations and update
|
|
log.info("RECEIVED : status %s; mtype %s; location %s; sender %s; comment %s; text %s\n"
|
|
% (status, mtype, location, sender, comment, text))
|
|
|
|
cur.last_update = curtime
|
|
|
|
# If that's global
|
|
if not(service):
|
|
|
|
# Host is now down
|
|
if PRIORITY[status] > PRIORITY[cur.status]:
|
|
cur.status = status
|
|
cur.worst = "DOWN"
|
|
|
|
# DOWNTIME
|
|
elif "DOWNTIME" in mtype:
|
|
pass
|
|
|
|
# Host is no more down and has no more problems
|
|
elif not len(cur.problems):
|
|
cur.status = "OK"
|
|
cur.worst = None
|
|
|
|
# Service problem
|
|
else:
|
|
cur_problem = None
|
|
|
|
# Look for existing problem
|
|
for problem in cur.problems:
|
|
if problem.name == service:
|
|
cur_problem = problem
|
|
|
|
# Problem not found, create it
|
|
if not(cur_problem):
|
|
cur_problem = ProblemData(service)
|
|
cur.problems.add(cur_problem)
|
|
log.info("CREATED PROBLEM in %s : %s\n" % (cur, cur_problem))
|
|
|
|
cur_problem.last_update = curtime
|
|
cur_problem.status = status
|
|
|
|
if PRIORITY[status] == 0 and cur.worst == cur_problem:
|
|
cur.worst = None
|
|
cur.status = "OK"
|
|
|
|
|
|
worst_problem = ProblemData(None)
|
|
|
|
# Find the worst current problem
|
|
for problem in cur.problems:
|
|
if PRIORITY[problem.status] > PRIORITY[worst_problem.status]:
|
|
if problem.last_update > worst_problem.last_update:
|
|
worst_problem = problem
|
|
|
|
if worst_problem.name != None:
|
|
cur.status = worst_problem.status
|
|
cur.worst = worst_problem.name
|
|
|
|
if PRIORITY[status] >= 2 or ("RECOVERY" in mtype and cur.worst == None):
|
|
self.notify(destmuc)
|
|
|
|
return
|