From 4bd6d19c602137b5d9029a45e6248cf3bbddf023 Mon Sep 17 00:00:00 2001 From: admin666 Date: Mon, 7 Feb 2022 18:39:34 +0100 Subject: [PATCH] =?UTF-8?q?Premi=C3=A8re=20version?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- bot_main.py | 60 ++++++++++++---- commands.py | 66 ++++++++++++----- localServer.py | 7 +- serviceData.py | 185 ++++++++++++++++++++++++++++++++++++++++++++++++ sharedBuffer.py | 167 ------------------------------------------- 5 files changed, 285 insertions(+), 200 deletions(-) create mode 100644 serviceData.py delete mode 100644 sharedBuffer.py diff --git a/bot_main.py b/bot_main.py index b942e12..d7963ab 100755 --- a/bot_main.py +++ b/bot_main.py @@ -8,10 +8,11 @@ import random import threading import socket import time +import signal from hintTables import * from commands import * -from sharedBuffer import SharedBuffer +from serviceData import ServiceData from localServer import LocalServer class MUCBot(slixmpp.ClientXMPP): @@ -23,12 +24,12 @@ class MUCBot(slixmpp.ClientXMPP): """ def __init__(self, jid, password, room, nick): - slixmpp.ClientXMPP.__init__(self, jid, password) + slixmpp.ClientXMPP.__init__(self, jid + "/Isengard", password) self.room = room self.nick = nick self.owners = {} - self.sbuf = None + self.serviceData = None # The session_start event will be triggered when # the bot establishes its connection with the server @@ -64,6 +65,12 @@ class MUCBot(slixmpp.ClientXMPP): # password=the_room_password, ) + def push(self, destmuc, msg): + self.send_message( mto=destmuc, + mbody=msg, + mtype='groupchat') + print("To: %s\nBody: %s" % (destmuc, msg)) + def muc_message(self, msg): """ Whenever the bot's nickname is mentioned, respond to @@ -85,7 +92,7 @@ class MUCBot(slixmpp.ClientXMPP): commandtable[opcod](self.owners[msg['from'].bare], msg['mucnick'], msg['body'], - self.sbuf)), + self.serviceData)), mtype='groupchat') return @@ -133,18 +140,41 @@ class MUCBot(slixmpp.ClientXMPP): the user's nickname """ - if presence['muc']['nick'] != self.nick: + if presence['muc']['nick'] in self.serviceData.maintainerData: self.send_message(mto=presence['from'].bare, - mbody="Salut %s !" % (presence['muc']['nick']), + mbody="Salut %s, vos services ont produit des " + + "alertes en votre absence !\nUtilisez la commande"+ + " `hist` pour consulter l'historique" + % (presence['muc']['nick']), mtype='groupchat') - if presence['muc']['affiliation'] == "owner": - if not presence['from'].bare in self.owners: - self.owners[presence['from'].bare] = [] + if presence['muc']['affiliation'] == "owner": + if not presence['from'].bare in self.owners: + self.owners[presence['from'].bare] = [] - self.owners[presence['from'].bare].append(presence['muc']['nick']) + self.owners[presence['from'].bare].append(presence['muc']['nick']) if __name__ == '__main__': + + def cleanExit(): + global localservthread + localservthread.pleaseStop = True + # stop tcp server + sockfd = socket.socket() + port = 12346 + sockfd.connect(('127.0.0.1', port)) + sockfd.send(b'') + sockfd.close() + + exit(0) + + + def signalHandler(sig, frame): + print("Exiting...") + cleanExit() + + signal.signal(signal.SIGINT, signalHandler) + # Setup the command line arguments. parser = ArgumentParser() @@ -181,14 +211,13 @@ if __name__ == '__main__': xmpp.register_plugin('xep_0199') # XMPP Ping # Create buffer - sBuffer = SharedBuffer(xmpp) - xmpp.sbuf = sBuffer + sBuffer = ServiceData(xmpp) + xmpp.serviceData = sBuffer # Connect to the XMPP server and start processing XMPP stanzas. xmpp.connect() localservthread = LocalServer(sBuffer) - localservthread.daemon = True localservthread.start() time.sleep(1) @@ -196,4 +225,7 @@ if __name__ == '__main__': if not localservthread.is_alive(): exit(1) - xmpp.process() + try: + xmpp.process() + except KeyboardInterrupt: + cleanExit() diff --git a/commands.py b/commands.py index e99b01a..a9d2a1a 100644 --- a/commands.py +++ b/commands.py @@ -9,6 +9,21 @@ def cmdping(owners, nick, text, sbuf): return "pong !" +def cmdhelp(owners, nick, text, sbuf): + """ + Ping command. + """ + + global commandtable + + msg = "Je suis Isengard, le bot de supervision de ce salon.\n" + msg += "\n" + msg += "Voici la liste de mes commandes disponibles : \n" + + for cmd in commandtable: + msg += "- " + cmd + "\n" + + return msg def cmdmainteneur(owners, nick, text, sbuf): """ @@ -26,23 +41,23 @@ def cmdmainteneur(owners, nick, text, sbuf): host = splittedtext[1] return "le responsable de cette machine est " \ - + sbuf.buf[host]["maintainer"] + + sbuf.serviceData[host]["maintainer"] if len(splittedtext) == 3: host = splittedtext[1] maintainer = splittedtext[2] - sbuf.buf[host] = {} - sbuf.buf[host]["destmuc"] = None - sbuf.buf[host]["status_state"] = None - sbuf.buf[host]["status_type"] = None - sbuf.buf[host]["text"] = None - sbuf.buf[host]["raw"] = None - sbuf.buf[host]["needUpdate"] = False - sbuf.buf[host]["maintainer"] = maintainer + sbuf.serviceData[host] = {} + sbuf.serviceData[host]["destmuc"] = None + sbuf.serviceData[host]["status_state"] = None + sbuf.serviceData[host]["status_type"] = None + sbuf.serviceData[host]["text"] = None + sbuf.serviceData[host]["raw"] = None + sbuf.serviceData[host]["needUpdate"] = False + sbuf.serviceData[host]["maintainer"] = maintainer return "le responsable est à présent " \ - + sbuf.buf[host]["maintainer"] + + sbuf.serviceData[host]["maintainer"] except Exception as e: print(repr(e)) @@ -60,7 +75,7 @@ def cmdsave(owners, nick, text, sbuf): try: with open('current_buffer', 'wb') as current_buffer_file: - pickle.dump(sbuf.buf, current_buffer_file) + pickle.dump(sbuf.serviceData, current_buffer_file) return "OK" except Exception as e: @@ -77,23 +92,40 @@ def cmdload(owners, nick, text, sbuf): try: with open('current_buffer', 'rb') as current_buffer_file: - sbuf.buf = pickle.load(current_buffer_file) + sbuf.serviceData = pickle.load(current_buffer_file) return "OK" except Exception as e: print(repr(e)) return "Erreur à l'exécution" +def cmdhist(owners, nick, text, sbuf): + """ + Check history for a maintainer + """ + + if not nick in sbuf.maintainerData or len(sbuf.maintainerData[nick]) == 0: + return "pas d'historique disponible pour vous." + + msg = "voici historique pour le mainteneur %s (vous) :\n" % nick + for host in sbuf.maintainerData[nick]: + msg += "\nHôte %s:" % host + + for serviceline in sbuf.maintainerData[nick][host]: + msg += "- %s" % serviceline + "\n" + + sbuf.maintainerData[nick] = {} + return msg # Commands commandtable = { - -"ping" : cmdping, -"mainteneur" : cmdmainteneur, -"save" : cmdsave, +"help" : cmdhelp, +"hist" : cmdhist, "load" : cmdload, - +"mainteneur" : cmdmainteneur, +"ping" : cmdping, +"save" : cmdsave, } diff --git a/localServer.py b/localServer.py index 50e8d31..8a7bdbe 100644 --- a/localServer.py +++ b/localServer.py @@ -6,6 +6,7 @@ class LocalServer(threading.Thread): def __init__(self, sharedBuffer): threading.Thread.__init__(self) self.sharedBuffer = sharedBuffer + self.pleaseStop = False def run(self): @@ -17,14 +18,16 @@ class LocalServer(threading.Thread): sockfd.listen(5) # Put the socket into listening mode print("Socket is listening") - while True: + while not self.pleaseStop: client, addr = sockfd.accept() # Establish connection with client print('Got connection from', addr) rcvStr = client.recv(1024).decode() print(rcvStr) - self.sharedBuffer.push(rcvStr) + if rcvStr != '': + self.sharedBuffer.push(rcvStr) client.send(b'') # Send a message to the client client.close() print("Socket is listening") + print("Socket is closed\nExiting") diff --git a/serviceData.py b/serviceData.py new file mode 100644 index 0000000..59e741a --- /dev/null +++ b/serviceData.py @@ -0,0 +1,185 @@ +import datetime + +class ServiceData: + + def __init__(self, linkedBot): + self.serviceData = {} + self.maintainerData = {} + self.linkedBot = linkedBot + + def flush(self): + + for host in self.serviceData: + if not isinstance(self.serviceData[host], dict): + continue + + maintainer = self.serviceData[host]["maintainer"] + + if self.serviceData[host]["needUpdate"]: + destmuc = self.serviceData[host]["destmuc"] + text = self.serviceData[host]["text"] + msg = "(néant)" + + if self.serviceData[host]["status_type"] == "PROBLEM": + msg = "{}, je détecte un problème sur {} ({})".format(maintainer, host, text) + + elif self.serviceData[host]["status_type"] == "UNKNOWN": + msg = "{}, état de {} inconnu ({})".format(maintainer, host, text) + + elif self.serviceData[host]["status_type"] == "RECOVERY": + msg = "{}, problème résolu sur {} ({})".format(maintainer, host, text) + + self.linkedBot.push(destmuc, msg) + + self.serviceData[host]["needUpdate"] = False + + for service in self.serviceData[host]: + if not isinstance(self.serviceData[host][service], dict): + continue + + if self.serviceData[host][service]["needUpdate"]: + destmuc = self.serviceData[host][service]["destmuc"] + text = self.serviceData[host][service]["text"] + msg = "(néant)" + + if self.serviceData[host][service]["status_type"] == "PROBLEM": + msg = "{}, je détecte un problème de {} sur {} ({})".format(maintainer, service, host, text) + + elif self.serviceData[host][service]["status_type"] == "UNKNOWN": + msg = "{}, état de {} inconnu pour {} ({})".format(maintainer, service, host, text) + + elif self.serviceData[host][service]["status_type"] == "RECOVERY": + msg = "{}, problème de {} résolu sur {} ({})".format(maintainer, service, host, text) + + self.linkedBot.push(destmuc, msg) + + self.serviceData[host][service]["needUpdate"] = False + + print("End of flush") + + def push(self, msg): + + # Get current time + curtime = datetime.datetime.now().strftime("%m/%d/%Y, %H:%M:%S") + + # separate dest and message + destmuc, rmsg = msg.split("|") + + # separate and parse lines + cutmsg_l0 = rmsg.split("\n")[0].split(" ") + cutmsg_l1 = rmsg.split("\n")[1].split("-") + + # get the status of location + status_type = cutmsg_l0[0].replace(" ", "") + status_state = cutmsg_l0[-1].replace(" ", "") + + # get the location + location = "" + for i in range(len(cutmsg_l0) - 2): + location += cutmsg_l0[i+1] + " " + location = location[:-1] + + # check if message is about a service or host + if len(location.split("/")) > 1: + host, service = location.split("/") + else: + host = location + service = False + + text = status_state + ": " + cutmsg_l1[1].split("(")[0][1:] + + raw = rmsg.split("\n")[1] + + print("Dest: %s, Msg: %s" % (destmuc, rmsg)) + print("Status: %s" % (status_type + " (" + status_state + ")")) + print("Host: %s, Service: %s" % (host, service)) + print("Text: %s" % (text)) + + # Is that host known + if host in self.serviceData: + + # Is it a service and is it known + if service and service in self.serviceData[host]: + # update host if needed + if status_type != self.serviceData[host][service]["status_type"]: + self.serviceData[host][service]["status_state"] = status_state + self.serviceData[host][service]["status_type"] = status_type + self.serviceData[host][service]["destmuc"] = destmuc + self.serviceData[host][service]["text"] = text + self.serviceData[host][service]["needUpdate"] = True + maintainer = self.serviceData[host]["maintainer"] + + # Is it an unkown service + elif service: + # create zone for service + self.serviceData[host][service] = {} + self.serviceData[host][service]["destmuc"] = destmuc + self.serviceData[host][service]["status_state"] = status_state + self.serviceData[host][service]["status_type"] = status_type + self.serviceData[host][service]["text"] = text + self.serviceData[host][service]["needUpdate"] = True + maintainer = self.serviceData[host]["maintainer"] + + # This is a host (not a service) + else: + # update host if needed + if status_type != self.serviceData[host]["status_type"]: + self.serviceData[host]["destmuc"] = destmuc + self.serviceData[host]["status_state"] = status_state + self.serviceData[host]["status_type"] = status_type + self.serviceData[host]["text"] = text + self.serviceData[host]["needUpdate"] = True + maintainer = self.serviceData[host]["maintainer"] + + # That host is not known + else: + + # create slot for host and service + if service: + self.serviceData[host] = {} + self.serviceData[host]["destmuc"] = None + self.serviceData[host]["status_state"] = None + self.serviceData[host]["status_type"] = None + self.serviceData[host]["text"] = None + self.serviceData[host]["maintainer"] = "Tout le monde" + self.serviceData[host]["needUpdate"] = False + self.serviceData[host][service] = {} + self.serviceData[host][service]["destmuc"] = destmuc + self.serviceData[host][service]["status_state"] = status_state + self.serviceData[host][service]["status_type"] = status_type + self.serviceData[host][service]["text"] = text + self.serviceData[host][service]["raw"] = raw + self.serviceData[host][service]["needUpdate"] = True + maintainer = self.serviceData[host]["maintainer"] + + # create slot for host + else: + self.serviceData[host] = {} + self.serviceData[host]["destmuc"] = destmuc + self.serviceData[host]["status_state"] = status_state + self.serviceData[host]["status_type"] = status_type + self.serviceData[host]["text"] = text + self.serviceData[host]["maintainer"] = "Tout le monde" + self.serviceData[host]["needUpdate"] = True + maintainer = self.serviceData[host]["maintainer"] + + # create maintainer in maintainer data if needed + if not maintainer in self.maintainerData: + self.maintainerData[maintainer] = {} + + # create host entry + if not service: + service = "GENERAL" + + if not host in self.maintainerData[maintainer]: + self.maintainerData[maintainer][host] = [] + + self.maintainerData[maintainer][host].append( + curtime + ": " + service + "/" + raw + ) + + print(self.serviceData) + print("Flushing...") + self.flush() + print(self.serviceData) + print("End of push") diff --git a/sharedBuffer.py b/sharedBuffer.py deleted file mode 100644 index 4a35e93..0000000 --- a/sharedBuffer.py +++ /dev/null @@ -1,167 +0,0 @@ -class SharedBuffer: - - def __init__(self, linkedBot): - self.buf = {} - self.linkedBot = linkedBot - - def flush(self): - - for host in self.buf: - if not isinstance(self.buf[host], dict): - continue - - maintainer = self.buf[host]["maintainer"] - - if self.buf[host]["needUpdate"]: - destmuc = self.buf[host]["destmuc"] - text = self.buf[host]["text"] - msg = "(néant)" - - if self.buf[host]["status_type"] == "PROBLEM": - msg = "{}, je détecte un problème sur {} ({})".format(maintainer, host, text) - - elif self.buf[host]["status_type"] == "UNKNOWN": - msg = "{}, état de {} inconnu ({})".format(maintainer, host, text) - - elif self.buf[host]["status_type"] == "RECOVERY": - msg = "{}, problème résolu sur {} ({})".format(maintainer, host, text) - - self.linkedBot.send_message( - mto=destmuc, - mbody=msg, - mtype='groupchat') - - self.buf[host]["needUpdate"] = False - print("Sent to {}, msg: {}".format(destmuc, msg)) - - for service in self.buf[host]: - if not isinstance(self.buf[host][service], dict): - continue - - if self.buf[host][service]["needUpdate"]: - destmuc = self.buf[host][service]["destmuc"] - text = self.buf[host][service]["text"] - msg = "(néant)" - - if self.buf[host][service]["status_type"] == "PROBLEM": - msg = "{}, je détecte un problème de {} sur {} ({})".format(maintainer, service, host, text) - - elif self.buf[host][service]["status_type"] == "UNKNOWN": - msg = "{}, état de {} inconnu pour {} ({})".format(maintainer, service, host, text) - - elif self.buf[host][service]["status_type"] == "RECOVERY": - msg = "{}, problème de {} résolu sur {} ({})".format(maintainer, service, host, text) - - self.linkedBot.send_message( - mto=destmuc, - mbody=msg, - mtype='groupchat') - - self.buf[host][service]["needUpdate"] = False - print("Sent to {}, msg: {}".format(destmuc, msg)) - - print("End of flush") - - def push(self, msg): - - # separate dest and message - destmuc, rmsg = msg.split("|") - - # separate and parse lines - cutmsg_l0 = rmsg.split("\n")[0].split(" ") - cutmsg_l1 = rmsg.split("\n")[1].split("-") - - # get the status of location - status_type = cutmsg_l0[0].replace(" ", "") - status_state = cutmsg_l0[-1].replace(" ", "") - - # get the location - location = "" - for i in range(len(cutmsg_l0) - 2): - location += cutmsg_l0[i+1] + " " - location = location[:-1] - - # check if message is about a service or host - if len(location.split("/")) > 1: - host, service = location.split("/") - else: - host = location - service = False - - text = status_state + ": " + cutmsg_l1[1].split("(")[0][1:] - - raw = rmsg.split("\n")[1] - - print("Dest: %s, Msg: %s" % (destmuc, rmsg)) - print("Status: %s" % (status_type + " (" + status_state + ")")) - print("Host: %s, Service: %s" % (host, service)) - print("Text: %s" % (text)) - - if host in self.buf: - if service and service in self.buf[host]: - if status_state != self.buf[host][service]["status_state"] \ - or status_type != self.buf[host][service]["status_type"]: - self.buf[host][service]["status_state"] = status_state - self.buf[host][service]["status_type"] = status_type - self.buf[host][service]["destmuc"] = destmuc - self.buf[host][service]["text"] = text - self.buf[host][service]["raw"] = raw - self.buf[host][service]["needUpdate"] = True - - else: - - # exit if problem resolved (but unkown in the first place) - if status_type == "RECOVERY": - return - - # create zone for service - self.buf[host][service] = {} - self.buf[host][service]["destmuc"] = destmuc - self.buf[host][service]["status_state"] = status_state - self.buf[host][service]["status_type"] = status_type - self.buf[host][service]["text"] = text - self.buf[host][service]["raw"] = raw - self.buf[host][service]["needUpdate"] = True - - else: - - # exit if problem resolved (but unkown in the first place) - if status_type == "RECOVERY": - return - - # create zone for service - if service: - self.buf[host] = {} - self.buf[host]["destmuc"] = None - self.buf[host]["status_state"] = None - self.buf[host]["status_type"] = None - self.buf[host]["text"] = None - self.buf[host]["raw"] = None - self.buf[host]["maintainer"] = None - self.buf[host]["needUpdate"] = False - self.buf[host][service] = {} - self.buf[host][service]["destmuc"] = destmuc - self.buf[host][service]["status_state"] = status_state - self.buf[host][service]["status_type"] = status_type - self.buf[host][service]["text"] = text - self.buf[host][service]["raw"] = raw - self.buf[host][service]["needUpdate"] = True - else: - self.buf[host] = {} - self.buf[host]["destmuc"] = destmuc - self.buf[host]["status_state"] = status_state - self.buf[host]["status_type"] = status_type - self.buf[host]["text"] = text - self.buf[host]["raw"] = raw - self.buf[host]["maintainer"] = None - self.buf[host]["needUpdate"] = True - - print(self.buf) - print("Sending...") - self.flush() - print("Sent.") - print(self.buf) - print("End of push") - -#PROBLEM video.chalec.org/System load CRITICAL -#CRITICAL - Charge moyenne: 6.45, 5.61, 4.12 (Commentaire: [] )