#!/usr/bin/python import telnetlib import re import simplejson as json import os import ConfigParser from signal import * from time import sleep from gearman import GearmanWorker,GearmanClient from threading import Thread """ This function generates a RTRV-HDR:::; command to keep our connections alive """ class KeepAlive(Thread): # are we supposed to end our loop? stop = False # starting point for thread def run(self): while True: # sleep for 5 minutes, always verifying if # the time to stop has arrived for i in range(300): # ops, time to stop if self.stop: return sleep(1) cmd = {} cmd["olt"] = "OLTCTA3" cmd["user"] = "script" cmd["pswd"] = "tpircs" cmd["command"] = "RTRV-HDR:::;" s = json.dumps(cmd) client = GearmanClient(["127.0.0.1"]) ret = client.submit_job('run_olt_command', json.dumps(cmd)) class Command: command = None olt = None user = None pswd = None login = "" logoff = "" cmdReturn = "" errorString = "" def loginSucceeded(self): return self.validateReturn(self.login) def runOk(self): return self.validateReturn(self.cmdReturn) # search the string for DENY # and return accordingly def validateReturn(self,out): self.errorString = "" regex = re.compile("\/\* (.*?) \*\/") if re.search("DENY",out) != None: lines = out.split("\n") for line in lines: matches = regex.search(line) if matches: self.errorString = matches.group(1) return False if out == "": self.errorString = "Empty string returned by TL1" return False return True # ok, parse output # this is disgusting, obviously def parseOutput(self): ret = [] str = self.cmdReturn.replace("\n","") str = str.replace("\r","") messages = str.split(">") for burst in messages: sepMessages = re.split(" +\"",burst) for msg in sepMessages: if not re.match("^\W",msg) and not re.match("^ *$",msg): strToEval = "" splited = msg.split("\n") for line in splited: if not re.match(".*\/\*.*",line): strToEval += line readyMessage = self.evalMessage(strToEval) if readyMessage != False: ret.append(readyMessage) return ret # keep the disgusting parse stuff def evalMessage(self,msg): ret = [] msg = msg.replace("\\","").replace("\"","").replace("'","").replace(";","").replace("\r",""); ret = msg.split(":") if len(ret) <= 1: return False return ret """ This class represents a connection to a OLT throuth TL1 GW """ class Conn: ip = None port = None tid = None user = None pswd = None c = None timeToClose = False timeout = 5 running = False _endCommandPrompt = "\r\n;" _connectedToOlt = False # connect to tl1 gateway def connect(self, dbg=False): try : self.c = telnetlib.Telnet(self.ip, self.port) if dbg: # put our telnet connection in debug state self.c.set_debuglevel(1) # issue the tl1 gw login command loginCommand = "ACT-USER:%s:%s::TCPNOA:%s;\r" % (self.tid,self.user,self.pswd) self.c.write(loginCommand) login = self.c.read_until(self._endCommandPrompt, self.timeout) # problem connecting, return false if re.search("DENY",login) != None: return False except: # unexpected error, return false return False return True # issue a command into our telnet socket # and retrieve the return def runCommand(self,cmd): # are we connected to desired OLT? if not self._connectedToOlt: # prepare to run # auth to desired olt authCommand = "ACT-USER:%s:%s:::%s;\r" % (cmd.olt,cmd.user,cmd.pswd) self.c.write(authCommand) cmd.login += self.c.read_until(self._endCommandPrompt, self.timeout) if cmd.loginSucceeded(): self._connectedToOlt = True else: # fail to login, nothing to do about it return else: cmd.login = "Already logged" # avoid the automatic alert generation at screen self.c.write("INH-MSG-ALL:%s:ALL:::;\r" % cmd.olt) inhmsgs = self.c.read_until(self._endCommandPrompt, self.timeout) # run ! self.c.write("%s\r" % cmd.command) cmd.cmdReturn = self.c.read_until(self._endCommandPrompt, self.timeout) # logoff from olt def close(self): self.c.write("LOGOFF:%s::;\r" % self.tid) sleep(1) self.c.close() return True """ Main worker function """ def runOltCommand(worker,job): global cons global ip global port global tid global user global password global debug # json decode ret = {} try: obj = json.loads(job.data) except: ret["state"] = 2 ret["pluginOutput"] = "JSON invalido" return json.dumps(ret) # retrieve the desired connection con = None try: # ok, this is an active connection con = cons[obj["olt"]] except KeyError: # we need to establish a new connection cons[obj["olt"]] = Conn() cons[obj["olt"]].ip = ip cons[obj["olt"]].port = port cons[obj["olt"]].tid = tid cons[obj["olt"]].user = user cons[obj["olt"]].pswd = password if debug == 1: cons[obj["olt"]].connect(dbg=True) else: cons[obj["olt"]].connect() con = cons[obj["olt"]] # create our command object using decoded json c = Command() c.olt = str(obj["olt"]) c.command = str(obj["command"]) c.user = str(obj["user"]) c.pswd = str(obj["pswd"]) print "running %s on %s" % (c.command,c.olt) # run the command on the desired connection con.runCommand(c) # did we have a login error during command execution? if not c.loginSucceeded(): ret["state"] = 2 ret["pluginOutput"] = "Permissao negada acessando %s (DENY)" % c.olt ret["commandReturn"] = None return json.dumps(ret) # did the command ran as expected(without DENY string on return)? if not c.runOk(): ret["state"] = 2 ret["pluginOutput"] = "Permissao negada ao rodar %s (%s)" % (c.command,c.errorString) ret["commandReturn"] = None return json.dumps(ret) # parse the output and return back to request process ret["state"] = 0 ret["pluginOutput"] = None ret["commandReturn"] = c.parseOutput() return json.dumps(ret) # signal handling function def signalProcessor(signum,stack): global olts global cons print "Stopping, please wait..." # stop our keep alive thread keepalive.stop = True keepalive.join() # unregister our gearman worker worker.unregister_task('run_olt_command') # wait for active commands to finish sleep(3) # close active connections for olt in olts: print "Closing connection to %s" % olt try: cons[olt].close() except: pass os.sys.exit(0) # Global variables worker = None keepalive = None cons = {} ip = None port = None tid = None user = None password = None debug = False olts = [] # Main function, everything starts here if __name__ == "__main__": # Parse config.ini file config = ConfigParser.ConfigParser() config.read("config.ini") ip = config.get("MAIN","IP") port = int(config.get("MAIN","PORT")) tid = config.get("MAIN","TID") user = config.get("MAIN","USER") password = config.get("MAIN","PASSWORD") olts = config.get("MAIN","OLTS").split(",") debug = int(config.get("MAIN","DEBUG")) # associate our signals signal(SIGINT,signalProcessor) signal(SIGQUIT,signalProcessor) signal(SIGTERM,signalProcessor) # register worker worker = GearmanWorker(["127.0.0.1"]) worker.register_task('run_olt_command', runOltCommand) # create our keep alive thread keepalive = KeepAlive() keepalive.start() # starts to listen # it's time to work worker.work()