Première version

This commit is contained in:
admin666 2022-02-07 18:39:34 +01:00
parent 57d21cc96d
commit 4bd6d19c60
5 changed files with 285 additions and 200 deletions

View File

@ -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,9 +140,12 @@ 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":
@ -145,6 +155,26 @@ class MUCBot(slixmpp.ClientXMPP):
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)
try:
xmpp.process()
except KeyboardInterrupt:
cleanExit()

View File

@ -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,
}

View File

@ -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)
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")

185
serviceData.py Normal file
View File

@ -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")

View File

@ -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: [] )