Commit e1f1403c authored by Tomas Hlavacek's avatar Tomas Hlavacek

ULG model implemented. CGI transition finalized. Select items implemeted and...

ULG model implemented. CGI transition finalized. Select items implemeted and Decorator support added.
parent 5a8a1abf
......@@ -25,3 +25,7 @@ pip-log.txt
#Mr Developer
.mr.developer.cfg
# Potentialy sensitive files
src/config.py
ulg
===
Universal Looking Glass for BIRD and others
\ No newline at end of file
......@@ -24,4 +24,3 @@ routers = [
CiscoRouter(host='testrouter2.core.company.com', user='xyz', password='xyz'),
BirdRouterLocal('/var/run/bird.ctl')
]
......@@ -24,7 +24,11 @@ usage_limit = 1 # maximum concurrently processe
# Settings defaults
always_start_thread = True
debug = True
debug = False
persistent_storage_file = '/tmp/ulg.data'
session_dir = '/tmp'
usage_counter_file = '/tmp/ulg.lock'
log_file = '/tmp/ulg.log'
default_bird_sock = '/var/run/bird.ctl'
# Template dir relative to the index.py script
......@@ -36,5 +40,12 @@ display_template_file = 'display.html'
bin_ssh = '/usr/bin/ssh'
# Output (localized) strings
STRING_SESSION_OVERLIMIT = "<em>Limit of maximum concurrently running sessions and/or queries has been reached. The command can not be executed now. Please retry later.</em>"
STRING_ANY='any'
STRING_PARAMETER='Parameter'
STRING_COMMAND='Command'
STRING_ERROR_COMMANDRUN='Error encountered while preparing or running command'
STRING_BAD_PARAMS='Verification of command or parameters failed.'
STRING_SESSION_OVERLIMIT = "<em>Limit of maximum concurrently running sessions and/or queries has been reached. The command can not be executed now. Please try again later.</em>"
STRING_ARBITRARY_ERROR = "Error encountered. Operation aborted. See log for further details."
STRING_IPADDRESS = "IP address"
STRING_IPSUBNET = "IP subnet"
This diff is collapsed.
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:py="http://genshi.edgewall.org/">
<head>
<title>Universal Looking Glass</title>
<py:if test="defined('refresh')">
<meta http-equiv="refresh" content="$refresh" py:if="defined('refresh') and (refresh>0)" />
</py:if>
<script type="text/javascript">
function updateFormParams()
{
var rs=document.getElementById("routerselect");
var cs=document.getElementById("commandselect");
<py:for each="ridx,router in enumerate(routers)">
<py:for each="cidx,cmd in enumerate(routers[ridx].listCommands())">
<![CDATA[ if((rs.options[rs.selectedIndex].value==$ridx) && (cs.options[cs.selectedIndex].value==$cidx)) { ]]>
<py:choose>
<py:when test="routers[ridx].listCommands()[cidx].getParamSpec() and (routers[ridx].listCommands()[cidx].getParamSpec().getType() == 'text')">
document.getElementById("paramrow").innerHTML=' \
<th align="left"> \
<label for="param">3. ${routers[ridx].listCommands()[cidx].getParamSpec().getName()}:</label> \
</th> \
<td align="left"> \
<input type="text" id="param1" name="param1" value="${routers[ridx].listCommands()[cidx].getParamSpec().getDefault()}" /></td>';
</py:when>
<py:otherwise>
document.getElementById("paramrow").innerHTML='';
</py:otherwise>
</py:choose>
}
</py:for>
</py:for>
}
function updateFormCommands()
{
var rs=document.getElementById("routerselect");
<py:for each="ridx,router in enumerate(routers)">
if(rs.options[rs.selectedIndex].value==$ridx) {
document.getElementById("commandselect").innerHTML='<py:for each="cidx,cmd in enumerate(routers[ridx].listCommands())"><py:choose><py:when test="cidx == default_command"><option value="$cidx" selected="selected">${cmd.getName()}</option></py:when><py:otherwise><option value="$cidx">${cmd.getName()}</option></py:otherwise></py:choose></py:for>';
}
</py:for>
updateFormParams()
}
</script>
</head>
<body class="index">
<script>
window.onload=updateFormCommands;
</script>
<div id="header">
<py:choose>
<py:when test="defaults.header">
<h1>ULG - $defaults.header</h1>
</py:when>
<py:otherwise>
<h1>ULG</h1>
</py:otherwise>
</py:choose>
</div>
<p>Select router to perform operation on, then select a command to perform and add (optional) argument if needed.</p>
<form action="runcommand" method="post">
<input type="hidden" name="session" value="$default_session" py:if="defined('default_session') and (default_session)" />
<table summary="Form settings">
<tbody>
<tr>
<th align="left"><label for="router">1. Router selection:</label></th>
<td>
<select id="routerselect" name="router" onchange="updateFormCommands()">
<py:for each="ridx,rtr in enumerate(routers)">
<py:choose>
<py:when test="ridx == default_router">
<option value="$ridx" selected="selected">
${rtr.getName()}
</option>
</py:when>
<py:otherwise>
<option value="$ridx">
${rtr.getName()}
</option>
</py:otherwise>
</py:choose>
</py:for>
</select>
</td>
</tr>
<tr height="10">
</tr>
<tr>
<th align="left" valign="top">2. Command selection:</th>
<td align="left">
<select id="commandselect" name="command" onchange="updateFormParams()">
<py:for each="cidx,cmd in enumerate(routers[default_router].listCommands())">
<py:choose>
<py:when test="cidx == default_command">
<option value="$cidx" selected="selected">
${cmd.getName()}
</option>
</py:when>
<py:otherwise>
<option value="$cidx">
${cmd.getName()}
</option>
</py:otherwise>
</py:choose>
</py:for>
</select>
</td>
</tr>
<tr height="10"></tr>
<tr id="paramrow">
</tr>
<tr>
<td></td>
<td>
<input type="submit" value="Submit" />
</td>
</tr>
</tbody>
</table>
</form>
<div id="result">
<hr/>
<py:choose>
<py:when test="defined('result')">
${result}
</py:when>
<py:otherwise>
<em>No result.</em>
</py:otherwise>
</py:choose>
<p py:if="defined('refresh') and (refresh>0)">
<em>Refreshing in $refresh seconds.</em>
</p>
</div>
<div id="footer">
<hr/>
<p class="legalese" align="right"><small>© 2012 Tomas Hlavacek</small></p>
</div>
</body>
</html>
......@@ -19,21 +19,51 @@
document.getElementById("paramsect").innerHTML=' \
<py:for each="pidx,param in enumerate(routers[ridx].listCommands()[cidx].getParamSpecs())">
<py:choose>
<py:when test="param.getType() == 'select'">
<tr> SELECT TODO!!! </tr> \
</py:when>
<py:otherwise>
<tr> \
<th align="left"> \
<label for="param">${pidx+3}. ${param.getName()}:</label> \
</th> \
<tr height="10"></tr> \
<tr> \
<th align="left"> \
${pidx+3}. ${param.getName()}: \
</th> \
<py:choose>
<py:when test="param.getType() == 'select'">
<td align="left"> \
<input type="text" name="param${pidx}" value="${param.getDefault()}" /> \
<select name="param${pidx}"> \
<py:for each="paridx,parname in enumerate(param.getOptionNames())">
<py:choose>
<py:when test="default_routerid == ridx and default_commandid == cidx and defined('default_params') and pidx &lt; len(default_params) and paridx == int(default_params[pidx])">
<option value="$paridx" selected="selected"> \
${parname} \
</option> \
</py:when>
<py:when test="paridx == param.getDefault()">
<option value="$paridx" selected="selected"> \
${parname} \
</option> \
</py:when>
<py:otherwise>
<option value="$paridx"> \
${parname} \
</option> \
</py:otherwise>
</py:choose>
</py:for>
</select> \
</td> \
</tr> \
</py:otherwise>
</py:choose>
</py:when>
<py:otherwise>
<td align="left"> \
<py:choose>
<py:when test="default_routerid == ridx and default_commandid == cidx and defined('default_params') and pidx &lt; len(default_params)">
<input type="text" name="param${pidx}" value="${default_params[pidx]}" /> \
</py:when>
<py:otherwise>
<input type="text" name="param${pidx}" value="${param.getDefault()}" /> \
</py:otherwise>
</py:choose>
</td> \
</py:otherwise>
</py:choose>
</tr> \
</py:for>';
}
</py:for>
......@@ -45,7 +75,17 @@
var rs=document.getElementById("routerselect");
<py:for each="ridx,router in enumerate(routers)">
if(rs.options[rs.selectedIndex].value==$ridx) {
document.getElementById("commandselect").innerHTML='<py:for each="cidx,cmd in enumerate(routers[ridx].listCommands())"><py:choose><py:when test="cidx == default_commandid"><option value="$cidx" selected="selected">${cmd.getName()}</option></py:when><py:otherwise><option value="$cidx">${cmd.getName()}</option></py:otherwise></py:choose></py:for>';
document.getElementById("commandselect").innerHTML=' \
<py:for each="cidx,cmd in enumerate(routers[ridx].listCommands())">
<py:choose>
<py:when test="default_routerid == ridx and default_commandid == cidx">
<option value="$cidx" selected="selected">${cmd.getName()}</option> \
</py:when>
<py:otherwise>
<option value="$cidx">${cmd.getName()}</option> \
</py:otherwise>
</py:choose>
</py:for>';
}
</py:for>
......@@ -69,12 +109,12 @@
</py:choose>
</div>
<p>Select router to perform operation on, then select a command to perform and add (optional) argument if needed.</p>
<form action="index.py?action=runcommand" method="post">
<form action="${getFormURL()}" method="post">
<input type="hidden" name="sessionid" value="$default_sessionid" py:if="defined('default_sessionid') and (default_sessionid)" />
<table summary="Form settings">
<tbody>
<tr>
<th align="left"><label for="router">1. Router selection:</label></th>
<th align="left">1. Router selection:</th>
<td>
<select id="routerselect" name="routerid" onchange="updateFormCommands()">
<py:for each="ridx,rtr in enumerate(routers)">
......@@ -94,8 +134,7 @@
</select>
</td>
</tr>
<tr height="10">
</tr>
<tr height="10"></tr>
<tr>
<th align="left" valign="top">2. Command selection:</th>
<td align="left">
......@@ -103,13 +142,13 @@
</select>
</td>
</tr>
<tr height="10"></tr>
</tbody>
<tbody id="paramsect">
</tbody>
<tbody>
<tr height="10"></tr>
<tr>
<td></td>
<th><br/></th>
<td>
<input type="submit" value="Submit" />
</td>
......
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:py="http://genshi.edgewall.org/">
<head>
<title>Universal Looking Glass</title>
<py:if test="defined('refresh')">
<meta http-equiv="refresh" content="$refresh" py:if="defined('refresh') and (refresh>0)" />
</py:if>
<script type="text/javascript">
function updateFormParams()
{
var rs=document.getElementById("routerselect");
var cs=document.getElementById("commandselect");
<py:for each="ridx,router in enumerate(routers)">
<py:for each="cidx,cmd in enumerate(routers[ridx].listCommands())">
<![CDATA[ if((rs.options[rs.selectedIndex].value==$ridx) && (cs.options[cs.selectedIndex].value==$cidx)) { ]]>
document.getElementById("paramsect").innerHTML=' \
<py:for each="pidx,param in enumerate(routers[ridx].listCommands()[cidx].getParamSpecs())">
<py:choose>
<py:when test="param.getType() == 'select'">
<tr> SELECT TODO!!! </tr> \
</py:when>
<py:otherwise>
<tr> \
<th align="left"> \
<label for="param">${pidx+3}. ${param.getName()}:</label> \
</th> \
<td align="left"> \
<input type="text" name="param${pidx}" value="${param.getDefault()}" /> \
</td> \
</tr> \
</py:otherwise>
</py:choose>
</py:for>';
}
</py:for>
</py:for>
}
function updateFormCommands()
{
var rs=document.getElementById("routerselect");
<py:for each="ridx,router in enumerate(routers)">
if(rs.options[rs.selectedIndex].value==$ridx) {
document.getElementById("commandselect").innerHTML='<py:for each="cidx,cmd in enumerate(routers[ridx].listCommands())"><py:choose><py:when test="cidx == default_commandid"><option value="$cidx" selected="selected">${cmd.getName()}</option></py:when><py:otherwise><option value="$cidx">${cmd.getName()}</option></py:otherwise></py:choose></py:for>';
}
</py:for>
updateFormParams()
}
</script>
</head>
<body class="index">
<script>
window.onload=updateFormCommands;
</script>
<div id="header">
<py:choose>
<py:when test="defaults.header">
<h1>ULG - $defaults.header</h1>
</py:when>
<py:otherwise>
<h1>ULG</h1>
</py:otherwise>
</py:choose>
</div>
<p>Select router to perform operation on, then select a command to perform and add (optional) argument if needed.</p>
<form action="runcommand" method="post">
<input type="hidden" name="sessionid" value="$default_sessionid" py:if="defined('default_sessionid') and (default_sessionid)" />
<table summary="Form settings">
<tbody>
<tr>
<th align="left"><label for="router">1. Router selection:</label></th>
<td>
<select id="routerselect" name="routerid" onchange="updateFormCommands()">
<py:for each="ridx,rtr in enumerate(routers)">
<py:choose>
<py:when test="ridx == default_routerid">
<option value="$ridx" selected="selected">
${rtr.getName()}
</option>
</py:when>
<py:otherwise>
<option value="$ridx">
${rtr.getName()}
</option>
</py:otherwise>
</py:choose>
</py:for>
</select>
</td>
</tr>
<tr height="10">
</tr>
<tr>
<th align="left" valign="top">2. Command selection:</th>
<td align="left">
<select id="commandselect" name="commandid" onchange="updateFormParams()">
</select>
</td>
</tr>
<tr height="10"></tr>
</tbody>
<tbody id="paramsect">
</tbody>
<tbody>
<tr>
<td></td>
<td>
<input type="submit" value="Submit" />
</td>
</tr>
</tbody>
</table>
</form>
<div id="result">
<hr/>
<py:choose>
<py:when test="defined('result')">
${result}
</py:when>
<py:otherwise>
<em>No result.</em>
</py:otherwise>
</py:choose>
<p py:if="defined('refresh') and (refresh>0)">
<em>Refreshing in $refresh seconds.</em>
</p>
</div>
<div id="footer">
<hr/>
<p class="legalese" align="right"><small>(c) 2012 Tomas Hlavacek</small></p>
</div>
</body>
</html>
......@@ -21,47 +21,172 @@
# Imports
import os, sys
import random
import cherrypy
import config
import defaults
import ulgmodel
import ulg
import index
import sys
import re
import time
import traceback
def testRouterCommand(router=0,command=0,params=[]):
r = config.routers[router]
try:
if(not r.runCommand(r.listCommands()[command],params,ulg.Decorator())):
print "WARN: Outpit of test running command "+str(command)+" on router "+str(router)+" with parameters:"+str(params)+" is empty."
return False
except Exception as e:
print "FAIL: Test running command "+str(command)+" on router "+str(router)+" with parameters:"+str(params)+".\n Exception="+str(e)
return False
print "OK: Test running command "+str(command)+" on router "+str(router)+" with parameters:"+str(params)
return True
def testULGIndex(routerid=0,commandid=0,sessionid=None):
try:
u = ulg.ULGCgi()
c = u.renderULGIndex(routerid,commandid,sessionid)
if(c):
print "OK: Test render ULG CGI index"
return True
else:
print "WARN: Test render ULG CGI index is empty!"
return False
except Exception as e:
print "FAIL: Test render ULG CGI index.\n Exception="+str(e)
return False
def testULGAction(routerid=0,commandid=0,sessionid=None,maxtimes=10,interval=5,**params):
try:
u = ulg.ULGCgi()
rdr = u.renderULGAction(routerid=0,commandid=0,sessionid=None,**params)
m = re.compile('sessionid=([^"]+)"',re.M).search(rdr)
if(m):
sessionid = m.groups()[0]
print "OK(1/2): Test ULG run action passed with sessionid="+str(sessionid)
else:
print "FAILED ULG run action. No session ID returned."
return False
except Exception as e:
print "FAILED ULG run action.\n Exception="+str(e)
return False
i=0
while(i<maxtimes):
if(re.compile("refresh",re.M).search(u.renderULGResult(sessionid=sessionid))):
print "Test ULG result is not complete. Waiting another 5 seconds."
time.sleep(interval)
i+=1
else:
print "OK(2/2): Test ULG result is complete."
return True
print "FAIL: Test ULG result is not complete after "+str(maxtimes)
return False
def testULGSessions(sessionid=None):
try:
s1 = ulg.Session(sessionid,routerid=1,commandid=2,parameters={'baba':'bubu'},result='reeesult')
sid = s1.getSessionId()
s2 = ulg.Session.load(sid)
if(s1.getSessionId() == s2.getSessionId() and s1.getRouterId() == s2.getRouterId()):
print "OK: Test sessions."
return True
else:
print "WARN: Test sessions failed!"
return False
except Exception as e:
print "FAIL: Test sessions.\n Exception="+str(e)
return False
def testULGLock():
c = ulg.ULGCgi()
def cleanup(c):
for i in range(0,defaults.usage_limit):
c.decreaseUsage()
for i in range(0,defaults.usage_limit):
if not c.increaseUsage():
print """FAIL: Test lock. Increase usage rejected me while it should let me it.
(It can be effect of a real ULG running concurrently to tests."""
return False
if(c.increaseUsage()):
print "FAIL: Test lock. Increase usage accepted overlimit."
cleanup(c)
return False
c.decreaseUsage()
if(not c.increaseUsage()):
print """FAIL: Test lock. Increase usage rejected me while it should let me it.
(It can be effect of a real ULG running concurrently to tests."""
cleanup(c)
return False
cleanup(c)
print "OK: Test lock."
return True
def testULGRunParameter(router=0,command=4,params=['91.210.16.1']):
r = config.routers[router]
try:
if(not r.runCommand(r.listCommands()[command],params,ulg.Decorator())):
print "WARN: Output of test running command "+str(command)+" on router "+str(router)+" with parameters:"+str(params)+" is empty."
return False
except Exception as e:
print "FAIL: Test running command "+str(command)+" on router "+str(router)+" with parameters:"+str(params)+".\n Exception="+str(e)
print traceback.format_exc()
return False
print "OK: Test running command "+str(command)+" on router "+str(router)+" with parameters:"+str(params)
return True
#####################################
results = []
def runTest(result):
global results
results.append(result)
def reportResults():
global results
tests = len(results)
failed = [ridx for (ridx,r) in enumerate(results) if r == False]
passed = [ridx for (ridx,r) in enumerate(results) if r == True]
print """\n***** Results *****
Tests pased: %d/%d
Tests failed: %d/%d""" % (len(passed),tests,len(failed),tests)
print "Failed numbers: "+str(failed)+"\n"
# main
if __name__=="__main__":
r = config.routers[0]
# print r.runCommand(r.listCommands()[0],[])
runTest(testRouterCommand(router=0,command=0,params=[]))
runTest(testULGRunParameter(router=0,command=4,params=['91.210.16.1']))
# print "Test router 0 command 0 passed. \n\n"
runTest(testULGIndex(routerid=0,commandid=0,sessionid=None))
u = index.ULGCgi()
print u.renderULGIndex(routerid=0,commandid=0,sessionid=None)
runTest(testULGAction(routerid=0,commandid=0,sessionid=None,maxtimes=10,interval=5,**{}))
print "Test ULG index passed. \n\n"
runTest(testULGSessions())
rdr = u.renderULGAction(routerid=0,commandid=0,sessionid=None,**{})
print "Test ULG run action passed. Rdr exc = %s \n\n" % str(rdr)
m = re.compile('sessionid=([^"]+)"',re.M).search(rdr)
if(m):
sessionid = m.groups()[0]
print "Test ULG run action passed with sessionid="+str(sessionid) + "\n\n"
else:
print "Failed ULG run action.\n\n"
sys.exit(0)
runTest(testULGLock())
print u.renderULGResult(sessionid=sessionid)
print "Test ULG result passed 1st time. Sleeping 5 seconds."
time.sleep(5)
print u.renderULGResult(sessionid=sessionid)
print "Test ULG result passed 2nd time. Sleeping 5 seconds."
time.sleep(5)
print u.renderULGResult(sessionid=sessionid)
print "Test ULG result passed 3rd time. Finish."
reportResults()
#!/usr/bin/env python
#
# ULG - Universal Looking Glass
# by Tomas Hlavacek (tomas.hlavacek@nic.cz)
# last udate: June 21 2012
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
# Imports
import os, sys
import random
import time
import pickle
import config
import defaults
import ulgmodel
### ULG cron script
class ULGCron:
def __init__(self):
pass
def run(self):
pass
# main
if __name__=="__main__":
return ULGCron().run()
This diff is collapsed.
#!/usr/bin/env python
#
# ULG - Universal Looking Glass
# by Tomas Hlavacek (tomas.hlavacek@nic.cz)
# last udate: June 21 2012
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
# Imports
import os
import socket
import re
import defaults
import ulgmodel
class BirdRouterLocal(ulgmodel.LocalRouter):
DefaultCommands = [ulgmodel.TextCommand('show protocols', [ulgmodel.TextParameter('.*')])]