Commit 3f9caa80 authored by Tomas Hlavacek's avatar Tomas Hlavacek

ULG Cisco decorators and select commands added.

parent fe1747c3
......@@ -7,7 +7,8 @@ ULG development version 0.1
Basic instalation procedure is:
1) install prerequisites: Python 2.7, Genshi, Python CGI module and pexpect
1) install prerequisites: Python 2.7, Genshi, Python CGI module, urllib
and pexpect
2) deploy files in src directory to some place in WWW tree
3) edit config.py to set up routers and credentials
4) edit defaults.py to set up paths
......
......@@ -25,6 +25,7 @@ usage_limit = 1 # maximum concurrently processe
# Settings defaults
always_start_thread = True
debug = False
rescan_on_display = False
persistent_storage_file = '/tmp/ulg.data'
session_dir = '/tmp'
usage_counter_file = '/tmp/ulg.lock'
......@@ -49,6 +50,9 @@ STRING_SESSION_OVERLIMIT = "<em>Limit of maximum concurrently running sessions a
STRING_ARBITRARY_ERROR = "Error encountered. Operation aborted. See log for further details."
STRING_IPADDRESS = "IP address"
STRING_IPSUBNET = "IP subnet"
STRING_MACADDRESS = "MAC address"
STRING_NONEORINTORIPADDRESS = "None or Interface or IP address"
STRING_INTERFACE = "Interface"
# URL generator functions
def getASNURL(asn):
......
......@@ -28,21 +28,21 @@
<py:when test="param.getType() == 'select'">
<td align="left"> \
<select name="param${pidx}"> \
<py:for each="paridx,parname in enumerate(param.getOptionNames())">
<py:for each="paridx,partuple in enumerate(param.getOptions())">
<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} \
<py:when test="default_routerid == ridx and default_commandid == cidx and defined('default_params') and partuple[0] == default_params[pidx]">
<option value="${partuple[0]}" selected="selected"> \
${partuple[1]} \
</option> \
</py:when>
<py:when test="paridx == param.getDefault()">
<option value="$paridx" selected="selected"> \
${parname} \
<py:when test="partuple[0] == param.getDefault()">
<option value="${partuple[0]}" selected="selected"> \
${partuple[1]} \
</option> \
</py:when>
<py:otherwise>
<option value="$paridx"> \
${parname} \
<option value="${partuple[0]}"> \
${partuple[1]} \
</option> \
</py:otherwise>
</py:choose>
......@@ -157,17 +157,17 @@
</table>
</form>
<div id="result">
<hr/>
<hr py:if="(defined('result') and result) or (defined('refresh') and (refresh>0))"/>
<py:choose>
<py:when test="defined('result') and 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>
<em>Please wait for data from the router...</em><br/>
<em>The page is going to be refreshed in $refresh seconds.</em>
</p>
</div>
<div id="footer">
......
......@@ -164,6 +164,42 @@ def testULGLog(testmessage="Test message no. 1."):
print traceback.format_exc()
return False
def testULGRescan():
try:
for r in config.routers:
r.rescanHook()
print "OK: Test running rescan."
return True
except Exception as e:
print "FAIL: Test running rescan.\n Exception="+str(e)
print traceback.format_exc()
return False
def testULGPersistentStorage():
try:
ps = ulgmodel.PersistentStorage.load()
ps.set('test','teststring')
ps.save()
ps2 = ulgmodel.PersistentStorage.load()
if(ps2.get('test') == 'teststring'):
ps2.delete('test')
if(ps2.get('test') == None):
print "OK: Test persistent storage."
return True
else:
print "FAIL: Test persistent storage: Delete performed no effect."
return False
else:
print "FAIL: Test persistent storage: Set performed no effect."
return False
except Exception as e:
print "FAIL: Test persistent storage.\n Exception="+str(e)
print traceback.format_exc()
return False
#####################################
results = []
......@@ -199,6 +235,10 @@ if __name__=="__main__":
runTest(testULGLog())
runTest(testULGRescan())
runTest(testULGPersistentStorage())
reportResults()
......@@ -23,6 +23,7 @@ import os, sys
import random
import time
import pickle
import re
import config
import defaults
......@@ -31,6 +32,8 @@ import ulgmodel
### ULG cron script
SESSION_FILE_REGEX='^ulg-.*\.session$'
class ULGCron:
def __init__(self):
pass
......@@ -40,13 +43,21 @@ class ULGCron:
r.rescanHook()
def clearSessions(self):
pass
sre = re.compile(SESSION_FILE_REGEX)
for file in os.listdir(defaults.session_dir):
if sre.match(file):
fp = defaults.session_dir+'/'+file
ulgmodel.log('Removing file '+fp)
try:
os.unlink(fp)
except OSError as e:
ulgmodel.log('Error while removing file '+fp+' '+str(e))
def run(self):
ulgmodel.log("ULG cron run.")
ulgmodel.log('ULG cron run.')
self.rescanRouters()
self.clearSessions()
ulgmodel.log("ULG cron finished.")
ulgmodel.log('ULG cron finished.')
# main
......
......@@ -30,6 +30,7 @@ import md5
import pickle
import re
import fcntl
import urllib
import traceback
import config
......@@ -163,9 +164,9 @@ class DecoratorHelper:
return os.path.basename(__file__)
def getURL(self,action,parameters={}):
url=self.getScriptURL() + ("?action=%s" % action)
url=self.getScriptURL() + ("?action=%s" % urllib.quote(action))
for k in parameters.keys():
url = url + '&' + k + '=' + parameters[k]
url = url + '&' + k + '=' + urllib.quote(parameters[k])
return url
def getIndexURL(self):
......@@ -201,7 +202,7 @@ class DecoratorHelper:
return ('<pre>%s</pre>' % text)
def ahref(self,url,text):
return ('<a href=%s>%s</a>' % (url,text))
return ('<a href=%s>%s</a>' % (str(url),str(text)))
class ULGCgi:
def __init__(self):
......@@ -354,11 +355,11 @@ class ULGCgi:
session.cleanParameters()
for pidx,ps in enumerate(session.getCommand().getParamSpecs()):
if('param'+str(pidx) in moreparams.keys()):
session.addParameter(moreparams['param'+str(pidx)])
session.addParameter(str(moreparams['param'+str(pidx)]))
else:
session.addParameter(ps.getDefault())
# run the command (possibly in a separate thread)
# run the command (possibly in a separate process)
self.runCommand(session)
# redirect to the session display
......
......@@ -27,21 +27,55 @@ import defaults
import ulgmodel
# module globals
STRING_EXPECT_SSH_NEWKEY='Are you sure you want to continue connecting'
STRING_EXPECT_PASSWORD='(P|p)assword:'
STRING_EXPECT_SHELL_PROMPT_REGEXP = '\n[a-zA-Z0-9\._-]+>'
BGP_IPV6_TABLE_SPLITLINE_REGEXP='^\s*[0-9a-fA-F:]+\s*$'
BGP_IPV6_TABLE_HEADER_REGEXP='^\s*(Neighbor)\s+(V)\s+(AS)\s+(MsgRcvd)\s+(MsgSent)\s+(TblVer)\s+(InQ)\s+(OutQ)\s+(Up/Down)\s+(State/PfxRcd)\s*$'
BGP_IPV6_TABLE_LINE_REGEXP='^\s*([0-9a-fA-F:]+)\s+([0-9]+)\s+([0-9]+)\s+([0-9]+)\s+([0-9]+)\s+([0-9]+)\s+([0-9]+)\s+([0-9]+)\s+([a-zA-Z0-9:]+)\s+([a-zA-Z0-9]+|[a-zA-Z0-9]+\s\(Admin\))\s*$'
BGP_IPV4_TABLE_LINE_REGEXP='^\s*([0-9\.]+)\s+([0-9]+)\s+([0-9]+)\s+([0-9]+)\s+([0-9]+)\s+([0-9]+)\s+([0-9]+)\s+([0-9]+)\s+([a-zA-Z0-9:]+)\s+([a-zA-Z0-9]+|[a-zA-Z0-9]+\s\(Admin\))\s*$'
BGP_IPV4_TABLE_HEADER_REGEXP='^\s*(Neighbor)\s+(V)\s+(AS)\s+(MsgRcvd)\s+(MsgSent)\s+(TblVer)\s+(InQ)\s+(OutQ)\s+(Up/Down)\s+(State/PfxRcd)\s*$'
RESCAN_BGP_IPv4_COMMAND='show bgp ipv4 unicast summary'
RESCAN_BGP_IPv6_COMMAND='show bgp ipv6 unicast summary'
IPV4_SUBNET_REGEXP = '^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}(/[0-9]{1,2}){0,1}]$'
IPV4_ADDRESS_REGEXP = '^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$'
IPV6_SUBNET_REGEXP = '^[0-9a-fA-F:]+(/[0-9]{1,2}){0,1}$'
IPV6_ADDRESS_REGEXP = '^[0-9a-fA-F:]+$'
MAC_ADDRESS_REGEXP = '^[0-9a-fA-F]{4}\.[0-9a-fA-F]{4}\.[0-9a-fA-F]{4}$'
def normalizeBGPIPv6SplitLines(lines):
"""This function concatenates lines with longer IPv6 addresses that
router splits (for no obvious reason)."""
result = []
slr = re.compile(BGP_IPV6_TABLE_SPLITLINE_REGEXP)
b = None
for l in lines:
if(b):
result.append(b + l)
b = None
elif(slr.match(l)):
b = l
else:
result.append(l)
return result
# classes
class CiscoCommandBgpIPv4Sum(ulgmodel.TextCommand):
COMMAND_TEXT='show bgp ipv4 unicast summary'
TABLE_HEADER_REGEXP='^\s*(Neighbor)\s+(V)\s+(AS)\s+(MsgRcvd)\s+(MsgSent)\s+(TblVer)\s+(InQ)\s+(OutQ)\s+(Up/Down)\s+(State/PfxRcd)\s*$'
TABLE_LINE_REGEXP='^\s*([0-9\.]+)\s+([0-9]+)\s+([0-9]+)\s+([0-9]+)\s+([0-9]+)\s+([0-9]+)\s+([0-9]+)\s+([0-9]+)\s+([a-z0-9:]+)\s+([a-zA-Z0-9]+|[a-zA-Z0-9]+\s\(Admin\))\s*$'
RED_STATES = ['Idle', 'Active']
YELLOW_STATES = ['Idle (Admin)',]
class CiscoCommandBgpIPv46Sum(ulgmodel.TextCommand):
""" Abstract class, baseline for IPv4 and IPv6 versions. """
def __init__(self,name=None,peer_address_command=None):
self.command=CiscoCommandBgpIPv4Sum.COMMAND_TEXT
def __init__(self,name=None,peer_address_command=None,peer_received_command=None):
self.command=self.COMMAND_TEXT
self.param_specs=[]
self.peer_address_command = peer_address_command
self.peer_received_command = peer_received_command
if(name==None):
if(self.param_specs):
......@@ -51,26 +85,58 @@ class CiscoCommandBgpIPv4Sum(ulgmodel.TextCommand):
else:
self.name = name
def _getPeerURL(self,decorator_helper,router,peer_address):
return decorator_helper.getRuncommandURL({'routerid':str(decorator_helper.getRouterID(router)),
'commandid':str(decorator_helper.getCommandID(router,self.peer_address_command)),
'param0':peer_address})
if decorator_helper and self.peer_address_command:
return decorator_helper.getRuncommandURL({'routerid':str(decorator_helper.getRouterID(router)),
'commandid':str(decorator_helper.getCommandID(router,self.peer_address_command)),
'param0':peer_address})
else:
return None
def _getPeerReceivedURL(self,decorator_helper,router,peer_address):
if decorator_helper and self.peer_received_command:
return decorator_helper.getRuncommandURL({'routerid':str(decorator_helper.getRouterID(router)),
'commandid':str(decorator_helper.getCommandID(router,self.peer_received_command)),
'param0':peer_address})
else:
return None
def _getPeerTableCell(self,decorator_helper,router,peer):
url = self._getPeerURL(decorator_helper,router,peer)
if url:
return decorator_helper.ahref(url,peer)
else:
return peer
def _getReceivedTableCell(self,decorator_helper,router,peer,received):
if re.compile('[0-9]+').match(received):
url = self._getPeerReceivedURL(decorator_helper,router,peer)
if url:
return decorator_helper.ahref(url,received)
else:
return received
else:
return received
def _decorateTableLine(self,line,decorator_helper,router):
lrm = re.compile(CiscoCommandBgpIPv4Sum.TABLE_LINE_REGEXP).match(line)
lrm = re.compile(self.table_line_regexp).match(line)
if(lrm):
# color selection
if(lrm.group(10) in CiscoCommandBgpIPv4Sum.YELLOW_STATES):
if(lrm.group(10) in self.YELLOW_STATES):
color = ulgmodel.TableDecorator.YELLOW
elif(lrm.group(10) in CiscoCommandBgpIPv4Sum.RED_STATES):
elif(lrm.group(10) in self.RED_STATES):
color = ulgmodel.TableDecorator.RED
else:
color = ulgmodel.TableDecorator.GREEN
# generate table content
return [
(decorator_helper.ahref(self._getPeerURL(decorator_helper,router,lrm.group(1)),lrm.group(1)),color)
if decorator_helper and self.peer_address_command else (lrm.group(1),color),
(self._getPeerTableCell(decorator_helper,router,lrm.group(1)),color),
(lrm.group(2),color),
(decorator_helper.ahref(defaults.getASNURL(lrm.group(3)),lrm.group(3)),color),
(lrm.group(4),color),
......@@ -79,7 +145,7 @@ class CiscoCommandBgpIPv4Sum(ulgmodel.TextCommand):
(lrm.group(7),color),
(lrm.group(8),color),
(lrm.group(9),color),
(lrm.group(10),color),
(self._getReceivedTableCell(decorator_helper,router,lrm.group(1),lrm.group(10)),color),
]
else:
raise Exception("Can not parse line: "+l)
......@@ -96,8 +162,8 @@ class CiscoCommandBgpIPv4Sum(ulgmodel.TextCommand):
table_header=[]
tb = False
header_regexp = re.compile(CiscoCommandBgpIPv4Sum.TABLE_HEADER_REGEXP)
line_regexp = re.compile(CiscoCommandBgpIPv4Sum.TABLE_LINE_REGEXP)
header_regexp = re.compile(self.table_header_regexp)
line_regexp = re.compile(self.table_line_regexp)
for l in lines:
if(tb):
# inside table body
......@@ -116,50 +182,174 @@ class CiscoCommandBgpIPv4Sum(ulgmodel.TextCommand):
return ulgmodel.TableDecorator(table,table_header,before=decorator_helper.pre(before)).decorate()
class CiscoCommandBgpIPv4Sum(CiscoCommandBgpIPv46Sum):
COMMAND_TEXT='show bgp ipv4 unicast summary'
table_line_regexp=BGP_IPV4_TABLE_LINE_REGEXP
table_header_regexp=BGP_IPV4_TABLE_HEADER_REGEXP
RED_STATES = ['Idle', 'Active']
YELLOW_STATES = ['Idle (Admin)',]
def __init__(self,name=None,peer_address_command=None,peer_received_command=None):
return CiscoCommandBgpIPv46Sum.__init__(self,name,peer_address_command,peer_received_command)
class CiscoCommandBgpIPv6Sum(CiscoCommandBgpIPv46Sum):
COMMAND_TEXT='show bgp ipv6 unicast summary'
table_line_regexp=BGP_IPV6_TABLE_LINE_REGEXP
table_header_regexp=BGP_IPV6_TABLE_HEADER_REGEXP
RED_STATES = ['Idle', 'Active']
YELLOW_STATES = ['Idle (Admin)',]
def __init__(self,name=None,peer_address_command=None,peer_received_command=None):
return CiscoCommandBgpIPv46Sum.__init__(self,name,peer_address_command,peer_received_command)
def decorateResult(self,result,router=None,decorator_helper=None):
res=''
for l in normalizeBGPIPv6SplitLines(str.splitlines(result)):
res = res + "\n" + l
return super(CiscoCommandBgpIPv6Sum,self).decorateResult(res,router,decorator_helper)
class CiscoCommandShowBgpIPv46Select(ulgmodel.TextCommand):
def __init__(self,peers,name=None):
peer_param = ulgmodel.SelectionParameter([tuple((p,p,)) for p in peers],
name=defaults.STRING_IPADDRESS)
ulgmodel.TextCommand.__init__(self,self.COMMAND_TEXT,param_specs=[peer_param],name=name)
class CiscoCommandShowBgpIPv4Neigh(CiscoCommandShowBgpIPv46Select):
COMMAND_TEXT='show bgp ipv4 unicast neighbor %s'
class CiscoCommandShowBgpIPv6Neigh(CiscoCommandShowBgpIPv46Select):
COMMAND_TEXT='show bgp ipv6 unicast neighbor %s'
class CiscoCommandShowBgpIPv4NeighAdv(CiscoCommandShowBgpIPv46Select):
COMMAND_TEXT='show bgp ipv4 unicast neighbor %s advertised'
class CiscoCommandShowBgpIPv6NeighAdv(CiscoCommandShowBgpIPv46Select):
COMMAND_TEXT='show bgp ipv6 unicast neighbor %s advertised'
class CiscoCommandShowBgpIPv4NeighRecv(CiscoCommandShowBgpIPv46Select):
COMMAND_TEXT='show bgp ipv4 unicast neighbor %s received-routes'
class CiscoCommandShowBgpIPv6NeighRecv(CiscoCommandShowBgpIPv46Select):
COMMAND_TEXT='show bgp ipv6 unicast neighbor %s received-routes'
class CiscoRouter(ulgmodel.RemoteRouter):
RegExIPv4Subnet = '^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}(/[0-9]{1,2}){0,1}]$'
RegExIPv4 = '^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$'
RegExIPv6Subnet = '^[0-9a-fA-F:]+(/[0-9]{1,2}){0,1}$'
RegExIPv6 = '^[0-9a-fA-F:]+$'
_show_bgp_ipv4_uni_neigh = ulgmodel.TextCommand('show bgp ipv4 unicast neighbor %s',[ulgmodel.TextParameter(RegExIPv4,name=defaults.STRING_IPADDRESS)])
DefaultCommands = [ulgmodel.TextCommand('show version'),
ulgmodel.TextCommand('show bgp ipv4 unicast %s', [ulgmodel.TextParameter(RegExIPv4Subnet,name=defaults.STRING_IPSUBNET)]),
ulgmodel.TextCommand('show bgp ipv6 unicast %s', [ulgmodel.TextParameter(RegExIPv6Subnet,name=defaults.STRING_IPSUBNET)]),
CiscoCommandBgpIPv4Sum('show bgp ipv4 unicast summary (+DECORATOR)',peer_address_command=_show_bgp_ipv4_uni_neigh),
ulgmodel.TextCommand('show bgp ipv4 unicast summary'),
ulgmodel.TextCommand('show bgp ipv6 unicast summary'),
_show_bgp_ipv4_uni_neigh,
ulgmodel.TextCommand('show bgp ipv6 unicast neighbor %s',[ulgmodel.TextParameter(RegExIPv6,name=defaults.STRING_IPADDRESS)]),
ulgmodel.TextCommand('show bgp ipv4 unicast neighbor %s received-routes',[ulgmodel.TextParameter(RegExIPv4,name=defaults.STRING_IPADDRESS)]),
ulgmodel.TextCommand('show bgp ipv6 unicast neighbor %s received-routes',[ulgmodel.TextParameter(RegExIPv6,name=defaults.STRING_IPADDRESS)]),
ulgmodel.TextCommand('show bgp ipv4 unicast neighbor %s advertised',[ulgmodel.TextParameter(RegExIPv4,name=defaults.STRING_IPADDRESS)]),
ulgmodel.TextCommand('show bgp ipv6 unicast neighbor %s advertised',[ulgmodel.TextParameter(RegExIPv6,name=defaults.STRING_IPADDRESS)]),
ulgmodel.TextCommand('show ip route %s',[ulgmodel.TextParameter(RegExIPv4,name=defaults.STRING_IPADDRESS)]),
ulgmodel.TextCommand('show ipv6 unicast route %s',[ulgmodel.TextParameter(RegExIPv6,name=defaults.STRING_IPADDRESS)]),
# ulgmodel.TextCommand('show bgp ipv4 uni neighbor',[ulgmodel.SelectionParameter([('91.210.16.1','91.210.16.1'),('91.210.16.2','91.210.16.2'),('91.210.16.3','91.210.16.3')],name=defaults.STRING_IPADDRESS)]),
]
STRING_SHELL_PROMPT_REGEXP = '\n[a-zA-Z0-9\._-]+>'
def __init__(self, host, user, password, port=22, commands=None):
PS_KEY_BGPV4 = '-bgpipv4'
PS_KEY_BGPV6 = '-bgpipv6'
def _getDefaultCommands(self):
_show_bgp_ipv4_uni_neigh = CiscoCommandShowBgpIPv4Neigh(self.getBGPIPv4Peers())
_show_bgp_ipv4_uni_neigh_advertised = CiscoCommandShowBgpIPv4NeighAdv(self.getBGPIPv4Peers())
_show_bgp_ipv4_uni_neigh_received_routes = CiscoCommandShowBgpIPv4NeighRecv(self.getBGPIPv4Peers())
_show_bgp_ipv6_uni_neigh = CiscoCommandShowBgpIPv6Neigh(self.getBGPIPv6Peers())
_show_bgp_ipv6_uni_neigh_advertised = CiscoCommandShowBgpIPv6NeighAdv(self.getBGPIPv6Peers())
_show_bgp_ipv6_uni_neigh_received_routes = CiscoCommandShowBgpIPv6NeighRecv(self.getBGPIPv6Peers())
return [ulgmodel.TextCommand('show version'),
ulgmodel.TextCommand('show interfaces status'),
CiscoCommandBgpIPv4Sum('show bgp ipv4 unicast summary',
peer_address_command=_show_bgp_ipv4_uni_neigh,
peer_received_command=_show_bgp_ipv4_uni_neigh_received_routes),
CiscoCommandBgpIPv6Sum('show bgp ipv6 unicast summary',
peer_address_command=_show_bgp_ipv6_uni_neigh,
peer_received_command=_show_bgp_ipv6_uni_neigh_received_routes),
_show_bgp_ipv4_uni_neigh,
_show_bgp_ipv6_uni_neigh,
_show_bgp_ipv4_uni_neigh_received_routes,
_show_bgp_ipv6_uni_neigh_received_routes,
_show_bgp_ipv4_uni_neigh_advertised,
_show_bgp_ipv6_uni_neigh_advertised,
ulgmodel.TextCommand('show ip route %s',[ulgmodel.TextParameter(IPV4_ADDRESS_REGEXP,name=defaults.STRING_IPADDRESS)]),
ulgmodel.TextCommand('show ipv6 unicast route %s',[ulgmodel.TextParameter(IPV6_ADDRESS_REGEXP,name=defaults.STRING_IPADDRESS)]),
ulgmodel.TextCommand('show ip arp %s',[ulgmodel.TextParameter('.*',name=defaults.STRING_NONEORINTORIPADDRESS)]),
ulgmodel.TextCommand('show ipv6 neighbors %s',[ulgmodel.TextParameter('.*',name=defaults.STRING_NONEORINTORIPADDRESS)]),
ulgmodel.TextCommand('show mac-address-table address %s',[ulgmodel.TextParameter(MAC_ADDRESS_REGEXP,name=defaults.STRING_MACADDRESS)]),
ulgmodel.TextCommand('show mac-address-table interface %s',[ulgmodel.TextParameter('.*',name=defaults.STRING_INTERFACE)]),
]
def __init__(self, host, user, password, port=22, commands=None, enable_bgp=True):
self.setHost(host)
self.setPort(port)
self.setUser(user)
self.setPassword(password)
self.bgp_ipv4_peers = []
self.bgp_ipv6_peers = []
self.setName(host)
if enable_bgp:
if(defaults.rescan_on_display):
self.rescanHook()
else:
self.loadBGPPeers()
if(commands):
self.setCommands(commands)
else:
self.setCommands(CiscoRouter.DefaultCommands)
self.setName(host)
self.setCommands(self._getDefaultCommands())
def getForkNeeded(self):
return True
def rescanBGPPeers(self,command,regexp,ipv6=True):
table = self.runRawCommand(command)
peers = []
rlr = re.compile(regexp)
if ipv6:
lines = normalizeBGPIPv6SplitLines(str.splitlines(table))
else:
lines = str.splitlines(table)
for tl in lines:
rlrm = rlr.match(tl)
if(rlrm):
peers.append(rlrm.group(1))
return peers
def rescanBGPIPv4Peers(self):
self.bgp_ipv4_peers = self.rescanBGPPeers(RESCAN_BGP_IPv4_COMMAND,BGP_IPV4_TABLE_LINE_REGEXP,False)
def rescanBGPIPv6Peers(self):
self.bgp_ipv6_peers = self.rescanBGPPeers(RESCAN_BGP_IPv6_COMMAND,BGP_IPV6_TABLE_LINE_REGEXP,True)
def rescanHook(self):
self.rescanBGPIPv4Peers()
self.rescanBGPIPv6Peers()
self.saveBGPPeers()
def getBGPIPv4Peers(self):
return self.bgp_ipv4_peers
def getBGPIPv6Peers(self):
return self.bgp_ipv6_peers
def saveBGPPeers(self):
key4 = self.getHost() + self.PS_KEY_BGPV4
key6 = self.getHost() + self.PS_KEY_BGPV6
ps = ulgmodel.PersistentStorage.load()
ps.set(key4,self.getBGPIPv4Peers())
ps.set(key6,self.getBGPIPv6Peers())
ps.save()
def loadBGPPeers(self):
key4 = self.getHost() + self.PS_KEY_BGPV4
key6 = self.getHost() + self.PS_KEY_BGPV6
ps = ulgmodel.PersistentStorage.load()
self.bgp_ipv4_peers = ps.get(key4)
self.bgp_ipv6_peers = ps.get(key6)
if(not self.getBGPIPv4Peers()) or (not self.getBGPIPv6Peers()):
self.rescanHook()
def runRawCommand(self,command):
return self._runTextCommand(command)
......@@ -183,25 +373,25 @@ class CiscoRouter(ulgmodel.RemoteRouter):
raise Exception("pexpect session failed: SSH error.")
# check shell and preset terminal
i=p.expect([CiscoRouter.STRING_SHELL_PROMPT_REGEXP,pexpect.EOF])
i=p.expect([STRING_EXPECT_SHELL_PROMPT_REGEXP,pexpect.EOF])
if(i==0):
p.sendline('terminal length 0')
else:
raise Exception("pexpect session failed: Missing shell prompt.")
i=p.expect([CiscoRouter.STRING_SHELL_PROMPT_REGEXP,pexpect.EOF])
i=p.expect([STRING_EXPECT_SHELL_PROMPT_REGEXP,pexpect.EOF])
if(i==0):
p.sendline('terminal width 0')
else:
raise Exception("pexpect session failed: Missing shell prompt.")
i=p.expect([CiscoRouter.STRING_SHELL_PROMPT_REGEXP,pexpect.EOF])
i=p.expect([STRING_EXPECT_SHELL_PROMPT_REGEXP,pexpect.EOF])
if(i==0):
p.sendline(command)
else:
raise Exception("pexpect session failed: Missing shell prompt.")
p.expect([CiscoRouter.STRING_SHELL_PROMPT_REGEXP,pexpect.EOF])
p.expect([STRING_EXPECT_SHELL_PROMPT_REGEXP,pexpect.EOF])
def stripFirstLine(string):
lines = str.splitlines(string)
......
......@@ -24,6 +24,8 @@ import re
from time import localtime, strftime
from genshi.template import TemplateLoader
from genshi.core import Markup
import pickle
import fcntl
import defaults
......@@ -33,7 +35,7 @@ def log(*messages):
try:
with open(defaults.log_file, 'a') as l:
for m in messages:
l.write(strftime("%b %d %Y %H:%M:%S: ", localtime()) + m)
l.write(strftime("%b %d %Y %H:%M:%S: ", localtime()) + m + "\n")
except Exception:
pass
......@@ -41,18 +43,19 @@ def debug(message):
log('DEBUG:' + message)
class PersistentStorgage(object):
def __init__(self,filename=defaults.persistent_storage_file):
self.filename = filename
class PersistentStorage(object):
def __init__(self):
self.data = {}
def save(self):
f = open(self.filename,'wb')
def save(self,filename=defaults.persistent_storage_file):
# TODO: locking
f = open(filename,'wb')
pickle.dump(self, f)