blob: 5d547fad9926b06af431d48f110dda63e8ecfa0a [file] [log] [blame]
andrewonlab95ce8322014-10-13 14:12:04 -04001#!/usr/bin/env python
2
kelvin8ec71442015-01-15 16:57:00 -08003"""
andrewonlab95ce8322014-10-13 14:12:04 -04004This driver enters the onos> prompt to issue commands.
5
kelvin8ec71442015-01-15 16:57:00 -08006Please follow the coding style demonstrated by existing
andrewonlab95ce8322014-10-13 14:12:04 -04007functions and document properly.
8
9If you are a contributor to the driver, please
10list your email here for future contact:
11
12jhall@onlab.us
13andrew@onlab.us
Jon Halle8217482014-10-17 13:49:14 -040014shreya@onlab.us
andrewonlab95ce8322014-10-13 14:12:04 -040015
16OCT 13 2014
17
kelvin8ec71442015-01-15 16:57:00 -080018"""
andrewonlab95ce8322014-10-13 14:12:04 -040019import sys
andrewonlab95ce8322014-10-13 14:12:04 -040020import pexpect
21import re
Jon Hall30b82fa2015-03-04 17:15:43 -080022import json
23import types
kelvin8ec71442015-01-15 16:57:00 -080024sys.path.append( "../" )
andrewonlab95ce8322014-10-13 14:12:04 -040025from drivers.common.clidriver import CLI
26
andrewonlab95ce8322014-10-13 14:12:04 -040027
kelvin8ec71442015-01-15 16:57:00 -080028class OnosCliDriver( CLI ):
andrewonlab95ce8322014-10-13 14:12:04 -040029
kelvin8ec71442015-01-15 16:57:00 -080030 def __init__( self ):
31 """
32 Initialize client
33 """
34 super( CLI, self ).__init__()
35
36 def connect( self, **connectargs ):
37 """
andrewonlab95ce8322014-10-13 14:12:04 -040038 Creates ssh handle for ONOS cli.
kelvin8ec71442015-01-15 16:57:00 -080039 """
andrewonlab95ce8322014-10-13 14:12:04 -040040 try:
41 for key in connectargs:
kelvin8ec71442015-01-15 16:57:00 -080042 vars( self )[ key ] = connectargs[ key ]
andrewonlab95ce8322014-10-13 14:12:04 -040043 self.home = "~/ONOS"
44 for key in self.options:
45 if key == "home":
kelvin8ec71442015-01-15 16:57:00 -080046 self.home = self.options[ 'home' ]
andrewonlab95ce8322014-10-13 14:12:04 -040047 break
kelvin-onlabfb521662015-02-27 09:52:40 -080048 if self.home is None or self.home == "":
kelvin-onlabd6634ac2015-01-29 14:23:10 -080049 self.home = "~/ONOS"
kelvin-onlabfb521662015-02-27 09:52:40 -080050
kelvin8ec71442015-01-15 16:57:00 -080051 self.name = self.options[ 'name' ]
52 self.handle = super( OnosCliDriver, self ).connect(
kelvin-onlab08679eb2015-01-21 16:11:48 -080053 user_name=self.user_name,
54 ip_address=self.ip_address,
kelvin-onlab898a6c62015-01-16 14:13:53 -080055 port=self.port,
56 pwd=self.pwd,
57 home=self.home )
andrewonlab95ce8322014-10-13 14:12:04 -040058
kelvin8ec71442015-01-15 16:57:00 -080059 self.handle.sendline( "cd " + self.home )
60 self.handle.expect( "\$" )
andrewonlab95ce8322014-10-13 14:12:04 -040061 if self.handle:
62 return self.handle
kelvin8ec71442015-01-15 16:57:00 -080063 else:
64 main.log.info( "NO ONOS HANDLE" )
andrewonlab95ce8322014-10-13 14:12:04 -040065 return main.FALSE
Jon Halld4d4b372015-01-28 16:02:41 -080066 except TypeError:
67 main.log.exception( self.name + ": Object not as expected" )
68 return None
andrewonlab95ce8322014-10-13 14:12:04 -040069 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -080070 main.log.error( self.name + ": EOF exception found" )
71 main.log.error( self.name + ": " + self.handle.before )
andrewonlab95ce8322014-10-13 14:12:04 -040072 main.cleanup()
73 main.exit()
74 except:
Jon Halld4d4b372015-01-28 16:02:41 -080075 main.log.exception( self.name + ": Uncaught exception!" )
andrewonlab95ce8322014-10-13 14:12:04 -040076 main.cleanup()
77 main.exit()
78
kelvin8ec71442015-01-15 16:57:00 -080079 def disconnect( self ):
80 """
andrewonlab95ce8322014-10-13 14:12:04 -040081 Called when Test is complete to disconnect the ONOS handle.
kelvin8ec71442015-01-15 16:57:00 -080082 """
Jon Halld61331b2015-02-17 16:35:47 -080083 response = main.TRUE
andrewonlab95ce8322014-10-13 14:12:04 -040084 try:
kelvin8ec71442015-01-15 16:57:00 -080085 self.handle.sendline( "" )
86 i = self.handle.expect( [ "onos>", "\$" ] )
Jon Hall7e5b9172014-10-22 12:32:47 -040087 if i == 0:
kelvin8ec71442015-01-15 16:57:00 -080088 self.handle.sendline( "system:shutdown" )
89 self.handle.expect( "Confirm" )
90 self.handle.sendline( "yes" )
91 self.handle.expect( "\$" )
92 self.handle.sendline( "" )
93 self.handle.expect( "\$" )
94 self.handle.sendline( "exit" )
95 self.handle.expect( "closed" )
andrewonlabc2d05aa2014-10-13 16:51:10 -040096
Jon Halld4d4b372015-01-28 16:02:41 -080097 except TypeError:
98 main.log.exception( self.name + ": Object not as expected" )
Jon Halld61331b2015-02-17 16:35:47 -080099 response = main.FALSE
andrewonlab95ce8322014-10-13 14:12:04 -0400100 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -0800101 main.log.error( self.name + ": EOF exception found" )
102 main.log.error( self.name + ": " + self.handle.before )
andrewonlab95ce8322014-10-13 14:12:04 -0400103 except:
Jon Halld4d4b372015-01-28 16:02:41 -0800104 main.log.exception( self.name + ": Connection failed to the host" )
andrewonlab95ce8322014-10-13 14:12:04 -0400105 response = main.FALSE
106 return response
107
kelvin8ec71442015-01-15 16:57:00 -0800108 def logout( self ):
109 """
andrewonlab38d2b4a2014-11-13 16:28:47 -0500110 Sends 'logout' command to ONOS cli
kelvin8ec71442015-01-15 16:57:00 -0800111 """
andrewonlab38d2b4a2014-11-13 16:28:47 -0500112 try:
kelvin8ec71442015-01-15 16:57:00 -0800113 self.handle.sendline( "" )
114 i = self.handle.expect( [
andrewonlab9627f432014-11-14 12:45:10 -0500115 "onos>",
kelvin8ec71442015-01-15 16:57:00 -0800116 "\$" ], timeout=10 )
andrewonlab9627f432014-11-14 12:45:10 -0500117 if i == 0:
kelvin8ec71442015-01-15 16:57:00 -0800118 self.handle.sendline( "logout" )
119 self.handle.expect( "\$" )
andrewonlab9627f432014-11-14 12:45:10 -0500120 elif i == 1:
121 return main.TRUE
kelvin8ec71442015-01-15 16:57:00 -0800122
Jon Halld4d4b372015-01-28 16:02:41 -0800123 except TypeError:
124 main.log.exception( self.name + ": Object not as expected" )
125 return None
andrewonlab38d2b4a2014-11-13 16:28:47 -0500126 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -0800127 main.log.error( self.name + ": eof exception found" )
128 main.log.error( self.name + ": " +
129 self.handle.before )
andrewonlab38d2b4a2014-11-13 16:28:47 -0500130 main.cleanup()
131 main.exit()
132 except:
Jon Halld4d4b372015-01-28 16:02:41 -0800133 main.log.exception( self.name + ": Uncaught exception!" )
andrewonlab38d2b4a2014-11-13 16:28:47 -0500134 main.cleanup()
135 main.exit()
136
kelvin-onlabd3b64892015-01-20 13:26:24 -0800137 def setCell( self, cellname ):
kelvin8ec71442015-01-15 16:57:00 -0800138 """
andrewonlab95ce8322014-10-13 14:12:04 -0400139 Calls 'cell <name>' to set the environment variables on ONOSbench
kelvin8ec71442015-01-15 16:57:00 -0800140
andrewonlab95ce8322014-10-13 14:12:04 -0400141 Before issuing any cli commands, set the environment variable first.
kelvin8ec71442015-01-15 16:57:00 -0800142 """
andrewonlab95ce8322014-10-13 14:12:04 -0400143 try:
144 if not cellname:
kelvin8ec71442015-01-15 16:57:00 -0800145 main.log.error( "Must define cellname" )
andrewonlab95ce8322014-10-13 14:12:04 -0400146 main.cleanup()
147 main.exit()
148 else:
kelvin8ec71442015-01-15 16:57:00 -0800149 self.handle.sendline( "cell " + str( cellname ) )
kelvin-onlabd3b64892015-01-20 13:26:24 -0800150 # Expect the cellname in the ONOSCELL variable.
kelvin8ec71442015-01-15 16:57:00 -0800151 # Note that this variable name is subject to change
andrewonlab95ce8322014-10-13 14:12:04 -0400152 # and that this driver will have to change accordingly
Jon Hall1e03cb62015-02-19 12:07:12 -0800153 self.handle.expect( "ONOS_CELL" )
kelvin-onlabd3b64892015-01-20 13:26:24 -0800154 handleBefore = self.handle.before
155 handleAfter = self.handle.after
kelvin8ec71442015-01-15 16:57:00 -0800156 # Get the rest of the handle
157 self.handle.sendline( "" )
158 self.handle.expect( "\$" )
kelvin-onlabd3b64892015-01-20 13:26:24 -0800159 handleMore = self.handle.before
andrewonlab95ce8322014-10-13 14:12:04 -0400160
kelvin-onlabd3b64892015-01-20 13:26:24 -0800161 main.log.info( "Cell call returned: " + handleBefore +
162 handleAfter + handleMore )
andrewonlab95ce8322014-10-13 14:12:04 -0400163
164 return main.TRUE
165
Jon Halld4d4b372015-01-28 16:02:41 -0800166 except TypeError:
167 main.log.exception( self.name + ": Object not as expected" )
168 return None
andrewonlab95ce8322014-10-13 14:12:04 -0400169 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -0800170 main.log.error( self.name + ": eof exception found" )
171 main.log.error( self.name + ": " + self.handle.before )
andrewonlab95ce8322014-10-13 14:12:04 -0400172 main.cleanup()
173 main.exit()
174 except:
Jon Halld4d4b372015-01-28 16:02:41 -0800175 main.log.exception( self.name + ": Uncaught exception!" )
andrewonlab95ce8322014-10-13 14:12:04 -0400176 main.cleanup()
177 main.exit()
kelvin8ec71442015-01-15 16:57:00 -0800178
kelvin-onlabd3b64892015-01-20 13:26:24 -0800179 def startOnosCli( self, ONOSIp, karafTimeout="" ):
kelvin8ec71442015-01-15 16:57:00 -0800180 """
kelvin-onlabd3b64892015-01-20 13:26:24 -0800181 karafTimeout is an optional arugument. karafTimeout value passed
182 by user would be used to set the current karaf shell idle timeout.
183 Note that when ever this property is modified the shell will exit and
Hari Krishnad7b9c202015-01-05 10:38:14 -0800184 the subsequent login would reflect new idle timeout.
kelvin-onlabd3b64892015-01-20 13:26:24 -0800185 Below is an example to start a session with 60 seconds idle timeout
186 ( input value is in milliseconds ):
kelvin8ec71442015-01-15 16:57:00 -0800187
Hari Krishna25d42f72015-01-05 15:08:28 -0800188 tValue = "60000"
kelvin-onlabd3b64892015-01-20 13:26:24 -0800189 main.ONOScli1.startOnosCli( ONOSIp, karafTimeout=tValue )
kelvin8ec71442015-01-15 16:57:00 -0800190
kelvin-onlabd3b64892015-01-20 13:26:24 -0800191 Note: karafTimeout is left as str so that this could be read
192 and passed to startOnosCli from PARAMS file as str.
kelvin8ec71442015-01-15 16:57:00 -0800193 """
andrewonlab95ce8322014-10-13 14:12:04 -0400194 try:
kelvin8ec71442015-01-15 16:57:00 -0800195 self.handle.sendline( "" )
196 x = self.handle.expect( [
197 "\$", "onos>" ], timeout=10 )
andrewonlab48829f62014-11-17 13:49:01 -0500198
199 if x == 1:
kelvin8ec71442015-01-15 16:57:00 -0800200 main.log.info( "ONOS cli is already running" )
andrewonlab48829f62014-11-17 13:49:01 -0500201 return main.TRUE
andrewonlab95ce8322014-10-13 14:12:04 -0400202
kelvin8ec71442015-01-15 16:57:00 -0800203 # Wait for onos start ( -w ) and enter onos cli
kelvin-onlabd3b64892015-01-20 13:26:24 -0800204 self.handle.sendline( "onos -w " + str( ONOSIp ) )
kelvin8ec71442015-01-15 16:57:00 -0800205 i = self.handle.expect( [
206 "onos>",
kelvin-onlab898a6c62015-01-16 14:13:53 -0800207 pexpect.TIMEOUT ], timeout=60 )
andrewonlab2a7ea9b2014-10-24 12:21:05 -0400208
209 if i == 0:
kelvin-onlabd3b64892015-01-20 13:26:24 -0800210 main.log.info( str( ONOSIp ) + " CLI Started successfully" )
Hari Krishnae36ef212015-01-04 14:09:13 -0800211 if karafTimeout:
kelvin8ec71442015-01-15 16:57:00 -0800212 self.handle.sendline(
Hari Krishnaac4e1782015-01-26 12:09:12 -0800213 "config:property-set -p org.apache.karaf.shell\
214 sshIdleTimeout " +
kelvin8ec71442015-01-15 16:57:00 -0800215 karafTimeout )
216 self.handle.expect( "\$" )
kelvin-onlabd3b64892015-01-20 13:26:24 -0800217 self.handle.sendline( "onos -w " + str( ONOSIp ) )
kelvin8ec71442015-01-15 16:57:00 -0800218 self.handle.expect( "onos>" )
andrewonlab2a7ea9b2014-10-24 12:21:05 -0400219 return main.TRUE
220 else:
kelvin8ec71442015-01-15 16:57:00 -0800221 # If failed, send ctrl+c to process and try again
222 main.log.info( "Starting CLI failed. Retrying..." )
223 self.handle.send( "\x03" )
kelvin-onlabd3b64892015-01-20 13:26:24 -0800224 self.handle.sendline( "onos -w " + str( ONOSIp ) )
kelvin8ec71442015-01-15 16:57:00 -0800225 i = self.handle.expect( [ "onos>", pexpect.TIMEOUT ],
226 timeout=30 )
andrewonlab3a7c3c72014-10-24 17:21:03 -0400227 if i == 0:
kelvin-onlabd3b64892015-01-20 13:26:24 -0800228 main.log.info( str( ONOSIp ) + " CLI Started " +
kelvin8ec71442015-01-15 16:57:00 -0800229 "successfully after retry attempt" )
Hari Krishnae36ef212015-01-04 14:09:13 -0800230 if karafTimeout:
kelvin8ec71442015-01-15 16:57:00 -0800231 self.handle.sendline(
kelvin-onlabd3b64892015-01-20 13:26:24 -0800232 "config:property-set -p org.apache.karaf.shell\
233 sshIdleTimeout " +
kelvin8ec71442015-01-15 16:57:00 -0800234 karafTimeout )
235 self.handle.expect( "\$" )
kelvin-onlabd3b64892015-01-20 13:26:24 -0800236 self.handle.sendline( "onos -w " + str( ONOSIp ) )
kelvin8ec71442015-01-15 16:57:00 -0800237 self.handle.expect( "onos>" )
andrewonlab3a7c3c72014-10-24 17:21:03 -0400238 return main.TRUE
239 else:
kelvin8ec71442015-01-15 16:57:00 -0800240 main.log.error( "Connection to CLI " +
kelvin-onlabd3b64892015-01-20 13:26:24 -0800241 str( ONOSIp ) + " timeout" )
andrewonlab3a7c3c72014-10-24 17:21:03 -0400242 return main.FALSE
andrewonlab95ce8322014-10-13 14:12:04 -0400243
Jon Halld4d4b372015-01-28 16:02:41 -0800244 except TypeError:
245 main.log.exception( self.name + ": Object not as expected" )
246 return None
andrewonlab95ce8322014-10-13 14:12:04 -0400247 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -0800248 main.log.error( self.name + ": EOF exception found" )
249 main.log.error( self.name + ": " + self.handle.before )
andrewonlab95ce8322014-10-13 14:12:04 -0400250 main.cleanup()
251 main.exit()
252 except:
Jon Halld4d4b372015-01-28 16:02:41 -0800253 main.log.exception( self.name + ": Uncaught exception!" )
andrewonlab95ce8322014-10-13 14:12:04 -0400254 main.cleanup()
255 main.exit()
256
kelvin-onlab338f5512015-02-06 10:53:16 -0800257 def log( self, cmdStr , level = "" ):
kelvin-onlab9f541032015-02-04 16:19:53 -0800258 """
259 log the commands in the onos CLI.
kelvin-onlab338f5512015-02-06 10:53:16 -0800260 returns main.TRUE on success
261 returns main.FALSE if Error occured
262 Available level: DEBUG, TRACE, INFO, WARN, ERROR
263 Level defaults to INFO
kelvin-onlab9f541032015-02-04 16:19:53 -0800264 """
265 try:
kelvin-onlab338f5512015-02-06 10:53:16 -0800266 lvlStr = ""
267 if level:
268 lvlStr = "--level=" + level
269
kelvin-onlab9f541032015-02-04 16:19:53 -0800270 self.handle.sendline( "" )
271 self.handle.expect( "onos>" )
kelvin-onlab338f5512015-02-06 10:53:16 -0800272 self.handle.sendline( "log:log " + lvlStr + " " + cmdStr )
kelvin-onlab9f541032015-02-04 16:19:53 -0800273 self.handle.expect( "onos>" )
kelvin-onlabfb521662015-02-27 09:52:40 -0800274
kelvin-onlab9f541032015-02-04 16:19:53 -0800275 response = self.handle.before
276 if re.search( "Error", response ):
277 return main.FALSE
278 return main.TRUE
279
280 except pexpect.EOF:
281 main.log.error( self.name + ": EOF exception found" )
282 main.log.error( self.name + ": " + self.handle.before )
283 main.cleanup()
284 main.exit()
285 except:
kelvin-onlabfb521662015-02-27 09:52:40 -0800286 main.log.exception( self.name + ": Uncaught exception!" )
kelvin-onlab9f541032015-02-04 16:19:53 -0800287 main.cleanup()
288 main.exit()
289
kelvin-onlabd3b64892015-01-20 13:26:24 -0800290 def sendline( self, cmdStr ):
kelvin8ec71442015-01-15 16:57:00 -0800291 """
Jon Halle3f39ff2015-01-13 11:50:53 -0800292 Send a completely user specified string to
293 the onos> prompt. Use this function if you have
andrewonlaba18f6bf2014-10-13 19:31:54 -0400294 a very specific command to send.
Jon Halle3f39ff2015-01-13 11:50:53 -0800295
andrewonlaba18f6bf2014-10-13 19:31:54 -0400296 Warning: There are no sanity checking to commands
297 sent using this method.
kelvin8ec71442015-01-15 16:57:00 -0800298 """
andrewonlaba18f6bf2014-10-13 19:31:54 -0400299 try:
kelvin-onlab338f5512015-02-06 10:53:16 -0800300 logStr = "\"Sending CLI command: '" + cmdStr + "'\""
301 self.log( logStr )
kelvin-onlabd3b64892015-01-20 13:26:24 -0800302 self.handle.sendline( cmdStr )
kelvin8ec71442015-01-15 16:57:00 -0800303 self.handle.expect( "onos>" )
Jon Hallaea67aa2015-01-23 13:30:57 -0800304 main.log.info( "Command '" + str( cmdStr ) + "' sent to "
305 + self.name + "." )
andrewonlaba18f6bf2014-10-13 19:31:54 -0400306 handle = self.handle.before
Jon Hall7bdfc122015-01-23 11:45:32 -0800307 # Remove control strings from output
308 ansiEscape = re.compile( r'\x1b[^m]*m' )
309 handle = ansiEscape.sub( '', handle )
kelvin-onlabfb521662015-02-27 09:52:40 -0800310 # Remove extra return chars that get added
Jon Hallaea67aa2015-01-23 13:30:57 -0800311 handle = re.sub( r"\s\r", "", handle )
312 handle = handle.strip()
Jon Hall7bdfc122015-01-23 11:45:32 -0800313 # parse for just the output, remove the cmd from handle
314 output = handle.split( cmdStr, 1 )[1]
Jon Hall7bdfc122015-01-23 11:45:32 -0800315 return output
Jon Halld4d4b372015-01-28 16:02:41 -0800316 except TypeError:
317 main.log.exception( self.name + ": Object not as expected" )
318 return None
andrewonlaba18f6bf2014-10-13 19:31:54 -0400319 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -0800320 main.log.error( self.name + ": EOF exception found" )
321 main.log.error( self.name + ": " + self.handle.before )
andrewonlaba18f6bf2014-10-13 19:31:54 -0400322 main.cleanup()
323 main.exit()
324 except:
Jon Halld4d4b372015-01-28 16:02:41 -0800325 main.log.exception( self.name + ": Uncaught exception!" )
andrewonlaba18f6bf2014-10-13 19:31:54 -0400326 main.cleanup()
327 main.exit()
328
kelvin8ec71442015-01-15 16:57:00 -0800329 # IMPORTANT NOTE:
330 # For all cli commands, naming convention should match
kelvin-onlabd3b64892015-01-20 13:26:24 -0800331 # the cli command changing 'a:b' with 'aB'.
332 # Ex ) onos:topology > onosTopology
333 # onos:links > onosLinks
334 # feature:list > featureList
Jon Halle3f39ff2015-01-13 11:50:53 -0800335
kelvin-onlabd3b64892015-01-20 13:26:24 -0800336 def addNode( self, nodeId, ONOSIp, tcpPort="" ):
kelvin8ec71442015-01-15 16:57:00 -0800337 """
andrewonlabc2d05aa2014-10-13 16:51:10 -0400338 Adds a new cluster node by ID and address information.
339 Required:
kelvin-onlabd3b64892015-01-20 13:26:24 -0800340 * nodeId
341 * ONOSIp
andrewonlabc2d05aa2014-10-13 16:51:10 -0400342 Optional:
kelvin-onlabd3b64892015-01-20 13:26:24 -0800343 * tcpPort
kelvin8ec71442015-01-15 16:57:00 -0800344 """
andrewonlabc2d05aa2014-10-13 16:51:10 -0400345 try:
kelvin-onlabd3b64892015-01-20 13:26:24 -0800346 cmdStr = "add-node " + str( nodeId ) + " " +\
347 str( ONOSIp ) + " " + str( tcpPort )
348 handle = self.sendline( cmdStr )
kelvin-onlab898a6c62015-01-16 14:13:53 -0800349 if re.search( "Error", handle ):
kelvin8ec71442015-01-15 16:57:00 -0800350 main.log.error( "Error in adding node" )
351 main.log.error( handle )
Jon Halle3f39ff2015-01-13 11:50:53 -0800352 return main.FALSE
andrewonlabc2d05aa2014-10-13 16:51:10 -0400353 else:
kelvin-onlabd3b64892015-01-20 13:26:24 -0800354 main.log.info( "Node " + str( ONOSIp ) + " added" )
andrewonlabc2d05aa2014-10-13 16:51:10 -0400355 return main.TRUE
Jon Halld4d4b372015-01-28 16:02:41 -0800356 except TypeError:
357 main.log.exception( self.name + ": Object not as expected" )
358 return None
andrewonlabc2d05aa2014-10-13 16:51:10 -0400359 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -0800360 main.log.error( self.name + ": EOF exception found" )
361 main.log.error( self.name + ": " + self.handle.before )
andrewonlabc2d05aa2014-10-13 16:51:10 -0400362 main.cleanup()
363 main.exit()
364 except:
Jon Halld4d4b372015-01-28 16:02:41 -0800365 main.log.exception( self.name + ": Uncaught exception!" )
andrewonlabc2d05aa2014-10-13 16:51:10 -0400366 main.cleanup()
367 main.exit()
368
kelvin-onlabd3b64892015-01-20 13:26:24 -0800369 def removeNode( self, nodeId ):
kelvin8ec71442015-01-15 16:57:00 -0800370 """
andrewonlab86dc3082014-10-13 18:18:38 -0400371 Removes a cluster by ID
372 Issues command: 'remove-node [<node-id>]'
373 Required:
kelvin-onlabd3b64892015-01-20 13:26:24 -0800374 * nodeId
kelvin8ec71442015-01-15 16:57:00 -0800375 """
andrewonlab86dc3082014-10-13 18:18:38 -0400376 try:
andrewonlab86dc3082014-10-13 18:18:38 -0400377
kelvin-onlabd3b64892015-01-20 13:26:24 -0800378 cmdStr = "remove-node " + str( nodeId )
379 self.sendline( cmdStr )
Jon Halle3f39ff2015-01-13 11:50:53 -0800380 # TODO: add error checking. Does ONOS give any errors?
andrewonlab86dc3082014-10-13 18:18:38 -0400381
382 return main.TRUE
Jon Halle3f39ff2015-01-13 11:50:53 -0800383
Jon Halld4d4b372015-01-28 16:02:41 -0800384 except TypeError:
385 main.log.exception( self.name + ": Object not as expected" )
386 return None
andrewonlab86dc3082014-10-13 18:18:38 -0400387 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -0800388 main.log.error( self.name + ": EOF exception found" )
389 main.log.error( self.name + ": " + self.handle.before )
andrewonlab86dc3082014-10-13 18:18:38 -0400390 main.cleanup()
391 main.exit()
392 except:
Jon Halld4d4b372015-01-28 16:02:41 -0800393 main.log.exception( self.name + ": Uncaught exception!" )
andrewonlab86dc3082014-10-13 18:18:38 -0400394 main.cleanup()
395 main.exit()
andrewonlabc2d05aa2014-10-13 16:51:10 -0400396
kelvin8ec71442015-01-15 16:57:00 -0800397 def nodes( self ):
398 """
andrewonlab7c211572014-10-15 16:45:20 -0400399 List the nodes currently visible
400 Issues command: 'nodes'
401 Returns: entire handle of list of nodes
kelvin8ec71442015-01-15 16:57:00 -0800402 """
andrewonlab7c211572014-10-15 16:45:20 -0400403 try:
kelvin-onlabd3b64892015-01-20 13:26:24 -0800404 cmdStr = "nodes"
405 handle = self.sendline( cmdStr )
andrewonlab7c211572014-10-15 16:45:20 -0400406 return handle
Jon Halld4d4b372015-01-28 16:02:41 -0800407 except TypeError:
408 main.log.exception( self.name + ": Object not as expected" )
409 return None
andrewonlab7c211572014-10-15 16:45:20 -0400410 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -0800411 main.log.error( self.name + ": EOF exception found" )
412 main.log.error( self.name + ": " + self.handle.before )
andrewonlab7c211572014-10-15 16:45:20 -0400413 main.cleanup()
414 main.exit()
415 except:
Jon Halld4d4b372015-01-28 16:02:41 -0800416 main.log.exception( self.name + ": Uncaught exception!" )
andrewonlab7c211572014-10-15 16:45:20 -0400417 main.cleanup()
418 main.exit()
419
kelvin8ec71442015-01-15 16:57:00 -0800420 def topology( self ):
421 """
andrewonlabc2d05aa2014-10-13 16:51:10 -0400422 Shows the current state of the topology
423 by issusing command: 'onos> onos:topology'
kelvin8ec71442015-01-15 16:57:00 -0800424 """
andrewonlab95ce8322014-10-13 14:12:04 -0400425 try:
Jon Halle3f39ff2015-01-13 11:50:53 -0800426 # either onos:topology or 'topology' will work in CLI
kelvin-onlabd3b64892015-01-20 13:26:24 -0800427 cmdStr = "onos:topology"
428 handle = self.sendline( cmdStr )
Jon Halle3f39ff2015-01-13 11:50:53 -0800429 main.log.info( "onos:topology returned: " + str( handle ) )
andrewonlab95ce8322014-10-13 14:12:04 -0400430 return handle
Jon Halld4d4b372015-01-28 16:02:41 -0800431 except TypeError:
432 main.log.exception( self.name + ": Object not as expected" )
433 return None
andrewonlab95ce8322014-10-13 14:12:04 -0400434 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -0800435 main.log.error( self.name + ": EOF exception found" )
436 main.log.error( self.name + ": " + self.handle.before )
andrewonlab95ce8322014-10-13 14:12:04 -0400437 main.cleanup()
438 main.exit()
439 except:
Jon Halld4d4b372015-01-28 16:02:41 -0800440 main.log.exception( self.name + ": Uncaught exception!" )
andrewonlab95ce8322014-10-13 14:12:04 -0400441 main.cleanup()
442 main.exit()
Jon Halle3f39ff2015-01-13 11:50:53 -0800443
kelvin-onlabd3b64892015-01-20 13:26:24 -0800444 def featureInstall( self, featureStr ):
kelvin8ec71442015-01-15 16:57:00 -0800445 """
Jon Halle3f39ff2015-01-13 11:50:53 -0800446 Installs a specified feature
andrewonlabc2d05aa2014-10-13 16:51:10 -0400447 by issuing command: 'onos> feature:install <feature_str>'
kelvin8ec71442015-01-15 16:57:00 -0800448 """
andrewonlabc2d05aa2014-10-13 16:51:10 -0400449 try:
kelvin-onlabd3b64892015-01-20 13:26:24 -0800450 cmdStr = "feature:install " + str( featureStr )
451 self.sendline( cmdStr )
Jon Halle3f39ff2015-01-13 11:50:53 -0800452 # TODO: Check for possible error responses from karaf
andrewonlabc2d05aa2014-10-13 16:51:10 -0400453 return main.TRUE
Jon Halld4d4b372015-01-28 16:02:41 -0800454 except TypeError:
455 main.log.exception( self.name + ": Object not as expected" )
456 return None
andrewonlabc2d05aa2014-10-13 16:51:10 -0400457 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -0800458 main.log.error( self.name + ": EOF exception found" )
459 main.log.error( self.name + ": " + self.handle.before )
460 main.log.report( "Failed to install feature" )
461 main.log.report( "Exiting test" )
andrewonlabc2d05aa2014-10-13 16:51:10 -0400462 main.cleanup()
463 main.exit()
464 except:
Jon Halld4d4b372015-01-28 16:02:41 -0800465 main.log.exception( self.name + ": Uncaught exception!" )
kelvin8ec71442015-01-15 16:57:00 -0800466 main.log.report( "Failed to install feature" )
467 main.log.report( "Exiting test" )
andrewonlabc2d05aa2014-10-13 16:51:10 -0400468 main.cleanup()
469 main.exit()
Jon Halle3f39ff2015-01-13 11:50:53 -0800470
kelvin-onlabd3b64892015-01-20 13:26:24 -0800471 def featureUninstall( self, featureStr ):
kelvin8ec71442015-01-15 16:57:00 -0800472 """
andrewonlabc2d05aa2014-10-13 16:51:10 -0400473 Uninstalls a specified feature
474 by issuing command: 'onos> feature:uninstall <feature_str>'
kelvin8ec71442015-01-15 16:57:00 -0800475 """
andrewonlabc2d05aa2014-10-13 16:51:10 -0400476 try:
Jon Hall30b82fa2015-03-04 17:15:43 -0800477 cmdStr = 'feature:list -i | grep "' + featureStr + '"'
478 handle = self.sendline( cmdStr )
479 if handle != '':
480 cmdStr = "feature:uninstall " + str( featureStr )
481 self.sendline( cmdStr )
482 # TODO: Check for possible error responses from karaf
483 else:
484 main.log.info( "Feature needs to be installed before uninstalling it" )
shahshreya280223a2015-02-26 12:25:25 -0800485 return main.TRUE
Jon Halld4d4b372015-01-28 16:02:41 -0800486 except TypeError:
487 main.log.exception( self.name + ": Object not as expected" )
488 return None
andrewonlabc2d05aa2014-10-13 16:51:10 -0400489 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -0800490 main.log.error( self.name + ": EOF exception found" )
491 main.log.error( self.name + ": " + self.handle.before )
andrewonlabc2d05aa2014-10-13 16:51:10 -0400492 main.cleanup()
493 main.exit()
494 except:
Jon Halld4d4b372015-01-28 16:02:41 -0800495 main.log.exception( self.name + ": Uncaught exception!" )
andrewonlabc2d05aa2014-10-13 16:51:10 -0400496 main.cleanup()
497 main.exit()
Jon Hallffb386d2014-11-21 13:43:38 -0800498
kelvin-onlabd3b64892015-01-20 13:26:24 -0800499 def devices( self, jsonFormat=True ):
kelvin8ec71442015-01-15 16:57:00 -0800500 """
Jon Hall7b02d952014-10-17 20:14:54 -0400501 Lists all infrastructure devices or switches
andrewonlab86dc3082014-10-13 18:18:38 -0400502 Optional argument:
kelvin-onlabd3b64892015-01-20 13:26:24 -0800503 * jsonFormat - boolean indicating if you want output in json
kelvin8ec71442015-01-15 16:57:00 -0800504 """
andrewonlab86dc3082014-10-13 18:18:38 -0400505 try:
kelvin-onlabd3b64892015-01-20 13:26:24 -0800506 if jsonFormat:
507 cmdStr = "devices -j"
508 handle = self.sendline( cmdStr )
kelvin-onlab898a6c62015-01-16 14:13:53 -0800509 """
Jon Halle3f39ff2015-01-13 11:50:53 -0800510 handle variable here contains some ANSI escape color code
511 sequences at the end which are invisible in the print command
512 output. To make that escape sequence visible, use repr()
kelvin-onlab898a6c62015-01-16 14:13:53 -0800513 function. The repr( handle ) output when printed shows the
514 ANSI escape sequences. In json.loads( somestring ), this
515 somestring variable is actually repr( somestring ) and
Jon Halle3f39ff2015-01-13 11:50:53 -0800516 json.loads would fail with the escape sequence. So we take off
517 that escape sequence using:
518
kelvin-onlabd3b64892015-01-20 13:26:24 -0800519 ansiEscape = re.compile( r'\r\r\n\x1b[^m]*m' )
520 handle1 = ansiEscape.sub( '', handle )
kelvin-onlab898a6c62015-01-16 14:13:53 -0800521 """
kelvin-onlabd3b64892015-01-20 13:26:24 -0800522 ansiEscape = re.compile( r'\r\r\n\x1b[^m]*m' )
523 handle1 = ansiEscape.sub( '', handle )
Jon Halla001c392014-10-17 18:50:59 -0400524 return handle1
Jon Halle8217482014-10-17 13:49:14 -0400525 else:
kelvin-onlabd3b64892015-01-20 13:26:24 -0800526 cmdStr = "devices"
527 handle = self.sendline( cmdStr )
Jon Hallcd707292014-10-17 19:06:17 -0400528 return handle
Jon Halld4d4b372015-01-28 16:02:41 -0800529 except TypeError:
530 main.log.exception( self.name + ": Object not as expected" )
531 return None
andrewonlab7c211572014-10-15 16:45:20 -0400532 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -0800533 main.log.error( self.name + ": EOF exception found" )
534 main.log.error( self.name + ": " + self.handle.before )
andrewonlab7c211572014-10-15 16:45:20 -0400535 main.cleanup()
536 main.exit()
537 except:
Jon Halld4d4b372015-01-28 16:02:41 -0800538 main.log.exception( self.name + ": Uncaught exception!" )
andrewonlab7c211572014-10-15 16:45:20 -0400539 main.cleanup()
540 main.exit()
541
kelvin-onlabd3b64892015-01-20 13:26:24 -0800542 def balanceMasters( self ):
kelvin8ec71442015-01-15 16:57:00 -0800543 """
Hari Krishnaa43d4e92014-12-19 13:22:40 -0800544 This balances the devices across all controllers
545 by issuing command: 'onos> onos:balance-masters'
546 If required this could be extended to return devices balanced output.
kelvin8ec71442015-01-15 16:57:00 -0800547 """
Hari Krishnaa43d4e92014-12-19 13:22:40 -0800548 try:
kelvin-onlabd3b64892015-01-20 13:26:24 -0800549 cmdStr = "onos:balance-masters"
550 self.sendline( cmdStr )
Jon Halle3f39ff2015-01-13 11:50:53 -0800551 # TODO: Check for error responses from ONOS
Hari Krishnaa43d4e92014-12-19 13:22:40 -0800552 return main.TRUE
Jon Halld4d4b372015-01-28 16:02:41 -0800553 except TypeError:
554 main.log.exception( self.name + ": Object not as expected" )
555 return None
Hari Krishnaa43d4e92014-12-19 13:22:40 -0800556 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -0800557 main.log.error( self.name + ": EOF exception found" )
558 main.log.error( self.name + ": " + self.handle.before )
Hari Krishnaa43d4e92014-12-19 13:22:40 -0800559 main.cleanup()
560 main.exit()
561 except:
Jon Halld4d4b372015-01-28 16:02:41 -0800562 main.log.exception( self.name + ": Uncaught exception!" )
Hari Krishnaa43d4e92014-12-19 13:22:40 -0800563 main.cleanup()
564 main.exit()
565
kelvin-onlabd3b64892015-01-20 13:26:24 -0800566 def links( self, jsonFormat=True ):
kelvin8ec71442015-01-15 16:57:00 -0800567 """
Jon Halle8217482014-10-17 13:49:14 -0400568 Lists all core links
569 Optional argument:
kelvin-onlabd3b64892015-01-20 13:26:24 -0800570 * jsonFormat - boolean indicating if you want output in json
kelvin8ec71442015-01-15 16:57:00 -0800571 """
Jon Halle8217482014-10-17 13:49:14 -0400572 try:
kelvin-onlabd3b64892015-01-20 13:26:24 -0800573 if jsonFormat:
574 cmdStr = "links -j"
575 handle = self.sendline( cmdStr )
kelvin-onlab898a6c62015-01-16 14:13:53 -0800576 """
Jon Halle3f39ff2015-01-13 11:50:53 -0800577 handle variable here contains some ANSI escape color code
578 sequences at the end which are invisible in the print command
579 output. To make that escape sequence visible, use repr()
kelvin-onlab898a6c62015-01-16 14:13:53 -0800580 function. The repr( handle ) output when printed shows the ANSI
581 escape sequences. In json.loads( somestring ), this somestring
582 variable is actually repr( somestring ) and json.loads would
Jon Halle3f39ff2015-01-13 11:50:53 -0800583 fail with the escape sequence. So we take off that escape
584 sequence using:
585
kelvin-onlabd3b64892015-01-20 13:26:24 -0800586 ansiEscape = re.compile( r'\r\r\n\x1b[^m]*m' )
587 handle1 = ansiEscape.sub( '', handle )
kelvin-onlab898a6c62015-01-16 14:13:53 -0800588 """
kelvin-onlabd3b64892015-01-20 13:26:24 -0800589 ansiEscape = re.compile( r'\r\r\n\x1b[^m]*m' )
590 handle1 = ansiEscape.sub( '', handle )
Jon Halla001c392014-10-17 18:50:59 -0400591 return handle1
Jon Halle8217482014-10-17 13:49:14 -0400592 else:
kelvin-onlabd3b64892015-01-20 13:26:24 -0800593 cmdStr = "links"
594 handle = self.sendline( cmdStr )
Jon Halla001c392014-10-17 18:50:59 -0400595 return handle
Jon Halld4d4b372015-01-28 16:02:41 -0800596 except TypeError:
597 main.log.exception( self.name + ": Object not as expected" )
598 return None
Jon Halle8217482014-10-17 13:49:14 -0400599 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -0800600 main.log.error( self.name + ": EOF exception found" )
601 main.log.error( self.name + ": " + self.handle.before )
Jon Halle8217482014-10-17 13:49:14 -0400602 main.cleanup()
603 main.exit()
604 except:
Jon Halld4d4b372015-01-28 16:02:41 -0800605 main.log.exception( self.name + ": Uncaught exception!" )
Jon Halle8217482014-10-17 13:49:14 -0400606 main.cleanup()
607 main.exit()
608
kelvin-onlabd3b64892015-01-20 13:26:24 -0800609 def ports( self, jsonFormat=True ):
kelvin8ec71442015-01-15 16:57:00 -0800610 """
Jon Halle8217482014-10-17 13:49:14 -0400611 Lists all ports
612 Optional argument:
kelvin-onlabd3b64892015-01-20 13:26:24 -0800613 * jsonFormat - boolean indicating if you want output in json
kelvin8ec71442015-01-15 16:57:00 -0800614 """
Jon Halle8217482014-10-17 13:49:14 -0400615 try:
kelvin-onlabd3b64892015-01-20 13:26:24 -0800616 if jsonFormat:
617 cmdStr = "ports -j"
618 handle = self.sendline( cmdStr )
kelvin-onlab898a6c62015-01-16 14:13:53 -0800619 """
Jon Halle3f39ff2015-01-13 11:50:53 -0800620 handle variable here contains some ANSI escape color code
621 sequences at the end which are invisible in the print command
622 output. To make that escape sequence visible, use repr()
kelvin-onlab898a6c62015-01-16 14:13:53 -0800623 function. The repr( handle ) output when printed shows the ANSI
624 escape sequences. In json.loads( somestring ), this somestring
625 variable is actually repr( somestring ) and json.loads would
Jon Halle3f39ff2015-01-13 11:50:53 -0800626 fail with the escape sequence. So we take off that escape
627 sequence using the following commads:
628
kelvin-onlabd3b64892015-01-20 13:26:24 -0800629 ansiEscape = re.compile( r'\r\r\n\x1b[^m]*m' )
630 handle1 = ansiEscape.sub( '', handle )
kelvin-onlab898a6c62015-01-16 14:13:53 -0800631 """
kelvin-onlabd3b64892015-01-20 13:26:24 -0800632 ansiEscape = re.compile( r'\r\r\n\x1b[^m]*m' )
633 handle1 = ansiEscape.sub( '', handle )
Jon Halla001c392014-10-17 18:50:59 -0400634 return handle1
635
Jon Halle8217482014-10-17 13:49:14 -0400636 else:
kelvin-onlabd3b64892015-01-20 13:26:24 -0800637 cmdStr = "ports"
638 handle = self.sendline( cmdStr )
Jon Hallffb386d2014-11-21 13:43:38 -0800639 return handle
Jon Halld4d4b372015-01-28 16:02:41 -0800640 except TypeError:
641 main.log.exception( self.name + ": Object not as expected" )
642 return None
Jon Halle8217482014-10-17 13:49:14 -0400643 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -0800644 main.log.error( self.name + ": EOF exception found" )
645 main.log.error( self.name + ": " + self.handle.before )
Jon Halle8217482014-10-17 13:49:14 -0400646 main.cleanup()
647 main.exit()
648 except:
Jon Halld4d4b372015-01-28 16:02:41 -0800649 main.log.exception( self.name + ": Uncaught exception!" )
Jon Halle8217482014-10-17 13:49:14 -0400650 main.cleanup()
651 main.exit()
652
kelvin-onlabd3b64892015-01-20 13:26:24 -0800653 def roles( self, jsonFormat=True ):
kelvin8ec71442015-01-15 16:57:00 -0800654 """
Jon Hall983a1702014-10-28 18:44:22 -0400655 Lists all devices and the controllers with roles assigned to them
656 Optional argument:
kelvin-onlabd3b64892015-01-20 13:26:24 -0800657 * jsonFormat - boolean indicating if you want output in json
kelvin8ec71442015-01-15 16:57:00 -0800658 """
andrewonlab7c211572014-10-15 16:45:20 -0400659 try:
kelvin-onlabd3b64892015-01-20 13:26:24 -0800660 if jsonFormat:
661 cmdStr = "roles -j"
662 handle = self.sendline( cmdStr )
kelvin-onlab898a6c62015-01-16 14:13:53 -0800663 """
Jon Halle3f39ff2015-01-13 11:50:53 -0800664 handle variable here contains some ANSI escape color code
665 sequences at the end which are invisible in the print command
666 output. To make that escape sequence visible, use repr()
kelvin-onlab898a6c62015-01-16 14:13:53 -0800667 function. The repr( handle ) output when printed shows the ANSI
668 escape sequences. In json.loads( somestring ), this somestring
669 variable is actually repr( somestring ) and json.loads would
Jon Halle3f39ff2015-01-13 11:50:53 -0800670 fail with the escape sequence.
Jon Hallb1290e82014-11-18 16:17:48 -0500671
Jon Halle3f39ff2015-01-13 11:50:53 -0800672 So we take off that escape sequence using the following
673 commads:
674
kelvin-onlabd3b64892015-01-20 13:26:24 -0800675 ansiEscape = re.compile( r'\r\r\n\x1b[^m]*m' )
676 handle1 = ansiEscape.sub( '', handle )
kelvin-onlab898a6c62015-01-16 14:13:53 -0800677 """
kelvin-onlabd3b64892015-01-20 13:26:24 -0800678 ansiEscape = re.compile( r'\r\r\n\x1b[^m]*m' )
679 handle1 = ansiEscape.sub( '', handle )
Jon Hall983a1702014-10-28 18:44:22 -0400680 return handle1
andrewonlab7c211572014-10-15 16:45:20 -0400681
andrewonlab7c211572014-10-15 16:45:20 -0400682 else:
kelvin-onlabd3b64892015-01-20 13:26:24 -0800683 cmdStr = "roles"
684 handle = self.sendline( cmdStr )
Jon Hallffb386d2014-11-21 13:43:38 -0800685 return handle
Jon Halld4d4b372015-01-28 16:02:41 -0800686 except TypeError:
687 main.log.exception( self.name + ": Object not as expected" )
688 return None
Jon Hall983a1702014-10-28 18:44:22 -0400689 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -0800690 main.log.error( self.name + ": EOF exception found" )
691 main.log.error( self.name + ": " + self.handle.before )
Jon Hall983a1702014-10-28 18:44:22 -0400692 main.cleanup()
693 main.exit()
694 except:
Jon Halld4d4b372015-01-28 16:02:41 -0800695 main.log.exception( self.name + ": Uncaught exception!" )
Jon Hall983a1702014-10-28 18:44:22 -0400696 main.cleanup()
697 main.exit()
698
kelvin-onlabd3b64892015-01-20 13:26:24 -0800699 def getRole( self, deviceId ):
kelvin-onlab898a6c62015-01-16 14:13:53 -0800700 """
Jon Halle3f39ff2015-01-13 11:50:53 -0800701 Given the a string containing the json representation of the "roles"
702 cli command and a partial or whole device id, returns a json object
703 containing the roles output for the first device whose id contains
704 "device_id"
Jon Hall983a1702014-10-28 18:44:22 -0400705
706 Returns:
Jon Halle3f39ff2015-01-13 11:50:53 -0800707 A dict of the role assignments for the given device or
708 None if no match
kelvin8ec71442015-01-15 16:57:00 -0800709 """
Jon Hall983a1702014-10-28 18:44:22 -0400710 try:
kelvin-onlabd3b64892015-01-20 13:26:24 -0800711 if deviceId is None:
Jon Hall983a1702014-10-28 18:44:22 -0400712 return None
713 else:
kelvin-onlabd3b64892015-01-20 13:26:24 -0800714 rawRoles = self.roles()
715 rolesJson = json.loads( rawRoles )
kelvin8ec71442015-01-15 16:57:00 -0800716 # search json for the device with id then return the device
kelvin-onlabd3b64892015-01-20 13:26:24 -0800717 for device in rolesJson:
kelvin8ec71442015-01-15 16:57:00 -0800718 # print device
kelvin-onlabd3b64892015-01-20 13:26:24 -0800719 if str( deviceId ) in device[ 'id' ]:
Jon Hall983a1702014-10-28 18:44:22 -0400720 return device
721 return None
Jon Halld4d4b372015-01-28 16:02:41 -0800722 except TypeError:
723 main.log.exception( self.name + ": Object not as expected" )
724 return None
andrewonlab86dc3082014-10-13 18:18:38 -0400725 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -0800726 main.log.error( self.name + ": EOF exception found" )
727 main.log.error( self.name + ": " + self.handle.before )
andrewonlab86dc3082014-10-13 18:18:38 -0400728 main.cleanup()
729 main.exit()
730 except:
Jon Halld4d4b372015-01-28 16:02:41 -0800731 main.log.exception( self.name + ": Uncaught exception!" )
andrewonlab86dc3082014-10-13 18:18:38 -0400732 main.cleanup()
733 main.exit()
Jon Hall94fd0472014-12-08 11:52:42 -0800734
kelvin-onlabd3b64892015-01-20 13:26:24 -0800735 def rolesNotNull( self ):
kelvin8ec71442015-01-15 16:57:00 -0800736 """
Jon Hall94fd0472014-12-08 11:52:42 -0800737 Iterates through each device and checks if there is a master assigned
738 Returns: main.TRUE if each device has a master
739 main.FALSE any device has no master
kelvin8ec71442015-01-15 16:57:00 -0800740 """
Jon Hall94fd0472014-12-08 11:52:42 -0800741 try:
kelvin-onlabd3b64892015-01-20 13:26:24 -0800742 rawRoles = self.roles()
743 rolesJson = json.loads( rawRoles )
kelvin8ec71442015-01-15 16:57:00 -0800744 # search json for the device with id then return the device
kelvin-onlabd3b64892015-01-20 13:26:24 -0800745 for device in rolesJson:
kelvin8ec71442015-01-15 16:57:00 -0800746 # print device
747 if device[ 'master' ] == "none":
748 main.log.warn( "Device has no master: " + str( device ) )
Jon Hall94fd0472014-12-08 11:52:42 -0800749 return main.FALSE
750 return main.TRUE
751
Jon Halld4d4b372015-01-28 16:02:41 -0800752 except TypeError:
753 main.log.exception( self.name + ": Object not as expected" )
754 return None
Jon Hall94fd0472014-12-08 11:52:42 -0800755 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -0800756 main.log.error( self.name + ": EOF exception found" )
757 main.log.error( self.name + ": " + self.handle.before )
Jon Hall94fd0472014-12-08 11:52:42 -0800758 main.cleanup()
759 main.exit()
760 except:
Jon Halld4d4b372015-01-28 16:02:41 -0800761 main.log.exception( self.name + ": Uncaught exception!" )
Jon Hall94fd0472014-12-08 11:52:42 -0800762 main.cleanup()
763 main.exit()
764
kelvin-onlabd3b64892015-01-20 13:26:24 -0800765 def paths( self, srcId, dstId ):
kelvin8ec71442015-01-15 16:57:00 -0800766 """
andrewonlab3e15ead2014-10-15 14:21:34 -0400767 Returns string of paths, and the cost.
768 Issues command: onos:paths <src> <dst>
kelvin8ec71442015-01-15 16:57:00 -0800769 """
andrewonlab3e15ead2014-10-15 14:21:34 -0400770 try:
kelvin-onlabd3b64892015-01-20 13:26:24 -0800771 cmdStr = "onos:paths " + str( srcId ) + " " + str( dstId )
772 handle = self.sendline( cmdStr )
Jon Halle3f39ff2015-01-13 11:50:53 -0800773 if re.search( "Error", handle ):
kelvin8ec71442015-01-15 16:57:00 -0800774 main.log.error( "Error in getting paths" )
775 return ( handle, "Error" )
andrewonlab3e15ead2014-10-15 14:21:34 -0400776 else:
kelvin8ec71442015-01-15 16:57:00 -0800777 path = handle.split( ";" )[ 0 ]
778 cost = handle.split( ";" )[ 1 ]
779 return ( path, cost )
Jon Halld4d4b372015-01-28 16:02:41 -0800780 except TypeError:
781 main.log.exception( self.name + ": Object not as expected" )
782 return ( handle, "Error" )
andrewonlab3e15ead2014-10-15 14:21:34 -0400783 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -0800784 main.log.error( self.name + ": EOF exception found" )
785 main.log.error( self.name + ": " + self.handle.before )
andrewonlab3e15ead2014-10-15 14:21:34 -0400786 main.cleanup()
787 main.exit()
788 except:
Jon Halld4d4b372015-01-28 16:02:41 -0800789 main.log.exception( self.name + ": Uncaught exception!" )
andrewonlab3e15ead2014-10-15 14:21:34 -0400790 main.cleanup()
791 main.exit()
Jon Hallffb386d2014-11-21 13:43:38 -0800792
kelvin-onlabd3b64892015-01-20 13:26:24 -0800793 def hosts( self, jsonFormat=True ):
kelvin8ec71442015-01-15 16:57:00 -0800794 """
Jon Hallffb386d2014-11-21 13:43:38 -0800795 Lists all discovered hosts
Jon Hall42db6dc2014-10-24 19:03:48 -0400796 Optional argument:
kelvin-onlabd3b64892015-01-20 13:26:24 -0800797 * jsonFormat - boolean indicating if you want output in json
kelvin8ec71442015-01-15 16:57:00 -0800798 """
Jon Hall42db6dc2014-10-24 19:03:48 -0400799 try:
kelvin-onlabd3b64892015-01-20 13:26:24 -0800800 if jsonFormat:
801 cmdStr = "hosts -j"
802 handle = self.sendline( cmdStr )
kelvin-onlab898a6c62015-01-16 14:13:53 -0800803 """
Jon Halle3f39ff2015-01-13 11:50:53 -0800804 handle variable here contains some ANSI escape color code
805 sequences at the end which are invisible in the print command
806 output. To make that escape sequence visible, use repr()
kelvin-onlab898a6c62015-01-16 14:13:53 -0800807 function. The repr( handle ) output when printed shows the ANSI
808 escape sequences. In json.loads( somestring ), this somestring
809 variable is actually repr( somestring ) and json.loads would
Jon Halle3f39ff2015-01-13 11:50:53 -0800810 fail with the escape sequence. So we take off that escape
811 sequence using:
812
kelvin-onlabd3b64892015-01-20 13:26:24 -0800813 ansiEscape = re.compile( r'\r\r\n\x1b[^m]*m' )
814 handle1 = ansiEscape.sub( '', handle )
kelvin-onlab898a6c62015-01-16 14:13:53 -0800815 """
kelvin-onlabd3b64892015-01-20 13:26:24 -0800816 ansiEscape = re.compile( r'\r\r\n\x1b[^m]*m' )
817 handle1 = ansiEscape.sub( '', handle )
Jon Hall42db6dc2014-10-24 19:03:48 -0400818 return handle1
819 else:
kelvin-onlabd3b64892015-01-20 13:26:24 -0800820 cmdStr = "hosts"
821 handle = self.sendline( cmdStr )
Jon Hall42db6dc2014-10-24 19:03:48 -0400822 return handle
Jon Halld4d4b372015-01-28 16:02:41 -0800823 except TypeError:
824 main.log.exception( self.name + ": Object not as expected" )
825 return None
Jon Hall42db6dc2014-10-24 19:03:48 -0400826 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -0800827 main.log.error( self.name + ": EOF exception found" )
828 main.log.error( self.name + ": " + self.handle.before )
Jon Hall42db6dc2014-10-24 19:03:48 -0400829 main.cleanup()
830 main.exit()
831 except:
Jon Halld4d4b372015-01-28 16:02:41 -0800832 main.log.exception( self.name + ": Uncaught exception!" )
Jon Hall42db6dc2014-10-24 19:03:48 -0400833 main.cleanup()
834 main.exit()
835
kelvin-onlabd3b64892015-01-20 13:26:24 -0800836 def getHost( self, mac ):
kelvin8ec71442015-01-15 16:57:00 -0800837 """
Jon Hall42db6dc2014-10-24 19:03:48 -0400838 Return the first host from the hosts api whose 'id' contains 'mac'
Jon Halle3f39ff2015-01-13 11:50:53 -0800839
840 Note: mac must be a colon seperated mac address, but could be a
841 partial mac address
842
Jon Hall42db6dc2014-10-24 19:03:48 -0400843 Return None if there is no match
kelvin8ec71442015-01-15 16:57:00 -0800844 """
Jon Hall42db6dc2014-10-24 19:03:48 -0400845 try:
kelvin8ec71442015-01-15 16:57:00 -0800846 if mac is None:
Jon Hall42db6dc2014-10-24 19:03:48 -0400847 return None
848 else:
849 mac = mac
kelvin-onlabd3b64892015-01-20 13:26:24 -0800850 rawHosts = self.hosts()
851 hostsJson = json.loads( rawHosts )
kelvin8ec71442015-01-15 16:57:00 -0800852 # search json for the host with mac then return the device
kelvin-onlabd3b64892015-01-20 13:26:24 -0800853 for host in hostsJson:
kelvin8ec71442015-01-15 16:57:00 -0800854 # print "%s in %s?" % ( mac, host[ 'id' ] )
Jon Halld4d4b372015-01-28 16:02:41 -0800855 if not host:
856 pass
857 elif mac in host[ 'id' ]:
Jon Hall42db6dc2014-10-24 19:03:48 -0400858 return host
859 return None
Jon Halld4d4b372015-01-28 16:02:41 -0800860 except TypeError:
861 main.log.exception( self.name + ": Object not as expected" )
862 return None
Jon Hall42db6dc2014-10-24 19:03:48 -0400863 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -0800864 main.log.error( self.name + ": EOF exception found" )
865 main.log.error( self.name + ": " + self.handle.before )
Jon Hall42db6dc2014-10-24 19:03:48 -0400866 main.cleanup()
867 main.exit()
868 except:
Jon Halld4d4b372015-01-28 16:02:41 -0800869 main.log.exception( self.name + ": Uncaught exception!" )
Jon Hall42db6dc2014-10-24 19:03:48 -0400870 main.cleanup()
871 main.exit()
872
kelvin-onlabd3b64892015-01-20 13:26:24 -0800873 def getHostsId( self, hostList ):
kelvin8ec71442015-01-15 16:57:00 -0800874 """
875 Obtain list of hosts
andrewonlab3f0a4af2014-10-17 12:25:14 -0400876 Issues command: 'onos> hosts'
kelvin8ec71442015-01-15 16:57:00 -0800877
andrewonlab3f0a4af2014-10-17 12:25:14 -0400878 Required:
kelvin-onlabd3b64892015-01-20 13:26:24 -0800879 * hostList: List of hosts obtained by Mininet
andrewonlab3f0a4af2014-10-17 12:25:14 -0400880 IMPORTANT:
881 This function assumes that you started your
kelvin8ec71442015-01-15 16:57:00 -0800882 topology with the option '--mac'.
andrewonlab3f0a4af2014-10-17 12:25:14 -0400883 Furthermore, it assumes that value of VLAN is '-1'
884 Description:
kelvin8ec71442015-01-15 16:57:00 -0800885 Converts mininet hosts ( h1, h2, h3... ) into
886 ONOS format ( 00:00:00:00:00:01/-1 , ... )
887 """
andrewonlab3f0a4af2014-10-17 12:25:14 -0400888 try:
kelvin-onlabd3b64892015-01-20 13:26:24 -0800889 onosHostList = []
andrewonlab3f0a4af2014-10-17 12:25:14 -0400890
kelvin-onlabd3b64892015-01-20 13:26:24 -0800891 for host in hostList:
kelvin8ec71442015-01-15 16:57:00 -0800892 host = host.replace( "h", "" )
kelvin-onlabd3b64892015-01-20 13:26:24 -0800893 hostHex = hex( int( host ) ).zfill( 12 )
894 hostHex = str( hostHex ).replace( 'x', '0' )
895 i = iter( str( hostHex ) )
896 hostHex = ":".join( a + b for a, b in zip( i, i ) )
897 hostHex = hostHex + "/-1"
898 onosHostList.append( hostHex )
andrewonlab3f0a4af2014-10-17 12:25:14 -0400899
kelvin-onlabd3b64892015-01-20 13:26:24 -0800900 return onosHostList
andrewonlab3f0a4af2014-10-17 12:25:14 -0400901
Jon Halld4d4b372015-01-28 16:02:41 -0800902 except TypeError:
903 main.log.exception( self.name + ": Object not as expected" )
904 return None
andrewonlab3f0a4af2014-10-17 12:25:14 -0400905 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -0800906 main.log.error( self.name + ": EOF exception found" )
907 main.log.error( self.name + ": " + self.handle.before )
andrewonlab3f0a4af2014-10-17 12:25:14 -0400908 main.cleanup()
909 main.exit()
910 except:
Jon Halld4d4b372015-01-28 16:02:41 -0800911 main.log.exception( self.name + ": Uncaught exception!" )
andrewonlab3f0a4af2014-10-17 12:25:14 -0400912 main.cleanup()
913 main.exit()
andrewonlab3e15ead2014-10-15 14:21:34 -0400914
kelvin-onlabd3b64892015-01-20 13:26:24 -0800915 def addHostIntent( self, hostIdOne, hostIdTwo ):
kelvin8ec71442015-01-15 16:57:00 -0800916 """
andrewonlabe6745342014-10-17 14:29:13 -0400917 Required:
kelvin-onlabd3b64892015-01-20 13:26:24 -0800918 * hostIdOne: ONOS host id for host1
919 * hostIdTwo: ONOS host id for host2
andrewonlabe6745342014-10-17 14:29:13 -0400920 Description:
kelvin8ec71442015-01-15 16:57:00 -0800921 Adds a host-to-host intent ( bidrectional ) by
Jon Hallb1290e82014-11-18 16:17:48 -0500922 specifying the two hosts.
kelvin-onlabfb521662015-02-27 09:52:40 -0800923 Returns:
924 A string of the intent id or None on Error
kelvin8ec71442015-01-15 16:57:00 -0800925 """
andrewonlabe6745342014-10-17 14:29:13 -0400926 try:
kelvin-onlabd3b64892015-01-20 13:26:24 -0800927 cmdStr = "add-host-intent " + str( hostIdOne ) +\
928 " " + str( hostIdTwo )
929 handle = self.sendline( cmdStr )
Hari Krishnaac4e1782015-01-26 12:09:12 -0800930 if re.search( "Error", handle ):
931 main.log.error( "Error in adding Host intent" )
kelvin-onlabfb521662015-02-27 09:52:40 -0800932 return None
Hari Krishnaac4e1782015-01-26 12:09:12 -0800933 else:
934 main.log.info( "Host intent installed between " +
kelvin-onlabfb521662015-02-27 09:52:40 -0800935 str( hostIdOne ) + " and " + str( hostIdTwo ) )
936 match = re.search('id=0x([\da-f]+),', handle)
937 if match:
938 return match.group()[3:-1]
939 else:
940 main.log.error( "Error, intent ID not found" )
941 return None
Jon Halld4d4b372015-01-28 16:02:41 -0800942 except TypeError:
943 main.log.exception( self.name + ": Object not as expected" )
944 return None
andrewonlabe6745342014-10-17 14:29:13 -0400945 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -0800946 main.log.error( self.name + ": EOF exception found" )
947 main.log.error( self.name + ": " + self.handle.before )
andrewonlabe6745342014-10-17 14:29:13 -0400948 main.cleanup()
949 main.exit()
950 except:
Jon Halld4d4b372015-01-28 16:02:41 -0800951 main.log.exception( self.name + ": Uncaught exception!" )
andrewonlabe6745342014-10-17 14:29:13 -0400952 main.cleanup()
953 main.exit()
954
kelvin-onlabd3b64892015-01-20 13:26:24 -0800955 def addOpticalIntent( self, ingressDevice, egressDevice ):
kelvin8ec71442015-01-15 16:57:00 -0800956 """
andrewonlab7b31d232014-10-24 13:31:47 -0400957 Required:
kelvin-onlabd3b64892015-01-20 13:26:24 -0800958 * ingressDevice: device id of ingress device
959 * egressDevice: device id of egress device
andrewonlab7b31d232014-10-24 13:31:47 -0400960 Optional:
961 TODO: Still needs to be implemented via dev side
kelvin-onlabfb521662015-02-27 09:52:40 -0800962 Description:
963 Adds an optical intent by specifying an ingress and egress device
964 Returns:
965 A string of the intent id or None on error
kelvin-onlab898a6c62015-01-16 14:13:53 -0800966 """
andrewonlab7b31d232014-10-24 13:31:47 -0400967 try:
kelvin-onlabd3b64892015-01-20 13:26:24 -0800968 cmdStr = "add-optical-intent " + str( ingressDevice ) +\
969 " " + str( egressDevice )
970 handle = self.sendline( cmdStr )
kelvin-onlab898a6c62015-01-16 14:13:53 -0800971 # If error, return error message
Jon Halle3f39ff2015-01-13 11:50:53 -0800972 if re.search( "Error", handle ):
kelvin-onlabfb521662015-02-27 09:52:40 -0800973 main.log.error( "Error in adding Optical intent" )
974 return None
andrewonlab7b31d232014-10-24 13:31:47 -0400975 else:
kelvin-onlabfb521662015-02-27 09:52:40 -0800976 main.log.info( "Optical intent installed between " +
977 str( ingressDevice ) + " and " +
978 str( egressDevice ) )
979 match = re.search('id=0x([\da-f]+),', handle)
980 if match:
981 return match.group()[3:-1]
982 else:
983 main.log.error( "Error, intent ID not found" )
984 return None
Jon Halld4d4b372015-01-28 16:02:41 -0800985 except TypeError:
986 main.log.exception( self.name + ": Object not as expected" )
987 return None
andrewonlab7b31d232014-10-24 13:31:47 -0400988 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -0800989 main.log.error( self.name + ": EOF exception found" )
990 main.log.error( self.name + ": " + self.handle.before )
andrewonlab7b31d232014-10-24 13:31:47 -0400991 main.cleanup()
992 main.exit()
993 except:
Jon Halld4d4b372015-01-28 16:02:41 -0800994 main.log.exception( self.name + ": Uncaught exception!" )
andrewonlab7b31d232014-10-24 13:31:47 -0400995 main.cleanup()
996 main.exit()
997
kelvin-onlabd3b64892015-01-20 13:26:24 -0800998 def addPointIntent(
kelvin-onlab898a6c62015-01-16 14:13:53 -0800999 self,
kelvin-onlabd3b64892015-01-20 13:26:24 -08001000 ingressDevice,
1001 egressDevice,
1002 portIngress="",
1003 portEgress="",
kelvin-onlab898a6c62015-01-16 14:13:53 -08001004 ethType="",
1005 ethSrc="",
1006 ethDst="",
1007 bandwidth="",
kelvin-onlabd3b64892015-01-20 13:26:24 -08001008 lambdaAlloc=False,
kelvin-onlab898a6c62015-01-16 14:13:53 -08001009 ipProto="",
1010 ipSrc="",
1011 ipDst="",
1012 tcpSrc="",
1013 tcpDst="" ):
kelvin8ec71442015-01-15 16:57:00 -08001014 """
andrewonlab4dbb4d82014-10-17 18:22:31 -04001015 Required:
kelvin-onlabd3b64892015-01-20 13:26:24 -08001016 * ingressDevice: device id of ingress device
1017 * egressDevice: device id of egress device
andrewonlab289e4b72014-10-21 21:24:18 -04001018 Optional:
1019 * ethType: specify ethType
kelvin8ec71442015-01-15 16:57:00 -08001020 * ethSrc: specify ethSrc ( i.e. src mac addr )
1021 * ethDst: specify ethDst ( i.e. dst mac addr )
andrewonlab0dbb6ec2014-11-06 13:46:55 -05001022 * bandwidth: specify bandwidth capacity of link
kelvin-onlabd3b64892015-01-20 13:26:24 -08001023 * lambdaAlloc: if True, intent will allocate lambda
andrewonlab40ccd8b2014-11-06 16:23:34 -05001024 for the specified intent
Jon Halle3f39ff2015-01-13 11:50:53 -08001025 * ipProto: specify ip protocol
andrewonlabf77e0cb2014-11-11 17:17:59 -05001026 * ipSrc: specify ip source address
1027 * ipDst: specify ip destination address
1028 * tcpSrc: specify tcp source port
1029 * tcpDst: specify tcp destination port
andrewonlab4dbb4d82014-10-17 18:22:31 -04001030 Description:
kelvin8ec71442015-01-15 16:57:00 -08001031 Adds a point-to-point intent ( uni-directional ) by
andrewonlab289e4b72014-10-21 21:24:18 -04001032 specifying device id's and optional fields
kelvin-onlabfb521662015-02-27 09:52:40 -08001033 Returns:
1034 A string of the intent id or None on error
andrewonlab289e4b72014-10-21 21:24:18 -04001035
Jon Halle3f39ff2015-01-13 11:50:53 -08001036 NOTE: This function may change depending on the
andrewonlab4dbb4d82014-10-17 18:22:31 -04001037 options developers provide for point-to-point
1038 intent via cli
kelvin8ec71442015-01-15 16:57:00 -08001039 """
andrewonlab4dbb4d82014-10-17 18:22:31 -04001040 try:
andrewonlab289e4b72014-10-21 21:24:18 -04001041 cmd = ""
1042
kelvin8ec71442015-01-15 16:57:00 -08001043 # If there are no optional arguments
andrewonlab0dbb6ec2014-11-06 13:46:55 -05001044 if not ethType and not ethSrc and not ethDst\
kelvin-onlabd3b64892015-01-20 13:26:24 -08001045 and not bandwidth and not lambdaAlloc \
andrewonlabfa4ff502014-11-11 16:41:30 -05001046 and not ipProto and not ipSrc and not ipDst \
1047 and not tcpSrc and not tcpDst:
andrewonlab36af3822014-11-18 17:48:18 -05001048 cmd = "add-point-intent"
andrewonlab36af3822014-11-18 17:48:18 -05001049
andrewonlab289e4b72014-10-21 21:24:18 -04001050 else:
andrewonlab36af3822014-11-18 17:48:18 -05001051 cmd = "add-point-intent"
Jon Halle3f39ff2015-01-13 11:50:53 -08001052
andrewonlab0c0a6772014-10-22 12:31:18 -04001053 if ethType:
kelvin8ec71442015-01-15 16:57:00 -08001054 cmd += " --ethType " + str( ethType )
andrewonlab289e4b72014-10-21 21:24:18 -04001055 if ethSrc:
kelvin8ec71442015-01-15 16:57:00 -08001056 cmd += " --ethSrc " + str( ethSrc )
1057 if ethDst:
1058 cmd += " --ethDst " + str( ethDst )
andrewonlab0dbb6ec2014-11-06 13:46:55 -05001059 if bandwidth:
kelvin8ec71442015-01-15 16:57:00 -08001060 cmd += " --bandwidth " + str( bandwidth )
kelvin-onlabd3b64892015-01-20 13:26:24 -08001061 if lambdaAlloc:
andrewonlabfa4ff502014-11-11 16:41:30 -05001062 cmd += " --lambda "
1063 if ipProto:
kelvin8ec71442015-01-15 16:57:00 -08001064 cmd += " --ipProto " + str( ipProto )
andrewonlabfa4ff502014-11-11 16:41:30 -05001065 if ipSrc:
kelvin8ec71442015-01-15 16:57:00 -08001066 cmd += " --ipSrc " + str( ipSrc )
andrewonlabfa4ff502014-11-11 16:41:30 -05001067 if ipDst:
kelvin8ec71442015-01-15 16:57:00 -08001068 cmd += " --ipDst " + str( ipDst )
andrewonlabfa4ff502014-11-11 16:41:30 -05001069 if tcpSrc:
kelvin8ec71442015-01-15 16:57:00 -08001070 cmd += " --tcpSrc " + str( tcpSrc )
andrewonlabfa4ff502014-11-11 16:41:30 -05001071 if tcpDst:
kelvin8ec71442015-01-15 16:57:00 -08001072 cmd += " --tcpDst " + str( tcpDst )
andrewonlab289e4b72014-10-21 21:24:18 -04001073
kelvin8ec71442015-01-15 16:57:00 -08001074 # Check whether the user appended the port
1075 # or provided it as an input
kelvin-onlabd3b64892015-01-20 13:26:24 -08001076 if "/" in ingressDevice:
1077 cmd += " " + str( ingressDevice )
andrewonlab36af3822014-11-18 17:48:18 -05001078 else:
kelvin-onlabd3b64892015-01-20 13:26:24 -08001079 if not portIngress:
kelvin-onlabfb521662015-02-27 09:52:40 -08001080 main.log.error( "You must specify the ingress port" )
kelvin8ec71442015-01-15 16:57:00 -08001081 # TODO: perhaps more meaningful return
kelvin-onlabfb521662015-02-27 09:52:40 -08001082 # Would it make sense to throw an exception and exit
1083 # the test?
1084 return None
andrewonlab36af3822014-11-18 17:48:18 -05001085
kelvin8ec71442015-01-15 16:57:00 -08001086 cmd += " " + \
kelvin-onlabd3b64892015-01-20 13:26:24 -08001087 str( ingressDevice ) + "/" +\
1088 str( portIngress ) + " "
andrewonlab36af3822014-11-18 17:48:18 -05001089
kelvin-onlabd3b64892015-01-20 13:26:24 -08001090 if "/" in egressDevice:
1091 cmd += " " + str( egressDevice )
andrewonlab36af3822014-11-18 17:48:18 -05001092 else:
kelvin-onlabd3b64892015-01-20 13:26:24 -08001093 if not portEgress:
kelvin-onlabfb521662015-02-27 09:52:40 -08001094 main.log.error( "You must specify the egress port" )
1095 return None
Jon Halle3f39ff2015-01-13 11:50:53 -08001096
kelvin8ec71442015-01-15 16:57:00 -08001097 cmd += " " +\
kelvin-onlabd3b64892015-01-20 13:26:24 -08001098 str( egressDevice ) + "/" +\
1099 str( portEgress )
kelvin8ec71442015-01-15 16:57:00 -08001100
kelvin-onlab898a6c62015-01-16 14:13:53 -08001101 handle = self.sendline( cmd )
kelvin-onlabfb521662015-02-27 09:52:40 -08001102 # If error, return error message
kelvin-onlab898a6c62015-01-16 14:13:53 -08001103 if re.search( "Error", handle ):
kelvin8ec71442015-01-15 16:57:00 -08001104 main.log.error( "Error in adding point-to-point intent" )
kelvin-onlabfb521662015-02-27 09:52:40 -08001105 return None
andrewonlab4dbb4d82014-10-17 18:22:31 -04001106 else:
kelvin-onlabfb521662015-02-27 09:52:40 -08001107 # TODO: print out all the options in this message?
1108 main.log.info( "Point-to-point intent installed between " +
1109 str( ingressDevice ) + " and " +
1110 str( egressDevice ) )
1111 match = re.search('id=0x([\da-f]+),', handle)
1112 if match:
1113 return match.group()[3:-1]
1114 else:
1115 main.log.error( "Error, intent ID not found" )
1116 return None
Jon Halld4d4b372015-01-28 16:02:41 -08001117 except TypeError:
1118 main.log.exception( self.name + ": Object not as expected" )
1119 return None
andrewonlab4dbb4d82014-10-17 18:22:31 -04001120 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08001121 main.log.error( self.name + ": EOF exception found" )
1122 main.log.error( self.name + ": " + self.handle.before )
andrewonlab4dbb4d82014-10-17 18:22:31 -04001123 main.cleanup()
1124 main.exit()
1125 except:
Jon Halld4d4b372015-01-28 16:02:41 -08001126 main.log.exception( self.name + ": Uncaught exception!" )
andrewonlab4dbb4d82014-10-17 18:22:31 -04001127 main.cleanup()
1128 main.exit()
1129
kelvin-onlabd3b64892015-01-20 13:26:24 -08001130 def addMultipointToSinglepointIntent(
kelvin-onlab898a6c62015-01-16 14:13:53 -08001131 self,
kelvin-onlabd3b64892015-01-20 13:26:24 -08001132 ingressDevice1,
1133 ingressDevice2,
1134 egressDevice,
kelvin-onlabfb521662015-02-27 09:52:40 -08001135 portIngress1="",
1136 portIngress2="",
kelvin-onlabd3b64892015-01-20 13:26:24 -08001137 portEgress="",
kelvin-onlab898a6c62015-01-16 14:13:53 -08001138 ethType="",
1139 ethSrc="",
1140 ethDst="",
1141 bandwidth="",
kelvin-onlabd3b64892015-01-20 13:26:24 -08001142 lambdaAlloc=False,
kelvin-onlab898a6c62015-01-16 14:13:53 -08001143 ipProto="",
1144 ipSrc="",
1145 ipDst="",
1146 tcpSrc="",
1147 tcpDst="",
1148 setEthSrc="",
1149 setEthDst="" ):
kelvin8ec71442015-01-15 16:57:00 -08001150 """
shahshreyad0c80432014-12-04 16:56:05 -08001151 Note:
Jon Halle3f39ff2015-01-13 11:50:53 -08001152 This function assumes that there would be 2 ingress devices and
1153 one egress device. For more number of ingress devices, this
1154 function needs to be modified
shahshreyad0c80432014-12-04 16:56:05 -08001155 Required:
kelvin-onlabd3b64892015-01-20 13:26:24 -08001156 * ingressDevice1: device id of ingress device1
1157 * ingressDevice2: device id of ingress device2
1158 * egressDevice: device id of egress device
shahshreyad0c80432014-12-04 16:56:05 -08001159 Optional:
1160 * ethType: specify ethType
kelvin8ec71442015-01-15 16:57:00 -08001161 * ethSrc: specify ethSrc ( i.e. src mac addr )
1162 * ethDst: specify ethDst ( i.e. dst mac addr )
shahshreyad0c80432014-12-04 16:56:05 -08001163 * bandwidth: specify bandwidth capacity of link
kelvin-onlabd3b64892015-01-20 13:26:24 -08001164 * lambdaAlloc: if True, intent will allocate lambda
shahshreyad0c80432014-12-04 16:56:05 -08001165 for the specified intent
Jon Halle3f39ff2015-01-13 11:50:53 -08001166 * ipProto: specify ip protocol
shahshreyad0c80432014-12-04 16:56:05 -08001167 * ipSrc: specify ip source address
1168 * ipDst: specify ip destination address
1169 * tcpSrc: specify tcp source port
1170 * tcpDst: specify tcp destination port
1171 * setEthSrc: action to Rewrite Source MAC Address
1172 * setEthDst: action to Rewrite Destination MAC Address
1173 Description:
kelvin8ec71442015-01-15 16:57:00 -08001174 Adds a multipoint-to-singlepoint intent ( uni-directional ) by
shahshreyad0c80432014-12-04 16:56:05 -08001175 specifying device id's and optional fields
kelvin-onlabfb521662015-02-27 09:52:40 -08001176 Returns:
1177 A string of the intent id or None on error
shahshreyad0c80432014-12-04 16:56:05 -08001178
Jon Halle3f39ff2015-01-13 11:50:53 -08001179 NOTE: This function may change depending on the
shahshreyad0c80432014-12-04 16:56:05 -08001180 options developers provide for multipointpoint-to-singlepoint
1181 intent via cli
kelvin8ec71442015-01-15 16:57:00 -08001182 """
shahshreyad0c80432014-12-04 16:56:05 -08001183 try:
1184 cmd = ""
1185
kelvin8ec71442015-01-15 16:57:00 -08001186 # If there are no optional arguments
shahshreyad0c80432014-12-04 16:56:05 -08001187 if not ethType and not ethSrc and not ethDst\
kelvin-onlabd3b64892015-01-20 13:26:24 -08001188 and not bandwidth and not lambdaAlloc\
Jon Halle3f39ff2015-01-13 11:50:53 -08001189 and not ipProto and not ipSrc and not ipDst\
1190 and not tcpSrc and not tcpDst and not setEthSrc\
1191 and not setEthDst:
shahshreyad0c80432014-12-04 16:56:05 -08001192 cmd = "add-multi-to-single-intent"
shahshreyad0c80432014-12-04 16:56:05 -08001193
1194 else:
1195 cmd = "add-multi-to-single-intent"
Jon Halle3f39ff2015-01-13 11:50:53 -08001196
shahshreyad0c80432014-12-04 16:56:05 -08001197 if ethType:
kelvin8ec71442015-01-15 16:57:00 -08001198 cmd += " --ethType " + str( ethType )
shahshreyad0c80432014-12-04 16:56:05 -08001199 if ethSrc:
kelvin8ec71442015-01-15 16:57:00 -08001200 cmd += " --ethSrc " + str( ethSrc )
1201 if ethDst:
1202 cmd += " --ethDst " + str( ethDst )
shahshreyad0c80432014-12-04 16:56:05 -08001203 if bandwidth:
kelvin8ec71442015-01-15 16:57:00 -08001204 cmd += " --bandwidth " + str( bandwidth )
kelvin-onlabd3b64892015-01-20 13:26:24 -08001205 if lambdaAlloc:
shahshreyad0c80432014-12-04 16:56:05 -08001206 cmd += " --lambda "
1207 if ipProto:
kelvin8ec71442015-01-15 16:57:00 -08001208 cmd += " --ipProto " + str( ipProto )
shahshreyad0c80432014-12-04 16:56:05 -08001209 if ipSrc:
kelvin8ec71442015-01-15 16:57:00 -08001210 cmd += " --ipSrc " + str( ipSrc )
shahshreyad0c80432014-12-04 16:56:05 -08001211 if ipDst:
kelvin8ec71442015-01-15 16:57:00 -08001212 cmd += " --ipDst " + str( ipDst )
shahshreyad0c80432014-12-04 16:56:05 -08001213 if tcpSrc:
kelvin8ec71442015-01-15 16:57:00 -08001214 cmd += " --tcpSrc " + str( tcpSrc )
shahshreyad0c80432014-12-04 16:56:05 -08001215 if tcpDst:
kelvin8ec71442015-01-15 16:57:00 -08001216 cmd += " --tcpDst " + str( tcpDst )
shahshreyad0c80432014-12-04 16:56:05 -08001217 if setEthSrc:
kelvin8ec71442015-01-15 16:57:00 -08001218 cmd += " --setEthSrc " + str( setEthSrc )
shahshreyad0c80432014-12-04 16:56:05 -08001219 if setEthDst:
kelvin8ec71442015-01-15 16:57:00 -08001220 cmd += " --setEthDst " + str( setEthDst )
shahshreyad0c80432014-12-04 16:56:05 -08001221
kelvin8ec71442015-01-15 16:57:00 -08001222 # Check whether the user appended the port
1223 # or provided it as an input
kelvin-onlabd3b64892015-01-20 13:26:24 -08001224 if "/" in ingressDevice1:
1225 cmd += " " + str( ingressDevice1 )
shahshreyad0c80432014-12-04 16:56:05 -08001226 else:
kelvin-onlabd3b64892015-01-20 13:26:24 -08001227 if not portIngress1:
kelvin8ec71442015-01-15 16:57:00 -08001228 main.log.error( "You must specify " +
1229 "the ingress port1" )
1230 # TODO: perhaps more meaningful return
kelvin-onlabfb521662015-02-27 09:52:40 -08001231 return None
shahshreyad0c80432014-12-04 16:56:05 -08001232
kelvin8ec71442015-01-15 16:57:00 -08001233 cmd += " " + \
kelvin-onlabd3b64892015-01-20 13:26:24 -08001234 str( ingressDevice1 ) + "/" +\
1235 str( portIngress1 ) + " "
shahshreyad0c80432014-12-04 16:56:05 -08001236
kelvin-onlabd3b64892015-01-20 13:26:24 -08001237 if "/" in ingressDevice2:
1238 cmd += " " + str( ingressDevice2 )
shahshreyad0c80432014-12-04 16:56:05 -08001239 else:
kelvin-onlabd3b64892015-01-20 13:26:24 -08001240 if not portIngress2:
kelvin8ec71442015-01-15 16:57:00 -08001241 main.log.error( "You must specify " +
1242 "the ingress port2" )
1243 # TODO: perhaps more meaningful return
kelvin-onlabfb521662015-02-27 09:52:40 -08001244 return None
shahshreyad0c80432014-12-04 16:56:05 -08001245
kelvin8ec71442015-01-15 16:57:00 -08001246 cmd += " " + \
kelvin-onlabd3b64892015-01-20 13:26:24 -08001247 str( ingressDevice2 ) + "/" +\
1248 str( portIngress2 ) + " "
shahshreyad0c80432014-12-04 16:56:05 -08001249
kelvin-onlabd3b64892015-01-20 13:26:24 -08001250 if "/" in egressDevice:
1251 cmd += " " + str( egressDevice )
shahshreyad0c80432014-12-04 16:56:05 -08001252 else:
kelvin-onlabd3b64892015-01-20 13:26:24 -08001253 if not portEgress:
kelvin8ec71442015-01-15 16:57:00 -08001254 main.log.error( "You must specify " +
1255 "the egress port" )
shahshreyad0c80432014-12-04 16:56:05 -08001256 return main.FALSE
Jon Halle3f39ff2015-01-13 11:50:53 -08001257
kelvin8ec71442015-01-15 16:57:00 -08001258 cmd += " " +\
kelvin-onlabd3b64892015-01-20 13:26:24 -08001259 str( egressDevice ) + "/" +\
1260 str( portEgress )
kelvin8ec71442015-01-15 16:57:00 -08001261 print "cmd= ", cmd
kelvin-onlab898a6c62015-01-16 14:13:53 -08001262 handle = self.sendline( cmd )
kelvin-onlabfb521662015-02-27 09:52:40 -08001263 # If error, return error message
kelvin-onlab898a6c62015-01-16 14:13:53 -08001264 if re.search( "Error", handle ):
kelvin-onlabfb521662015-02-27 09:52:40 -08001265 main.log.error( "Error in adding multipoint-to-singlepoint " +
1266 "intent" )
1267 return None
shahshreyad0c80432014-12-04 16:56:05 -08001268 else:
kelvin-onlabfb521662015-02-27 09:52:40 -08001269 # TODO: print out all the options in this message?
1270 main.log.info( "Multipoint-to-singlepoint intent installed" +
1271 " between " + str( ingressDevice1 ) + ", " +
1272 str( ingressDevice2 ) + " and " +
1273 str( egressDevice ) )
1274 match = re.search('id=0x([\da-f]+),', handle)
1275 if match:
1276 return match.group()[3:-1]
1277 else:
1278 main.log.error( "Error, intent ID not found" )
1279 return None
Jon Halld4d4b372015-01-28 16:02:41 -08001280 except TypeError:
1281 main.log.exception( self.name + ": Object not as expected" )
1282 return None
shahshreyad0c80432014-12-04 16:56:05 -08001283 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08001284 main.log.error( self.name + ": EOF exception found" )
1285 main.log.error( self.name + ": " + self.handle.before )
shahshreyad0c80432014-12-04 16:56:05 -08001286 main.cleanup()
1287 main.exit()
1288 except:
Jon Halld4d4b372015-01-28 16:02:41 -08001289 main.log.exception( self.name + ": Uncaught exception!" )
shahshreyad0c80432014-12-04 16:56:05 -08001290 main.cleanup()
1291 main.exit()
1292
shahshreya1c818fc2015-02-26 13:44:08 -08001293 def removeIntent( self, intentId, app = 'org.onosproject.cli',
1294 purge = False, sync = False ):
kelvin-onlab898a6c62015-01-16 14:13:53 -08001295 """
shahshreya1c818fc2015-02-26 13:44:08 -08001296 Remove intent for specified application id and intent id
1297 Optional args:-
1298 -s or --sync: Waits for the removal before returning
1299 -p or --purge: Purge the intent from the store after removal
1300
Jon Halle3f39ff2015-01-13 11:50:53 -08001301 Returns:
1302 main.False on error and
1303 cli output otherwise
kelvin-onlab898a6c62015-01-16 14:13:53 -08001304 """
andrewonlab9a50dfe2014-10-17 17:22:31 -04001305 try:
shahshreya1c818fc2015-02-26 13:44:08 -08001306 cmdStr = "remove-intent "
1307 if purge:
1308 cmdStr += " -p"
1309 if sync:
1310 cmdStr += " -s"
1311
1312 cmdStr += " " + app + " " + str( intentId )
kelvin-onlabd3b64892015-01-20 13:26:24 -08001313 handle = self.sendline( cmdStr )
Jon Halle3f39ff2015-01-13 11:50:53 -08001314 if re.search( "Error", handle ):
kelvin-onlab898a6c62015-01-16 14:13:53 -08001315 main.log.error( "Error in removing intent" )
Jon Halle3f39ff2015-01-13 11:50:53 -08001316 return main.FALSE
andrewonlab9a50dfe2014-10-17 17:22:31 -04001317 else:
Jon Halle3f39ff2015-01-13 11:50:53 -08001318 # TODO: Should this be main.TRUE
1319 return handle
Jon Halld4d4b372015-01-28 16:02:41 -08001320 except TypeError:
1321 main.log.exception( self.name + ": Object not as expected" )
1322 return None
andrewonlab9a50dfe2014-10-17 17:22:31 -04001323 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08001324 main.log.error( self.name + ": EOF exception found" )
1325 main.log.error( self.name + ": " + self.handle.before )
andrewonlab9a50dfe2014-10-17 17:22:31 -04001326 main.cleanup()
1327 main.exit()
1328 except:
Jon Halld4d4b372015-01-28 16:02:41 -08001329 main.log.exception( self.name + ": Uncaught exception!" )
andrewonlab9a50dfe2014-10-17 17:22:31 -04001330 main.cleanup()
1331 main.exit()
1332
kelvin-onlabd3b64892015-01-20 13:26:24 -08001333 def routes( self, jsonFormat=False ):
kelvin8ec71442015-01-15 16:57:00 -08001334 """
kelvin-onlab898a6c62015-01-16 14:13:53 -08001335 NOTE: This method should be used after installing application:
1336 onos-app-sdnip
pingping-lin8b306ac2014-11-17 18:13:51 -08001337 Optional:
kelvin-onlabd3b64892015-01-20 13:26:24 -08001338 * jsonFormat: enable output formatting in json
pingping-lin8b306ac2014-11-17 18:13:51 -08001339 Description:
1340 Obtain all routes in the system
kelvin8ec71442015-01-15 16:57:00 -08001341 """
pingping-lin8b306ac2014-11-17 18:13:51 -08001342 try:
kelvin-onlabd3b64892015-01-20 13:26:24 -08001343 if jsonFormat:
1344 cmdStr = "routes -j"
1345 handleTmp = self.sendline( cmdStr )
1346 ansiEscape = re.compile( r'\r\r\n\x1b[^m]*m' )
1347 handle = ansiEscape.sub( '', handleTmp )
pingping-lin8b306ac2014-11-17 18:13:51 -08001348 else:
kelvin-onlabd3b64892015-01-20 13:26:24 -08001349 cmdStr = "routes"
1350 handle = self.sendline( cmdStr )
pingping-lin8b306ac2014-11-17 18:13:51 -08001351 return handle
Jon Halld4d4b372015-01-28 16:02:41 -08001352 except TypeError:
1353 main.log.exception( self.name + ": Object not as expected" )
1354 return None
pingping-lin8b306ac2014-11-17 18:13:51 -08001355 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08001356 main.log.error( self.name + ": EOF exception found" )
1357 main.log.error( self.name + ": " + self.handle.before )
pingping-lin8b306ac2014-11-17 18:13:51 -08001358 main.cleanup()
1359 main.exit()
1360 except:
Jon Halld4d4b372015-01-28 16:02:41 -08001361 main.log.exception( self.name + ": Uncaught exception!" )
pingping-lin8b306ac2014-11-17 18:13:51 -08001362 main.cleanup()
1363 main.exit()
1364
kelvin-onlabd3b64892015-01-20 13:26:24 -08001365 def intents( self, jsonFormat=True ):
kelvin8ec71442015-01-15 16:57:00 -08001366 """
andrewonlab377693f2014-10-21 16:00:30 -04001367 Optional:
kelvin-onlabd3b64892015-01-20 13:26:24 -08001368 * jsonFormat: enable output formatting in json
andrewonlabe6745342014-10-17 14:29:13 -04001369 Description:
Jon Halle3f39ff2015-01-13 11:50:53 -08001370 Obtain intents currently installed
kelvin-onlab898a6c62015-01-16 14:13:53 -08001371 """
andrewonlabe6745342014-10-17 14:29:13 -04001372 try:
kelvin-onlabd3b64892015-01-20 13:26:24 -08001373 if jsonFormat:
1374 cmdStr = "intents -j"
1375 handle = self.sendline( cmdStr )
1376 ansiEscape = re.compile( r'\r\r\n\x1b[^m]*m' )
1377 handle = ansiEscape.sub( '', handle )
kelvin8ec71442015-01-15 16:57:00 -08001378 else:
kelvin-onlabd3b64892015-01-20 13:26:24 -08001379 cmdStr = "intents"
1380 handle = self.sendline( cmdStr )
andrewonlabe6745342014-10-17 14:29:13 -04001381 return handle
Jon Halld4d4b372015-01-28 16:02:41 -08001382 except TypeError:
1383 main.log.exception( self.name + ": Object not as expected" )
1384 return None
andrewonlabe6745342014-10-17 14:29:13 -04001385 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08001386 main.log.error( self.name + ": EOF exception found" )
1387 main.log.error( self.name + ": " + self.handle.before )
andrewonlabe6745342014-10-17 14:29:13 -04001388 main.cleanup()
1389 main.exit()
1390 except:
Jon Halld4d4b372015-01-28 16:02:41 -08001391 main.log.exception( self.name + ": Uncaught exception!" )
andrewonlabe6745342014-10-17 14:29:13 -04001392 main.cleanup()
1393 main.exit()
1394
kelvin-onlab54400a92015-02-26 18:05:51 -08001395 def getIntentState(self, intentsId, intentsJson=None):
1396 """
kelvin-onlab54400a92015-02-26 18:05:51 -08001397 Check intent state.
1398 Accepts a single intent ID (string type) or a list of intent IDs.
1399 Returns the state(string type) of the id if a single intent ID is
1400 accepted.
1401 Returns a dictionary with intent IDs as the key and its corresponding
1402 states as the values
kelvin-onlabfb521662015-02-27 09:52:40 -08001403 Parameters:
kelvin-onlab54400a92015-02-26 18:05:51 -08001404 intentId: intent ID (string type)
1405 intentsJson: parsed json object from the onos:intents api
1406 Returns:
1407 state = An intent's state- INSTALL,WITHDRAWN etc.
1408 stateDict = Dictionary of intent's state. intent ID as the keys and
1409 state as the values.
1410 """
kelvin-onlab54400a92015-02-26 18:05:51 -08001411 try:
1412 state = "State is Undefined"
1413 if not intentsJson:
1414 intentsJsonTemp = json.loads(self.intents())
1415 else:
1416 intentsJsonTemp = json.loads(intentsJson)
1417 if isinstance(intentsId,types.StringType):
1418 for intent in intentsJsonTemp:
1419 if intentsId == intent['id']:
1420 state = intent['state']
1421 return state
1422 main.log.info("Cannot find intent ID" + str(intentsId) +" on the list")
1423 return state
1424 elif isinstance(intentsId,types.ListType):
kelvin-onlab07dbd012015-03-04 16:29:39 -08001425 dictList = []
kelvin-onlab54400a92015-02-26 18:05:51 -08001426 for ID in intentsId:
kelvin-onlab07dbd012015-03-04 16:29:39 -08001427 stateDict = {}
kelvin-onlab54400a92015-02-26 18:05:51 -08001428 for intents in intentsJsonTemp:
1429 if ID == intents['id']:
kelvin-onlab07dbd012015-03-04 16:29:39 -08001430 stateDict['state'] = intents['state']
1431 stateDict['id'] = ID
1432 dictList.append(stateDict)
kelvin-onlab54400a92015-02-26 18:05:51 -08001433 break
kelvin-onlab07dbd012015-03-04 16:29:39 -08001434 if len(intentsId) != len(dictList):
kelvin-onlab54400a92015-02-26 18:05:51 -08001435 main.log.info("Cannot find some of the intent ID state")
kelvin-onlab07dbd012015-03-04 16:29:39 -08001436 return dictList
kelvin-onlab54400a92015-02-26 18:05:51 -08001437 else:
1438 main.log.info("Invalid intents ID entry")
1439 return None
1440 main.log.info("Something went wrong getting intent ID state")
1441 return None
1442 except TypeError:
1443 main.log.exception( self.name + ": Object not as expected" )
1444 return None
1445 except pexpect.EOF:
1446 main.log.error( self.name + ": EOF exception found" )
1447 main.log.error( self.name + ": " + self.handle.before )
1448 main.cleanup()
1449 main.exit()
1450 except:
1451 main.log.exception( self.name + ": Uncaught exception!" )
1452 main.cleanup()
1453 main.exit()
Jon Hall30b82fa2015-03-04 17:15:43 -08001454
kelvin-onlabd3b64892015-01-20 13:26:24 -08001455 def flows( self, jsonFormat=True ):
kelvin8ec71442015-01-15 16:57:00 -08001456 """
Shreya Shah0f01c812014-10-26 20:15:28 -04001457 Optional:
kelvin-onlabd3b64892015-01-20 13:26:24 -08001458 * jsonFormat: enable output formatting in json
Shreya Shah0f01c812014-10-26 20:15:28 -04001459 Description:
Jon Halle3f39ff2015-01-13 11:50:53 -08001460 Obtain flows currently installed
kelvin-onlab898a6c62015-01-16 14:13:53 -08001461 """
Shreya Shah0f01c812014-10-26 20:15:28 -04001462 try:
kelvin-onlabd3b64892015-01-20 13:26:24 -08001463 if jsonFormat:
1464 cmdStr = "flows -j"
1465 handle = self.sendline( cmdStr )
1466 ansiEscape = re.compile( r'\r\r\n\x1b[^m]*m' )
1467 handle = ansiEscape.sub( '', handle )
Shreya Shah0f01c812014-10-26 20:15:28 -04001468 else:
kelvin-onlabd3b64892015-01-20 13:26:24 -08001469 cmdStr = "flows"
1470 handle = self.sendline( cmdStr )
kelvin8ec71442015-01-15 16:57:00 -08001471 if re.search( "Error\sexecuting\scommand:", handle ):
kelvin-onlab898a6c62015-01-16 14:13:53 -08001472 main.log.error( self.name + ".flows() response: " +
1473 str( handle ) )
Shreya Shah0f01c812014-10-26 20:15:28 -04001474 return handle
Jon Halld4d4b372015-01-28 16:02:41 -08001475 except TypeError:
1476 main.log.exception( self.name + ": Object not as expected" )
1477 return None
Shreya Shah0f01c812014-10-26 20:15:28 -04001478 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08001479 main.log.error( self.name + ": EOF exception found" )
1480 main.log.error( self.name + ": " + self.handle.before )
Shreya Shah0f01c812014-10-26 20:15:28 -04001481 main.cleanup()
1482 main.exit()
1483 except:
Jon Halld4d4b372015-01-28 16:02:41 -08001484 main.log.exception( self.name + ": Uncaught exception!" )
Shreya Shah0f01c812014-10-26 20:15:28 -04001485 main.cleanup()
1486 main.exit()
1487
kelvin-onlabd3b64892015-01-20 13:26:24 -08001488 def pushTestIntents( self, dpidSrc, dpidDst, numIntents,
1489 numMult="", appId="", report=True ):
kelvin8ec71442015-01-15 16:57:00 -08001490 """
andrewonlab87852b02014-11-19 18:44:19 -05001491 Description:
Jon Halle3f39ff2015-01-13 11:50:53 -08001492 Push a number of intents in a batch format to
andrewonlab87852b02014-11-19 18:44:19 -05001493 a specific point-to-point intent definition
1494 Required:
kelvin-onlabd3b64892015-01-20 13:26:24 -08001495 * dpidSrc: specify source dpid
1496 * dpidDst: specify destination dpid
1497 * numIntents: specify number of intents to push
andrewonlab87852b02014-11-19 18:44:19 -05001498 Optional:
kelvin-onlabd3b64892015-01-20 13:26:24 -08001499 * numMult: number multiplier for multiplying
andrewonlabb66dfa12014-12-02 15:51:10 -05001500 the number of intents specified
kelvin-onlabd3b64892015-01-20 13:26:24 -08001501 * appId: specify the application id init to further
andrewonlabb66dfa12014-12-02 15:51:10 -05001502 modularize the intents
andrewonlab87852b02014-11-19 18:44:19 -05001503 * report: default True, returns latency information
kelvin8ec71442015-01-15 16:57:00 -08001504 """
andrewonlab87852b02014-11-19 18:44:19 -05001505 try:
kelvin8ec71442015-01-15 16:57:00 -08001506 cmd = "push-test-intents " +\
kelvin-onlabd3b64892015-01-20 13:26:24 -08001507 str( dpidSrc ) + " " + str( dpidDst ) + " " +\
1508 str( numIntents )
1509 if numMult:
1510 cmd += " " + str( numMult )
1511 # If app id is specified, then numMult
kelvin8ec71442015-01-15 16:57:00 -08001512 # must exist because of the way this command
kelvin-onlabd3b64892015-01-20 13:26:24 -08001513 if appId:
1514 cmd += " " + str( appId )
kelvin-onlab898a6c62015-01-16 14:13:53 -08001515 handle = self.sendline( cmd )
kelvin-onlabd3b64892015-01-20 13:26:24 -08001516 ansiEscape = re.compile( r'\r\r\n\x1b[^m]*m' )
1517 handle = ansiEscape.sub( '', handle )
andrewonlab87852b02014-11-19 18:44:19 -05001518 if report:
kelvin-onlabd3b64892015-01-20 13:26:24 -08001519 latResult = []
kelvin8ec71442015-01-15 16:57:00 -08001520 main.log.info( handle )
1521 # Split result by newline
1522 newline = handle.split( "\r\r\n" )
1523 # Ignore the first object of list, which is empty
1524 newline = newline[ 1: ]
1525 # Some sloppy parsing method to get the latency
andrewonlabb66dfa12014-12-02 15:51:10 -05001526 for result in newline:
kelvin8ec71442015-01-15 16:57:00 -08001527 result = result.split( ": " )
1528 # Append the first result of second parse
kelvin-onlabd3b64892015-01-20 13:26:24 -08001529 latResult.append( result[ 1 ].split( " " )[ 0 ] )
1530 main.log.info( latResult )
1531 return latResult
andrewonlab87852b02014-11-19 18:44:19 -05001532 else:
1533 return main.TRUE
Jon Halld4d4b372015-01-28 16:02:41 -08001534 except TypeError:
1535 main.log.exception( self.name + ": Object not as expected" )
1536 return None
andrewonlab87852b02014-11-19 18:44:19 -05001537 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08001538 main.log.error( self.name + ": EOF exception found" )
1539 main.log.error( self.name + ": " + self.handle.before )
andrewonlab87852b02014-11-19 18:44:19 -05001540 main.cleanup()
1541 main.exit()
1542 except:
Jon Halld4d4b372015-01-28 16:02:41 -08001543 main.log.exception( self.name + ": Uncaught exception!" )
andrewonlab87852b02014-11-19 18:44:19 -05001544 main.cleanup()
1545 main.exit()
1546
kelvin-onlabd3b64892015-01-20 13:26:24 -08001547 def intentsEventsMetrics( self, jsonFormat=True ):
kelvin8ec71442015-01-15 16:57:00 -08001548 """
Jon Halle3f39ff2015-01-13 11:50:53 -08001549 Description:Returns topology metrics
andrewonlab0dbb6ec2014-11-06 13:46:55 -05001550 Optional:
kelvin-onlabd3b64892015-01-20 13:26:24 -08001551 * jsonFormat: enable json formatting of output
kelvin8ec71442015-01-15 16:57:00 -08001552 """
andrewonlab0dbb6ec2014-11-06 13:46:55 -05001553 try:
kelvin-onlabd3b64892015-01-20 13:26:24 -08001554 if jsonFormat:
1555 cmdStr = "intents-events-metrics -j"
1556 handle = self.sendline( cmdStr )
Jon Halle3f39ff2015-01-13 11:50:53 -08001557 # Some color thing that we want to escape
kelvin-onlabd3b64892015-01-20 13:26:24 -08001558 ansiEscape = re.compile( r'\r\r\n\x1b[^m]*m' )
1559 handle = ansiEscape.sub( '', handle )
andrewonlab0dbb6ec2014-11-06 13:46:55 -05001560 else:
kelvin-onlabd3b64892015-01-20 13:26:24 -08001561 cmdStr = "intents-events-metrics"
1562 handle = self.sendline( cmdStr )
andrewonlab0dbb6ec2014-11-06 13:46:55 -05001563 return handle
Jon Halld4d4b372015-01-28 16:02:41 -08001564 except TypeError:
1565 main.log.exception( self.name + ": Object not as expected" )
1566 return None
andrewonlab0dbb6ec2014-11-06 13:46:55 -05001567 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08001568 main.log.error( self.name + ": EOF exception found" )
1569 main.log.error( self.name + ": " + self.handle.before )
andrewonlab0dbb6ec2014-11-06 13:46:55 -05001570 main.cleanup()
1571 main.exit()
1572 except:
Jon Halld4d4b372015-01-28 16:02:41 -08001573 main.log.exception( self.name + ": Uncaught exception!" )
andrewonlab0dbb6ec2014-11-06 13:46:55 -05001574 main.cleanup()
1575 main.exit()
Shreya Shah0f01c812014-10-26 20:15:28 -04001576
kelvin-onlabd3b64892015-01-20 13:26:24 -08001577 def topologyEventsMetrics( self, jsonFormat=True ):
kelvin8ec71442015-01-15 16:57:00 -08001578 """
1579 Description:Returns topology metrics
andrewonlab867212a2014-10-22 20:13:38 -04001580 Optional:
kelvin-onlabd3b64892015-01-20 13:26:24 -08001581 * jsonFormat: enable json formatting of output
kelvin8ec71442015-01-15 16:57:00 -08001582 """
andrewonlab867212a2014-10-22 20:13:38 -04001583 try:
kelvin-onlabd3b64892015-01-20 13:26:24 -08001584 if jsonFormat:
1585 cmdStr = "topology-events-metrics -j"
1586 handle = self.sendline( cmdStr )
kelvin-onlab898a6c62015-01-16 14:13:53 -08001587 # Some color thing that we want to escape
kelvin-onlabd3b64892015-01-20 13:26:24 -08001588 ansiEscape = re.compile( r'\r\r\n\x1b[^m]*m' )
1589 handle = ansiEscape.sub( '', handle )
andrewonlab867212a2014-10-22 20:13:38 -04001590 else:
kelvin-onlabd3b64892015-01-20 13:26:24 -08001591 cmdStr = "topology-events-metrics"
1592 handle = self.sendline( cmdStr )
andrewonlab867212a2014-10-22 20:13:38 -04001593 return handle
Jon Halld4d4b372015-01-28 16:02:41 -08001594 except TypeError:
1595 main.log.exception( self.name + ": Object not as expected" )
1596 return None
andrewonlab867212a2014-10-22 20:13:38 -04001597 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08001598 main.log.error( self.name + ": EOF exception found" )
1599 main.log.error( self.name + ": " + self.handle.before )
andrewonlab867212a2014-10-22 20:13:38 -04001600 main.cleanup()
1601 main.exit()
1602 except:
Jon Halld4d4b372015-01-28 16:02:41 -08001603 main.log.exception( self.name + ": Uncaught exception!" )
andrewonlab867212a2014-10-22 20:13:38 -04001604 main.cleanup()
1605 main.exit()
1606
kelvin8ec71442015-01-15 16:57:00 -08001607 # Wrapper functions ****************
1608 # Wrapper functions use existing driver
1609 # functions and extends their use case.
1610 # For example, we may use the output of
1611 # a normal driver function, and parse it
1612 # using a wrapper function
andrewonlabc2d05aa2014-10-13 16:51:10 -04001613
kelvin-onlabd3b64892015-01-20 13:26:24 -08001614 def getAllIntentsId( self ):
kelvin8ec71442015-01-15 16:57:00 -08001615 """
andrewonlab9a50dfe2014-10-17 17:22:31 -04001616 Description:
1617 Obtain all intent id's in a list
kelvin8ec71442015-01-15 16:57:00 -08001618 """
andrewonlab9a50dfe2014-10-17 17:22:31 -04001619 try:
kelvin8ec71442015-01-15 16:57:00 -08001620 # Obtain output of intents function
kelvin-onlabfb521662015-02-27 09:52:40 -08001621 intentsStr = self.intents(jsonFormat=False)
kelvin-onlabd3b64892015-01-20 13:26:24 -08001622 intentIdList = []
andrewonlab9a50dfe2014-10-17 17:22:31 -04001623
kelvin8ec71442015-01-15 16:57:00 -08001624 # Parse the intents output for ID's
kelvin-onlabd3b64892015-01-20 13:26:24 -08001625 intentsList = [ s.strip() for s in intentsStr.splitlines() ]
1626 for intents in intentsList:
kelvin-onlabfb521662015-02-27 09:52:40 -08001627 match = re.search('id=0x([\da-f]+),', intents)
1628 if match:
1629 tmpId = match.group()[3:-1]
1630 intentIdList.append( tmpId )
kelvin-onlabd3b64892015-01-20 13:26:24 -08001631 return intentIdList
andrewonlab9a50dfe2014-10-17 17:22:31 -04001632
Jon Halld4d4b372015-01-28 16:02:41 -08001633 except TypeError:
1634 main.log.exception( self.name + ": Object not as expected" )
1635 return None
andrewonlab9a50dfe2014-10-17 17:22:31 -04001636 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08001637 main.log.error( self.name + ": EOF exception found" )
1638 main.log.error( self.name + ": " + self.handle.before )
andrewonlab9a50dfe2014-10-17 17:22:31 -04001639 main.cleanup()
1640 main.exit()
1641 except:
Jon Halld4d4b372015-01-28 16:02:41 -08001642 main.log.exception( self.name + ": Uncaught exception!" )
andrewonlab9a50dfe2014-10-17 17:22:31 -04001643 main.cleanup()
1644 main.exit()
1645
Jon Hall30b82fa2015-03-04 17:15:43 -08001646 def FlowAddedCount( self, deviceId ):
1647 """
1648 Determine the number of flow rules for the given device id that are
1649 in the added state
1650 """
1651 try:
1652 cmdStr = "flows any " + str( deviceId ) + " | " +\
1653 "grep 'state=ADDED' | wc -l"
1654 handle = self.sendline( cmdStr )
1655 return handle
1656 except pexpect.EOF:
1657 main.log.error( self.name + ": EOF exception found" )
1658 main.log.error( self.name + ": " + self.handle.before )
1659 main.cleanup()
1660 main.exit()
1661 except:
1662 main.log.exception( self.name + ": Uncaught exception!" )
1663 main.cleanup()
1664 main.exit()
1665
kelvin-onlabd3b64892015-01-20 13:26:24 -08001666 def getAllDevicesId( self ):
kelvin8ec71442015-01-15 16:57:00 -08001667 """
andrewonlab7e4d2d32014-10-15 13:23:21 -04001668 Use 'devices' function to obtain list of all devices
1669 and parse the result to obtain a list of all device
1670 id's. Returns this list. Returns empty list if no
1671 devices exist
kelvin8ec71442015-01-15 16:57:00 -08001672 List is ordered sequentially
1673
andrewonlab3e15ead2014-10-15 14:21:34 -04001674 This function may be useful if you are not sure of the
kelvin8ec71442015-01-15 16:57:00 -08001675 device id, and wish to execute other commands using
andrewonlab3e15ead2014-10-15 14:21:34 -04001676 the ids. By obtaining the list of device ids on the fly,
1677 you can iterate through the list to get mastership, etc.
kelvin8ec71442015-01-15 16:57:00 -08001678 """
andrewonlab7e4d2d32014-10-15 13:23:21 -04001679 try:
kelvin8ec71442015-01-15 16:57:00 -08001680 # Call devices and store result string
kelvin-onlabd3b64892015-01-20 13:26:24 -08001681 devicesStr = self.devices( jsonFormat=False )
1682 idList = []
kelvin8ec71442015-01-15 16:57:00 -08001683
kelvin-onlabd3b64892015-01-20 13:26:24 -08001684 if not devicesStr:
kelvin8ec71442015-01-15 16:57:00 -08001685 main.log.info( "There are no devices to get id from" )
kelvin-onlabd3b64892015-01-20 13:26:24 -08001686 return idList
kelvin8ec71442015-01-15 16:57:00 -08001687
1688 # Split the string into list by comma
kelvin-onlabd3b64892015-01-20 13:26:24 -08001689 deviceList = devicesStr.split( "," )
kelvin8ec71442015-01-15 16:57:00 -08001690 # Get temporary list of all arguments with string 'id='
kelvin-onlabd3b64892015-01-20 13:26:24 -08001691 tempList = [ dev for dev in deviceList if "id=" in dev ]
kelvin8ec71442015-01-15 16:57:00 -08001692 # Split list further into arguments before and after string
1693 # 'id='. Get the latter portion ( the actual device id ) and
kelvin-onlabd3b64892015-01-20 13:26:24 -08001694 # append to idList
1695 for arg in tempList:
1696 idList.append( arg.split( "id=" )[ 1 ] )
1697 return idList
andrewonlab7e4d2d32014-10-15 13:23:21 -04001698
Jon Halld4d4b372015-01-28 16:02:41 -08001699 except TypeError:
1700 main.log.exception( self.name + ": Object not as expected" )
1701 return None
andrewonlab7e4d2d32014-10-15 13:23:21 -04001702 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08001703 main.log.error( self.name + ": EOF exception found" )
1704 main.log.error( self.name + ": " + self.handle.before )
andrewonlab7e4d2d32014-10-15 13:23:21 -04001705 main.cleanup()
1706 main.exit()
1707 except:
Jon Halld4d4b372015-01-28 16:02:41 -08001708 main.log.exception( self.name + ": Uncaught exception!" )
andrewonlab7e4d2d32014-10-15 13:23:21 -04001709 main.cleanup()
1710 main.exit()
1711
kelvin-onlabd3b64892015-01-20 13:26:24 -08001712 def getAllNodesId( self ):
kelvin8ec71442015-01-15 16:57:00 -08001713 """
andrewonlab7c211572014-10-15 16:45:20 -04001714 Uses 'nodes' function to obtain list of all nodes
1715 and parse the result of nodes to obtain just the
kelvin8ec71442015-01-15 16:57:00 -08001716 node id's.
andrewonlab7c211572014-10-15 16:45:20 -04001717 Returns:
1718 list of node id's
kelvin8ec71442015-01-15 16:57:00 -08001719 """
andrewonlab7c211572014-10-15 16:45:20 -04001720 try:
kelvin-onlabd3b64892015-01-20 13:26:24 -08001721 nodesStr = self.nodes()
1722 idList = []
andrewonlab7c211572014-10-15 16:45:20 -04001723
kelvin-onlabd3b64892015-01-20 13:26:24 -08001724 if not nodesStr:
kelvin8ec71442015-01-15 16:57:00 -08001725 main.log.info( "There are no nodes to get id from" )
kelvin-onlabd3b64892015-01-20 13:26:24 -08001726 return idList
andrewonlab7c211572014-10-15 16:45:20 -04001727
kelvin-onlabd3b64892015-01-20 13:26:24 -08001728 # Sample nodesStr output
kelvin8ec71442015-01-15 16:57:00 -08001729 # id=local, address=127.0.0.1:9876, state=ACTIVE *
andrewonlab7c211572014-10-15 16:45:20 -04001730
kelvin8ec71442015-01-15 16:57:00 -08001731 # Split the string into list by comma
kelvin-onlabd3b64892015-01-20 13:26:24 -08001732 nodesList = nodesStr.split( "," )
1733 tempList = [ node for node in nodesList if "id=" in node ]
1734 for arg in tempList:
1735 idList.append( arg.split( "id=" )[ 1 ] )
andrewonlab7c211572014-10-15 16:45:20 -04001736
kelvin-onlabd3b64892015-01-20 13:26:24 -08001737 return idList
kelvin8ec71442015-01-15 16:57:00 -08001738
Jon Halld4d4b372015-01-28 16:02:41 -08001739 except TypeError:
1740 main.log.exception( self.name + ": Object not as expected" )
1741 return None
andrewonlab7c211572014-10-15 16:45:20 -04001742 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08001743 main.log.error( self.name + ": EOF exception found" )
1744 main.log.error( self.name + ": " + self.handle.before )
andrewonlab7c211572014-10-15 16:45:20 -04001745 main.cleanup()
1746 main.exit()
1747 except:
Jon Halld4d4b372015-01-28 16:02:41 -08001748 main.log.exception( self.name + ": Uncaught exception!" )
andrewonlab7c211572014-10-15 16:45:20 -04001749 main.cleanup()
1750 main.exit()
andrewonlab7e4d2d32014-10-15 13:23:21 -04001751
kelvin-onlabd3b64892015-01-20 13:26:24 -08001752 def getDevice( self, dpid=None ):
kelvin8ec71442015-01-15 16:57:00 -08001753 """
Jon Halla91c4dc2014-10-22 12:57:04 -04001754 Return the first device from the devices api whose 'id' contains 'dpid'
1755 Return None if there is no match
kelvin8ec71442015-01-15 16:57:00 -08001756 """
Jon Halla91c4dc2014-10-22 12:57:04 -04001757 try:
kelvin8ec71442015-01-15 16:57:00 -08001758 if dpid is None:
Jon Halla91c4dc2014-10-22 12:57:04 -04001759 return None
1760 else:
kelvin8ec71442015-01-15 16:57:00 -08001761 dpid = dpid.replace( ':', '' )
kelvin-onlabd3b64892015-01-20 13:26:24 -08001762 rawDevices = self.devices()
1763 devicesJson = json.loads( rawDevices )
kelvin8ec71442015-01-15 16:57:00 -08001764 # search json for the device with dpid then return the device
kelvin-onlabd3b64892015-01-20 13:26:24 -08001765 for device in devicesJson:
kelvin8ec71442015-01-15 16:57:00 -08001766 # print "%s in %s?" % ( dpid, device[ 'id' ] )
1767 if dpid in device[ 'id' ]:
Jon Halla91c4dc2014-10-22 12:57:04 -04001768 return device
1769 return None
Jon Halld4d4b372015-01-28 16:02:41 -08001770 except TypeError:
1771 main.log.exception( self.name + ": Object not as expected" )
1772 return None
Jon Halla91c4dc2014-10-22 12:57:04 -04001773 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08001774 main.log.error( self.name + ": EOF exception found" )
1775 main.log.error( self.name + ": " + self.handle.before )
Jon Halla91c4dc2014-10-22 12:57:04 -04001776 main.cleanup()
1777 main.exit()
1778 except:
Jon Halld4d4b372015-01-28 16:02:41 -08001779 main.log.exception( self.name + ": Uncaught exception!" )
Jon Halla91c4dc2014-10-22 12:57:04 -04001780 main.cleanup()
1781 main.exit()
1782
kelvin-onlabd3b64892015-01-20 13:26:24 -08001783 def checkStatus( self, ip, numoswitch, numolink, logLevel="info" ):
kelvin8ec71442015-01-15 16:57:00 -08001784 """
1785 Checks the number of swithes & links that ONOS sees against the
1786 supplied values. By default this will report to main.log, but the
Jon Hall42db6dc2014-10-24 19:03:48 -04001787 log level can be specifid.
kelvin8ec71442015-01-15 16:57:00 -08001788
Jon Hall42db6dc2014-10-24 19:03:48 -04001789 Params: ip = ip used for the onos cli
1790 numoswitch = expected number of switches
1791 numlink = expected number of links
kelvin-onlabd3b64892015-01-20 13:26:24 -08001792 logLevel = level to log to. Currently accepts
1793 'info', 'warn' and 'report'
Jon Hall42db6dc2014-10-24 19:03:48 -04001794
1795
kelvin-onlabd3b64892015-01-20 13:26:24 -08001796 logLevel can
Jon Hall42db6dc2014-10-24 19:03:48 -04001797
kelvin8ec71442015-01-15 16:57:00 -08001798 Returns: main.TRUE if the number of switchs and links are correct,
Jon Hall42db6dc2014-10-24 19:03:48 -04001799 main.FALSE if the numer of switches and links is incorrect,
1800 and main.ERROR otherwise
kelvin8ec71442015-01-15 16:57:00 -08001801 """
Jon Hall42db6dc2014-10-24 19:03:48 -04001802 try:
kelvin-onlabd3b64892015-01-20 13:26:24 -08001803 topology = self.getTopology( ip )
Jon Hall42db6dc2014-10-24 19:03:48 -04001804 if topology == {}:
1805 return main.ERROR
1806 output = ""
kelvin8ec71442015-01-15 16:57:00 -08001807 # Is the number of switches is what we expected
1808 devices = topology.get( 'devices', False )
1809 links = topology.get( 'links', False )
kelvin-onlabfb521662015-02-27 09:52:40 -08001810 if devices is False or links is False:
Jon Hall42db6dc2014-10-24 19:03:48 -04001811 return main.ERROR
kelvin-onlabd3b64892015-01-20 13:26:24 -08001812 switchCheck = ( int( devices ) == int( numoswitch ) )
kelvin8ec71442015-01-15 16:57:00 -08001813 # Is the number of links is what we expected
kelvin-onlabd3b64892015-01-20 13:26:24 -08001814 linkCheck = ( int( links ) == int( numolink ) )
1815 if ( switchCheck and linkCheck ):
kelvin8ec71442015-01-15 16:57:00 -08001816 # We expected the correct numbers
Jon Hall42db6dc2014-10-24 19:03:48 -04001817 output = output + "The number of links and switches match "\
kelvin8ec71442015-01-15 16:57:00 -08001818 + "what was expected"
Jon Hall42db6dc2014-10-24 19:03:48 -04001819 result = main.TRUE
1820 else:
1821 output = output + \
kelvin-onlabd3b64892015-01-20 13:26:24 -08001822 "The number of links and switches does not matc\
1823 h what was expected"
Jon Hall42db6dc2014-10-24 19:03:48 -04001824 result = main.FALSE
kelvin-onlabd3b64892015-01-20 13:26:24 -08001825 output = output + "\n ONOS sees %i devices (%i expected) \
1826 and %i links (%i expected)" % (
1827 int( devices ), int( numoswitch ), int( links ),
1828 int( numolink ) )
1829 if logLevel == "report":
kelvin8ec71442015-01-15 16:57:00 -08001830 main.log.report( output )
kelvin-onlabd3b64892015-01-20 13:26:24 -08001831 elif logLevel == "warn":
kelvin8ec71442015-01-15 16:57:00 -08001832 main.log.warn( output )
Jon Hall42db6dc2014-10-24 19:03:48 -04001833 else:
kelvin8ec71442015-01-15 16:57:00 -08001834 main.log.info( output )
1835 return result
Jon Halld4d4b372015-01-28 16:02:41 -08001836 except TypeError:
1837 main.log.exception( self.name + ": Object not as expected" )
1838 return None
Jon Hall42db6dc2014-10-24 19:03:48 -04001839 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08001840 main.log.error( self.name + ": EOF exception found" )
1841 main.log.error( self.name + ": " + self.handle.before )
Jon Hall42db6dc2014-10-24 19:03:48 -04001842 main.cleanup()
1843 main.exit()
1844 except:
Jon Halld4d4b372015-01-28 16:02:41 -08001845 main.log.exception( self.name + ": Uncaught exception!" )
Jon Hall42db6dc2014-10-24 19:03:48 -04001846 main.cleanup()
1847 main.exit()
Jon Hall1c9e8732014-10-27 19:29:27 -04001848
kelvin-onlabd3b64892015-01-20 13:26:24 -08001849 def deviceRole( self, deviceId, onosNode, role="master" ):
kelvin8ec71442015-01-15 16:57:00 -08001850 """
Jon Hall1c9e8732014-10-27 19:29:27 -04001851 Calls the device-role cli command.
kelvin-onlabd3b64892015-01-20 13:26:24 -08001852 deviceId must be the id of a device as seen in the onos devices command
1853 onosNode is the ip of one of the onos nodes in the cluster
Jon Hall1c9e8732014-10-27 19:29:27 -04001854 role must be either master, standby, or none
1855
Jon Halle3f39ff2015-01-13 11:50:53 -08001856 Returns:
1857 main.TRUE or main.FALSE based on argument verification and
1858 main.ERROR if command returns and error
kelvin-onlab898a6c62015-01-16 14:13:53 -08001859 """
Jon Hall1c9e8732014-10-27 19:29:27 -04001860 try:
Jon Halle3f39ff2015-01-13 11:50:53 -08001861 if role.lower() == "master" or role.lower() == "standby" or\
Jon Hall1c9e8732014-10-27 19:29:27 -04001862 role.lower() == "none":
kelvin-onlabd3b64892015-01-20 13:26:24 -08001863 cmdStr = "device-role " +\
1864 str( deviceId ) + " " +\
1865 str( onosNode ) + " " +\
kelvin-onlab898a6c62015-01-16 14:13:53 -08001866 str( role )
kelvin-onlabd3b64892015-01-20 13:26:24 -08001867 handle = self.sendline( cmdStr )
kelvin-onlab898a6c62015-01-16 14:13:53 -08001868 if re.search( "Error", handle ):
1869 # end color output to escape any colours
1870 # from the cli
kelvin8ec71442015-01-15 16:57:00 -08001871 main.log.error( self.name + ": " +
kelvin-onlab898a6c62015-01-16 14:13:53 -08001872 handle + '\033[0m' )
kelvin8ec71442015-01-15 16:57:00 -08001873 return main.ERROR
kelvin8ec71442015-01-15 16:57:00 -08001874 return main.TRUE
Jon Hall1c9e8732014-10-27 19:29:27 -04001875 else:
kelvin-onlab898a6c62015-01-16 14:13:53 -08001876 main.log.error( "Invalid 'role' given to device_role(). " +
1877 "Value was '" + str(role) + "'." )
Jon Hall1c9e8732014-10-27 19:29:27 -04001878 return main.FALSE
Jon Halld4d4b372015-01-28 16:02:41 -08001879 except TypeError:
1880 main.log.exception( self.name + ": Object not as expected" )
1881 return None
Jon Hall1c9e8732014-10-27 19:29:27 -04001882 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08001883 main.log.error( self.name + ": EOF exception found" )
1884 main.log.error( self.name + ": " + self.handle.before )
Jon Hall1c9e8732014-10-27 19:29:27 -04001885 main.cleanup()
1886 main.exit()
1887 except:
Jon Halld4d4b372015-01-28 16:02:41 -08001888 main.log.exception( self.name + ": Uncaught exception!" )
Jon Hall1c9e8732014-10-27 19:29:27 -04001889 main.cleanup()
1890 main.exit()
1891
kelvin-onlabd3b64892015-01-20 13:26:24 -08001892 def clusters( self, jsonFormat=True ):
kelvin8ec71442015-01-15 16:57:00 -08001893 """
Jon Hall73cf9cc2014-11-20 22:28:38 -08001894 Lists all clusters
Jon Hallffb386d2014-11-21 13:43:38 -08001895 Optional argument:
kelvin-onlabd3b64892015-01-20 13:26:24 -08001896 * jsonFormat - boolean indicating if you want output in json
kelvin8ec71442015-01-15 16:57:00 -08001897 """
Jon Hall73cf9cc2014-11-20 22:28:38 -08001898 try:
kelvin-onlabd3b64892015-01-20 13:26:24 -08001899 if jsonFormat:
1900 cmdStr = "clusters -j"
1901 handle = self.sendline( cmdStr )
kelvin-onlab898a6c62015-01-16 14:13:53 -08001902 """
Jon Hall73cf9cc2014-11-20 22:28:38 -08001903 handle variable here contains some ANSI escape color code
1904 sequences at the end which are invisible in the print command
Jon Halle3f39ff2015-01-13 11:50:53 -08001905 output. To make that escape sequence visible, use repr()
kelvin-onlab898a6c62015-01-16 14:13:53 -08001906 function. The repr( handle ) output when printed shows the ANSI
1907 escape sequences. In json.loads( somestring ), this somestring
kelvin-onlabd3b64892015-01-20 13:26:24 -08001908 variable is actually repr( somestring ) and json.loads would
1909 fail with the escape sequence. So we take off that escape
1910 sequence using:
Jon Halle3f39ff2015-01-13 11:50:53 -08001911
kelvin-onlabd3b64892015-01-20 13:26:24 -08001912 ansiEscape = re.compile( r'\r\r\n\x1b[^m]*m' )
1913 handle1 = ansiEscape.sub( '', handle )
kelvin-onlab898a6c62015-01-16 14:13:53 -08001914 """
kelvin-onlabd3b64892015-01-20 13:26:24 -08001915 ansiEscape = re.compile( r'\r\r\n\x1b[^m]*m' )
1916 handle1 = ansiEscape.sub( '', handle )
Jon Hall73cf9cc2014-11-20 22:28:38 -08001917 return handle1
1918 else:
kelvin-onlabd3b64892015-01-20 13:26:24 -08001919 cmdStr = "clusters"
1920 handle = self.sendline( cmdStr )
Jon Hall73cf9cc2014-11-20 22:28:38 -08001921 return handle
Jon Halld4d4b372015-01-28 16:02:41 -08001922 except TypeError:
1923 main.log.exception( self.name + ": Object not as expected" )
1924 return None
Jon Hall73cf9cc2014-11-20 22:28:38 -08001925 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08001926 main.log.error( self.name + ": EOF exception found" )
1927 main.log.error( self.name + ": " + self.handle.before )
Jon Hall73cf9cc2014-11-20 22:28:38 -08001928 main.cleanup()
1929 main.exit()
1930 except:
Jon Halld4d4b372015-01-28 16:02:41 -08001931 main.log.exception( self.name + ": Uncaught exception!" )
Jon Hall73cf9cc2014-11-20 22:28:38 -08001932 main.cleanup()
1933 main.exit()
1934
kelvin-onlabd3b64892015-01-20 13:26:24 -08001935 def electionTestLeader( self ):
kelvin-onlab898a6c62015-01-16 14:13:53 -08001936 """
Jon Halle3f39ff2015-01-13 11:50:53 -08001937 CLI command to get the current leader for the Election test application
1938 NOTE: Requires installation of the onos-app-election feature
1939 Returns: Node IP of the leader if one exists
1940 None if none exists
1941 Main.FALSE on error
kelvin-onlab898a6c62015-01-16 14:13:53 -08001942 """
Jon Hall94fd0472014-12-08 11:52:42 -08001943 try:
kelvin-onlabd3b64892015-01-20 13:26:24 -08001944 cmdStr = "election-test-leader"
1945 response = self.sendline( cmdStr )
Jon Halle3f39ff2015-01-13 11:50:53 -08001946 # Leader
1947 leaderPattern = "The\scurrent\sleader\sfor\sthe\sElection\s" +\
kelvin-onlab898a6c62015-01-16 14:13:53 -08001948 "app\sis\s(?P<node>.+)\."
kelvin-onlabd3b64892015-01-20 13:26:24 -08001949 nodeSearch = re.search( leaderPattern, response )
1950 if nodeSearch:
1951 node = nodeSearch.group( 'node' )
Jon Halle3f39ff2015-01-13 11:50:53 -08001952 main.log.info( "Election-test-leader on " + str( self.name ) +
kelvin-onlab898a6c62015-01-16 14:13:53 -08001953 " found " + node + " as the leader" )
Jon Hall94fd0472014-12-08 11:52:42 -08001954 return node
Jon Halle3f39ff2015-01-13 11:50:53 -08001955 # no leader
1956 nullPattern = "There\sis\scurrently\sno\sleader\selected\sfor\s" +\
kelvin-onlab898a6c62015-01-16 14:13:53 -08001957 "the\sElection\sapp"
kelvin-onlabd3b64892015-01-20 13:26:24 -08001958 nullSearch = re.search( nullPattern, response )
1959 if nullSearch:
Jon Halle3f39ff2015-01-13 11:50:53 -08001960 main.log.info( "Election-test-leader found no leader on " +
kelvin-onlab898a6c62015-01-16 14:13:53 -08001961 self.name )
Jon Hall94fd0472014-12-08 11:52:42 -08001962 return None
kelvin-onlab898a6c62015-01-16 14:13:53 -08001963 # error
Jon Halle3f39ff2015-01-13 11:50:53 -08001964 errorPattern = "Command\snot\sfound"
kelvin-onlab898a6c62015-01-16 14:13:53 -08001965 if re.search( errorPattern, response ):
1966 main.log.error( "Election app is not loaded on " + self.name )
Jon Halle3f39ff2015-01-13 11:50:53 -08001967 # TODO: Should this be main.ERROR?
Jon Hall669173b2014-12-17 11:36:30 -08001968 return main.FALSE
1969 else:
kelvin-onlab898a6c62015-01-16 14:13:53 -08001970 main.log.error( "Error in election_test_leader: " +
1971 "unexpected response" )
kelvin8ec71442015-01-15 16:57:00 -08001972 main.log.error( repr( response ) )
Jon Hall669173b2014-12-17 11:36:30 -08001973 return main.FALSE
Jon Halld4d4b372015-01-28 16:02:41 -08001974 except TypeError:
1975 main.log.exception( self.name + ": Object not as expected" )
1976 return main.FALSE
Jon Hall94fd0472014-12-08 11:52:42 -08001977 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08001978 main.log.error( self.name + ": EOF exception found" )
1979 main.log.error( self.name + ": " + self.handle.before )
Jon Hall94fd0472014-12-08 11:52:42 -08001980 main.cleanup()
1981 main.exit()
1982 except:
Jon Halld4d4b372015-01-28 16:02:41 -08001983 main.log.exception( self.name + ": Uncaught exception!" )
Jon Hall94fd0472014-12-08 11:52:42 -08001984 main.cleanup()
1985 main.exit()
1986
kelvin-onlabd3b64892015-01-20 13:26:24 -08001987 def electionTestRun( self ):
kelvin-onlab898a6c62015-01-16 14:13:53 -08001988 """
Jon Halle3f39ff2015-01-13 11:50:53 -08001989 CLI command to run for leadership of the Election test application.
1990 NOTE: Requires installation of the onos-app-election feature
1991 Returns: Main.TRUE on success
1992 Main.FALSE on error
kelvin-onlab898a6c62015-01-16 14:13:53 -08001993 """
Jon Hall94fd0472014-12-08 11:52:42 -08001994 try:
kelvin-onlabd3b64892015-01-20 13:26:24 -08001995 cmdStr = "election-test-run"
1996 response = self.sendline( cmdStr )
kelvin-onlab898a6c62015-01-16 14:13:53 -08001997 # success
Jon Halle3f39ff2015-01-13 11:50:53 -08001998 successPattern = "Entering\sleadership\selections\sfor\sthe\s" +\
kelvin-onlab898a6c62015-01-16 14:13:53 -08001999 "Election\sapp."
Jon Halle3f39ff2015-01-13 11:50:53 -08002000 search = re.search( successPattern, response )
Jon Hall94fd0472014-12-08 11:52:42 -08002001 if search:
Jon Halle3f39ff2015-01-13 11:50:53 -08002002 main.log.info( self.name + " entering leadership elections " +
kelvin-onlab898a6c62015-01-16 14:13:53 -08002003 "for the Election app." )
Jon Hall94fd0472014-12-08 11:52:42 -08002004 return main.TRUE
kelvin-onlab898a6c62015-01-16 14:13:53 -08002005 # error
Jon Halle3f39ff2015-01-13 11:50:53 -08002006 errorPattern = "Command\snot\sfound"
2007 if re.search( errorPattern, response ):
2008 main.log.error( "Election app is not loaded on " + self.name )
Jon Hall669173b2014-12-17 11:36:30 -08002009 return main.FALSE
2010 else:
Jon Halle3f39ff2015-01-13 11:50:53 -08002011 main.log.error( "Error in election_test_run: " +
kelvin-onlab898a6c62015-01-16 14:13:53 -08002012 "unexpected response" )
Jon Halle3f39ff2015-01-13 11:50:53 -08002013 main.log.error( repr( response ) )
Jon Hall669173b2014-12-17 11:36:30 -08002014 return main.FALSE
Jon Halld4d4b372015-01-28 16:02:41 -08002015 except TypeError:
2016 main.log.exception( self.name + ": Object not as expected" )
2017 return main.FALSE
Jon Hall94fd0472014-12-08 11:52:42 -08002018 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08002019 main.log.error( self.name + ": EOF exception found" )
2020 main.log.error( self.name + ": " + self.handle.before )
Jon Hall94fd0472014-12-08 11:52:42 -08002021 main.cleanup()
2022 main.exit()
2023 except:
Jon Halld4d4b372015-01-28 16:02:41 -08002024 main.log.exception( self.name + ": Uncaught exception!" )
Jon Hall94fd0472014-12-08 11:52:42 -08002025 main.cleanup()
2026 main.exit()
2027
kelvin-onlabd3b64892015-01-20 13:26:24 -08002028 def electionTestWithdraw( self ):
kelvin8ec71442015-01-15 16:57:00 -08002029 """
Jon Hall94fd0472014-12-08 11:52:42 -08002030 * CLI command to withdraw the local node from leadership election for
2031 * the Election test application.
2032 #NOTE: Requires installation of the onos-app-election feature
2033 Returns: Main.TRUE on success
2034 Main.FALSE on error
kelvin8ec71442015-01-15 16:57:00 -08002035 """
Jon Hall94fd0472014-12-08 11:52:42 -08002036 try:
kelvin-onlabd3b64892015-01-20 13:26:24 -08002037 cmdStr = "election-test-withdraw"
2038 response = self.sendline( cmdStr )
kelvin-onlab898a6c62015-01-16 14:13:53 -08002039 # success
Jon Halle3f39ff2015-01-13 11:50:53 -08002040 successPattern = "Withdrawing\sfrom\sleadership\selections\sfor" +\
kelvin-onlab898a6c62015-01-16 14:13:53 -08002041 "\sthe\sElection\sapp."
Jon Halle3f39ff2015-01-13 11:50:53 -08002042 if re.search( successPattern, response ):
2043 main.log.info( self.name + " withdrawing from leadership " +
kelvin-onlab898a6c62015-01-16 14:13:53 -08002044 "elections for the Election app." )
Jon Hall94fd0472014-12-08 11:52:42 -08002045 return main.TRUE
kelvin-onlab898a6c62015-01-16 14:13:53 -08002046 # error
Jon Halle3f39ff2015-01-13 11:50:53 -08002047 errorPattern = "Command\snot\sfound"
2048 if re.search( errorPattern, response ):
2049 main.log.error( "Election app is not loaded on " + self.name )
Jon Hall669173b2014-12-17 11:36:30 -08002050 return main.FALSE
2051 else:
Jon Halle3f39ff2015-01-13 11:50:53 -08002052 main.log.error( "Error in election_test_withdraw: " +
kelvin-onlab898a6c62015-01-16 14:13:53 -08002053 "unexpected response" )
Jon Halle3f39ff2015-01-13 11:50:53 -08002054 main.log.error( repr( response ) )
Jon Hall669173b2014-12-17 11:36:30 -08002055 return main.FALSE
Jon Halld4d4b372015-01-28 16:02:41 -08002056 except TypeError:
2057 main.log.exception( self.name + ": Object not as expected" )
2058 return main.FALSE
Jon Hall94fd0472014-12-08 11:52:42 -08002059 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08002060 main.log.error( self.name + ": EOF exception found" )
2061 main.log.error( self.name + ": " + self.handle.before )
Jon Hall94fd0472014-12-08 11:52:42 -08002062 main.cleanup()
2063 main.exit()
2064 except:
Jon Halld4d4b372015-01-28 16:02:41 -08002065 main.log.exception( self.name + ": Uncaught exception!" )
Jon Hall94fd0472014-12-08 11:52:42 -08002066 main.cleanup()
2067 main.exit()
Jon Hall1c9e8732014-10-27 19:29:27 -04002068
kelvin8ec71442015-01-15 16:57:00 -08002069 def getDevicePortsEnabledCount( self, dpid ):
2070 """
Hari Krishnaa43d4e92014-12-19 13:22:40 -08002071 Get the count of all enabled ports on a particular device/switch
kelvin8ec71442015-01-15 16:57:00 -08002072 """
Hari Krishnaa43d4e92014-12-19 13:22:40 -08002073 try:
Jon Halle3f39ff2015-01-13 11:50:53 -08002074 dpid = str( dpid )
kelvin-onlabd3b64892015-01-20 13:26:24 -08002075 cmdStr = "onos:ports -e " + dpid + " | wc -l"
2076 output = self.sendline( cmdStr )
Jon Halle3f39ff2015-01-13 11:50:53 -08002077 if re.search( "No such device", output ):
2078 main.log.error( "Error in getting ports" )
2079 return ( output, "Error" )
Hari Krishnaa43d4e92014-12-19 13:22:40 -08002080 else:
Jon Halle3f39ff2015-01-13 11:50:53 -08002081 return output
Jon Halld4d4b372015-01-28 16:02:41 -08002082 except TypeError:
2083 main.log.exception( self.name + ": Object not as expected" )
2084 return ( output, "Error" )
Hari Krishnaa43d4e92014-12-19 13:22:40 -08002085 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08002086 main.log.error( self.name + ": EOF exception found" )
2087 main.log.error( self.name + ": " + self.handle.before )
Hari Krishnaa43d4e92014-12-19 13:22:40 -08002088 main.cleanup()
2089 main.exit()
2090 except:
Jon Halld4d4b372015-01-28 16:02:41 -08002091 main.log.exception( self.name + ": Uncaught exception!" )
Hari Krishnaa43d4e92014-12-19 13:22:40 -08002092 main.cleanup()
2093 main.exit()
2094
kelvin8ec71442015-01-15 16:57:00 -08002095 def getDeviceLinksActiveCount( self, dpid ):
2096 """
Hari Krishnaa43d4e92014-12-19 13:22:40 -08002097 Get the count of all enabled ports on a particular device/switch
kelvin8ec71442015-01-15 16:57:00 -08002098 """
Hari Krishnaa43d4e92014-12-19 13:22:40 -08002099 try:
kelvin-onlab898a6c62015-01-16 14:13:53 -08002100 dpid = str( dpid )
kelvin-onlabd3b64892015-01-20 13:26:24 -08002101 cmdStr = "onos:links " + dpid + " | grep ACTIVE | wc -l"
2102 output = self.sendline( cmdStr )
Jon Halle3f39ff2015-01-13 11:50:53 -08002103 if re.search( "No such device", output ):
kelvin-onlab898a6c62015-01-16 14:13:53 -08002104 main.log.error( "Error in getting ports " )
2105 return ( output, "Error " )
Hari Krishnaa43d4e92014-12-19 13:22:40 -08002106 else:
Jon Halle3f39ff2015-01-13 11:50:53 -08002107 return output
Jon Halld4d4b372015-01-28 16:02:41 -08002108 except TypeError:
2109 main.log.exception( self.name + ": Object not as expected" )
2110 return ( output, "Error " )
Hari Krishnaa43d4e92014-12-19 13:22:40 -08002111 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08002112 main.log.error( self.name + ": EOF exception found" )
2113 main.log.error( self.name + ": " + self.handle.before )
Hari Krishnaa43d4e92014-12-19 13:22:40 -08002114 main.cleanup()
2115 main.exit()
2116 except:
Jon Halld4d4b372015-01-28 16:02:41 -08002117 main.log.exception( self.name + ": Uncaught exception!" )
Hari Krishnaa43d4e92014-12-19 13:22:40 -08002118 main.cleanup()
2119 main.exit()
2120
kelvin8ec71442015-01-15 16:57:00 -08002121 def getAllIntentIds( self ):
2122 """
Hari Krishnaa43d4e92014-12-19 13:22:40 -08002123 Return a list of all Intent IDs
kelvin8ec71442015-01-15 16:57:00 -08002124 """
Hari Krishnaa43d4e92014-12-19 13:22:40 -08002125 try:
kelvin-onlabd3b64892015-01-20 13:26:24 -08002126 cmdStr = "onos:intents | grep id="
2127 output = self.sendline( cmdStr )
Jon Halle3f39ff2015-01-13 11:50:53 -08002128 if re.search( "Error", output ):
2129 main.log.error( "Error in getting ports" )
2130 return ( output, "Error" )
Hari Krishnaa43d4e92014-12-19 13:22:40 -08002131 else:
Jon Halle3f39ff2015-01-13 11:50:53 -08002132 return output
Jon Halld4d4b372015-01-28 16:02:41 -08002133 except TypeError:
2134 main.log.exception( self.name + ": Object not as expected" )
2135 return ( output, "Error" )
Hari Krishnaa43d4e92014-12-19 13:22:40 -08002136 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08002137 main.log.error( self.name + ": EOF exception found" )
2138 main.log.error( self.name + ": " + self.handle.before )
Hari Krishnaa43d4e92014-12-19 13:22:40 -08002139 main.cleanup()
2140 main.exit()
2141 except:
Jon Halld4d4b372015-01-28 16:02:41 -08002142 main.log.exception( self.name + ": Uncaught exception!" )
2143 main.cleanup()
2144 main.exit()
2145