Commit 17afb492 authored by Tomas Hlavacek's avatar Tomas Hlavacek

Async operations support added.

ULGmodel, Cisco and BIRD support changed in order to support sync
as well as async commands (async = command result is displayed
in the same time when the command is running).
parent 9c6be4f1
......@@ -41,7 +41,7 @@ import ulgmodel
### CGI output handler
class Session(object):
def __init__(self,sessionid=None,routerid=None,commandid=None,parameters=[],result=None,finished=False):
def __init__(self,sessionid=None,routerid=None,commandid=None,parameters=[],result=None,finished=False,error=None):
if(sessionid == None):
self.sessionid = self.__genSessionId__()
else:
......@@ -51,6 +51,7 @@ class Session(object):
self.commandid=commandid
self.parameters=parameters
self.result=result
self.error=None
self.finished=finished
self.save()
......@@ -134,12 +135,18 @@ class Session(object):
self.result = result
self.save()
def setPreResult(self,result):
self.setResult('<pre>'+result+'</pre>')
def getResult(self):
return self.result
def getDecoratedResult(self,decorator_helper):
if(self.getError()):
return decorator_helper.pre(self.getResult())
else:
if(self.getResult()):
return self.getCommand().decorateResult(self.getResult(),self.getRouter(),decorator_helper)
else:
return None
def appendResult(self,result_fragment):
self.result = self.result + result_fragment
self.save()
......@@ -156,6 +163,12 @@ class Session(object):
else:
return None
def getError(self):
return self.error
def setError(self,error=None):
self.error=error
class DecoratorHelper:
def __init__(self):
pass
......@@ -279,6 +292,12 @@ class ULGCgi:
session.setResult(defaults.STRING_SESSION_OVERLIMIT)
session.setFinished()
def getRefreshInterval(self,datalength=None):
if(datalength):
return (datalength/1024)*defaults.refresh_interval + defaults.refresh_interval
else:
return defaults.refresh_interval
def HTTPRedirect(self,url):
return """<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html>
......@@ -300,10 +319,10 @@ class ULGCgi:
def commandThreadBody(session,decreaseUsageMethod):
ulgmodel.debug("Running command: "+session.getCommand().getName())
try:
session.setResult(session.getRouter().runCommand(session.getCommand(),session.getParameters(),self.decorator_helper))
session.setResult(session.getRouter().runSyncCommand(session.getCommand(),session.getParameters()))
except Exception as e:
ulgmodel.log("ERROR: Exception occured while running a command:" + traceback.format_exc())
session.setPreResult("ERROR in commandThreadBody:\n"+traceback.format_exc())
session.setResult("ERROR in commandThreadBody:\n"+traceback.format_exc())
finally:
ulgmodel.debug("Command finished: "+session.getCommand().getName())
session.setFinished()
......@@ -378,7 +397,9 @@ class ULGCgi:
if(session.isFinished()):
refresh=None
else:
refresh = defaults.refresh_interval
refresh = self.getRefreshInterval()
result_text = session.getDecoratedResult(self.decorator_helper)
template = self.loader.load(defaults.index_template_file)
return template.generate(defaults=defaults,
......@@ -387,7 +408,7 @@ class ULGCgi:
default_commandid=session.getCommandId(),
default_params=session.getParameters(),
default_sessionid=sessionid,
result=Markup(session.getResult()) if (session.getResult()) else None,
result=Markup(result_text) if(result_text) else None,
refresh=refresh,
getFormURL=self.decorator_helper.getRuncommandURL
).render('html', doctype='html')
......@@ -399,7 +420,7 @@ class ULGCgi:
session = Session.load(sessionid)
if(session!=None):
result_text=self.sessions[sessionid].getResult()
result_text=self.decorator_helper.pre(self.sessions[sessionid].getError())
return template.generate(defaults=defaults,
routers=config.routers,
......@@ -426,7 +447,7 @@ class ULGCgi:
default_sessionid=None,
result=Markup(result_text) if(result_text) else None,
refresh=0,
getFormURL=self.decorator_helper.getRuncommandURL
getFormURL=self.decorator_helper.getRuncommandURL()
).render('html', doctype='html')
def index(self, **params):
......
......@@ -196,7 +196,7 @@ class BirdRouterLocal(ulgmodel.LocalRouter):
ulgmodel.TextCommand('show memory')
]
def runRawCommand(self,command):
def runRawCommand(self,command,outfile):
def parseBirdSockLine(line):
hm = bird_sock_header_regexp.match(line)
if(hm):
......@@ -234,62 +234,58 @@ class BirdRouterLocal(ulgmodel.LocalRouter):
else:
return False
# try:
# open socket to BIRD
s = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
s.settimeout(defaults.default_bird_sock_timeout)
s.connect(self.sock)
result=''
try:
# open socket to BIRD
s = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
s.settimeout(defaults.default_bird_sock_timeout)
s.connect(self.sock)
# cretate FD for the socket
sf=s.makefile()
# cretate FD for the socket
sf=s.makefile()
# wait for initial header
l = sf.readline()
# wait for initial header
l = sf.readline()
# send the command string
sf.write(command+"\n")
sf.flush()
# send the command string
sf.write(command+"\n")
sf.flush()
# read and capture lines until the output delimiter string is hit
while(True):
l = sf.readline()
# read and capture lines until the output delimiter string is hit
while(True):
l = sf.readline()
ulgmodel.debug("Raw line read: " + l)
ulgmodel.debug("Raw line read: " + l)
# process line according to rules take out from the C code
lp = parseBirdSockLine(l)
if(isBirdSockReplyEnd(lp[0])):
# End of reply (0000 or similar code)
ulgmodel.debug("End of reply. Code="+str(lp[0]))
# process line according to rules take out from the C code
lp = parseBirdSockLine(l)
if(isBirdSockReplyEnd(lp[0])):
# End of reply (0000 or similar code)
ulgmodel.debug("End of reply. Code="+str(lp[0]))
if(lp[1]):
ulgmodel.debug("Last read line after normalize: " + lp[1])
result=result+lp[1]+'\n'
break
if(lp[1]):
ulgmodel.debug("Last read line after normalize: " + lp[1])
outfile.write(lp[1]+'\n')
break
else:
if(lp[1]):
ulgmodel.debug("Read line after normalize: " + lp[1])
outfile.write(lp[1]+'\n')
else:
if(lp[1]):
ulgmodel.debug("Read line after normalize: " + lp[1])
result=result+lp[1]+'\n'
else:
ulgmodel.debug("Read line was empty after normalize.")
# close the socket and return captured result
s.close()
ulgmodel.debug("Read line was empty after normalize.")
except socket.timeout as e:
# catch only timeout exception, while letting other exceptions pass
result = defaults.STRING_SOCKET_TIMEOUT
# close the socket and return captured result
s.close()
return result
# except socket.timeout as e:
# # catch only timeout exception, while letting other exceptions pass
# outfile.result(defaults.STRING_SOCKET_TIMEOUT)
def getForkNeeded(self):
return False
def rescanPeers(self):
res = self.runRawCommand(self.RESCAN_PEERS_COMMAND)
res = self.runRawSyncCommand(self.RESCAN_PEERS_COMMAND)
psp = parseBirdShowProtocols(res)
peers = []
......
......@@ -514,7 +514,7 @@ class CiscoRouter(ulgmodel.RemoteRouter):
return True
def rescanBGPPeers(self,command,regexp,ipv6=True):
table = self.runRawCommand(command)
table = self.runRawSyncCommand(command)
peers = []
rlr = re.compile(regexp)
......@@ -566,10 +566,7 @@ class CiscoRouter(ulgmodel.RemoteRouter):
if(not self.getBGPIPv4Peers()) or (not self.getBGPIPv6Peers()):
self.rescanHook()
def runRawCommand(self,command):
return self._runTextCommand(command)
def _runTextCommand(self,command):
def runRawCommand(self,command,outfile):
# connect
p=pexpect.spawn(defaults.bin_ssh+' -p'+str(self.getPort())+' '+str(self.getUser())+'@'+self.getHost())
......@@ -616,4 +613,4 @@ class CiscoRouter(ulgmodel.RemoteRouter):
r = r + l + '\n'
return r
return stripFirstLine(p.before)
outfile.write(stripFirstLine(p.before))
......@@ -26,6 +26,7 @@ from genshi.template import TemplateLoader
from genshi.core import Markup
import pickle
import fcntl
import StringIO
import defaults
......@@ -295,7 +296,7 @@ class Router(object):
r = r + ': '+error+'</em>' if error else r+'.</em>'
return r
def runCommand(self,command,parameters,decorator_helper):
def runSyncCommand(self,command,parameters):
c = command.getCommandText(parameters)
if(c == None):
......@@ -306,17 +307,24 @@ class Router(object):
r = ''
if(defaults.debug):
r = "<h3>DEBUG</h3><pre>Router.runCommand():\ncommand_name="+command.getName()+'\n'
r = "DEBUG: Router.runCommand():\ncommand_name="+command.getName()+'\n'
if(parameters != None):
for pidx,p in enumerate(parameters):
r = r + " param"+str(pidx)+"="+str(p)+"\n"
r = r + "complete command="+c+"\n" + \
"</pre><hr>"
r = r + "complete command="+c+"\n"
r = r + command.decorateResult(self.runRawCommand(c),self,decorator_helper)
return r
return r+self.runRawSyncCommand(c)
def runAsyncCommand(self,command,parameters,outfile):
# TODO
pass
def runRawSyncCommand(self,command):
cr = StringIO.StringIO()
self.runRawCommand(command,cr)
return cr.getvalue()
def runRawCommand(self,command):
def runRawCommand(self,command,outfile):
""" Abstract method. """
raise Exception("runRawCommand() method not supported for the abstract class Router. Inherit from the class and implement the method.")
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment