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