blob: ec660ebef102f930f431650a6b036ec77819f90d [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
pingping-lin763ee042015-05-20 17:45:30 -070022import json
23import types
24import time
kelvin8ec71442015-01-15 16:57:00 -080025sys.path.append( "../" )
andrewonlab95ce8322014-10-13 14:12:04 -040026from drivers.common.clidriver import CLI
27
andrewonlab95ce8322014-10-13 14:12:04 -040028
kelvin8ec71442015-01-15 16:57:00 -080029class OnosCliDriver( CLI ):
andrewonlab95ce8322014-10-13 14:12:04 -040030
kelvin8ec71442015-01-15 16:57:00 -080031 def __init__( self ):
32 """
33 Initialize client
34 """
pingping-lin763ee042015-05-20 17:45:30 -070035 self.name = None
36 self.home = None
37 self.handle = None
kelvin8ec71442015-01-15 16:57:00 -080038 super( CLI, self ).__init__()
39
40 def connect( self, **connectargs ):
41 """
andrewonlab95ce8322014-10-13 14:12:04 -040042 Creates ssh handle for ONOS cli.
kelvin8ec71442015-01-15 16:57:00 -080043 """
andrewonlab95ce8322014-10-13 14:12:04 -040044 try:
45 for key in connectargs:
kelvin8ec71442015-01-15 16:57:00 -080046 vars( self )[ key ] = connectargs[ key ]
pingping-lin763ee042015-05-20 17:45:30 -070047 self.home = "~/onos"
andrewonlab95ce8322014-10-13 14:12:04 -040048 for key in self.options:
49 if key == "home":
kelvin8ec71442015-01-15 16:57:00 -080050 self.home = self.options[ 'home' ]
andrewonlab95ce8322014-10-13 14:12:04 -040051 break
pingping-lin763ee042015-05-20 17:45:30 -070052 if self.home is None or self.home == "":
53 self.home = "~/onos"
andrewonlab95ce8322014-10-13 14:12:04 -040054
kelvin8ec71442015-01-15 16:57:00 -080055 self.name = self.options[ 'name' ]
56 self.handle = super( OnosCliDriver, self ).connect(
kelvin-onlab08679eb2015-01-21 16:11:48 -080057 user_name=self.user_name,
58 ip_address=self.ip_address,
kelvin-onlab898a6c62015-01-16 14:13:53 -080059 port=self.port,
60 pwd=self.pwd,
61 home=self.home )
andrewonlab95ce8322014-10-13 14:12:04 -040062
kelvin8ec71442015-01-15 16:57:00 -080063 self.handle.sendline( "cd " + self.home )
64 self.handle.expect( "\$" )
andrewonlab95ce8322014-10-13 14:12:04 -040065 if self.handle:
66 return self.handle
kelvin8ec71442015-01-15 16:57:00 -080067 else:
68 main.log.info( "NO ONOS HANDLE" )
andrewonlab95ce8322014-10-13 14:12:04 -040069 return main.FALSE
pingping-lin763ee042015-05-20 17:45:30 -070070 except TypeError:
71 main.log.exception( self.name + ": Object not as expected" )
72 return None
andrewonlab95ce8322014-10-13 14:12:04 -040073 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -080074 main.log.error( self.name + ": EOF exception found" )
75 main.log.error( self.name + ": " + self.handle.before )
andrewonlab95ce8322014-10-13 14:12:04 -040076 main.cleanup()
77 main.exit()
pingping-lin763ee042015-05-20 17:45:30 -070078 except Exception:
79 main.log.exception( self.name + ": Uncaught exception!" )
andrewonlab95ce8322014-10-13 14:12:04 -040080 main.cleanup()
81 main.exit()
82
kelvin8ec71442015-01-15 16:57:00 -080083 def disconnect( self ):
84 """
andrewonlab95ce8322014-10-13 14:12:04 -040085 Called when Test is complete to disconnect the ONOS handle.
kelvin8ec71442015-01-15 16:57:00 -080086 """
pingping-lin763ee042015-05-20 17:45:30 -070087 response = main.TRUE
andrewonlab95ce8322014-10-13 14:12:04 -040088 try:
pingping-lin763ee042015-05-20 17:45:30 -070089 if self.handle:
90 i = self.logout()
91 if i == main.TRUE:
92 self.handle.sendline( "" )
93 self.handle.expect( "\$" )
94 self.handle.sendline( "exit" )
95 self.handle.expect( "closed" )
96 except TypeError:
97 main.log.exception( self.name + ": Object not as expected" )
98 response = main.FALSE
andrewonlab95ce8322014-10-13 14:12:04 -040099 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -0800100 main.log.error( self.name + ": EOF exception found" )
101 main.log.error( self.name + ": " + self.handle.before )
pingping-lin763ee042015-05-20 17:45:30 -0700102 except ValueError:
103 main.log.exception( "Exception in disconnect of " + self.name )
104 response = main.TRUE
105 except Exception:
106 main.log.exception( self.name + ": Connection failed to the host" )
andrewonlab95ce8322014-10-13 14:12:04 -0400107 response = main.FALSE
108 return response
109
kelvin8ec71442015-01-15 16:57:00 -0800110 def logout( self ):
111 """
andrewonlab38d2b4a2014-11-13 16:28:47 -0500112 Sends 'logout' command to ONOS cli
pingping-lin763ee042015-05-20 17:45:30 -0700113 Returns main.TRUE if exited CLI and
114 main.FALSE on timeout (not guranteed you are disconnected)
115 None on TypeError
116 Exits test on unknown error or pexpect exits unexpectedly
kelvin8ec71442015-01-15 16:57:00 -0800117 """
andrewonlab38d2b4a2014-11-13 16:28:47 -0500118 try:
pingping-lin763ee042015-05-20 17:45:30 -0700119 if self.handle:
120 self.handle.sendline( "" )
121 i = self.handle.expect( [ "onos>", "\$", pexpect.TIMEOUT ],
122 timeout=10 )
123 if i == 0: # In ONOS CLI
124 self.handle.sendline( "logout" )
125 self.handle.expect( "\$" )
126 return main.TRUE
127 elif i == 1: # not in CLI
128 return main.TRUE
129 elif i == 3: # Timeout
130 return main.FALSE
131 else:
andrewonlab9627f432014-11-14 12:45:10 -0500132 return main.TRUE
pingping-lin763ee042015-05-20 17:45:30 -0700133 except TypeError:
134 main.log.exception( self.name + ": Object not as expected" )
135 return None
andrewonlab38d2b4a2014-11-13 16:28:47 -0500136 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -0800137 main.log.error( self.name + ": eof exception found" )
pingping-lin763ee042015-05-20 17:45:30 -0700138 main.log.error( self.name + ": " + self.handle.before )
andrewonlab38d2b4a2014-11-13 16:28:47 -0500139 main.cleanup()
140 main.exit()
pingping-lin763ee042015-05-20 17:45:30 -0700141 except ValueError:
142 main.log.error( self.name +
143 "ValueError exception in logout method" )
144 except Exception:
145 main.log.exception( self.name + ": Uncaught exception!" )
andrewonlab38d2b4a2014-11-13 16:28:47 -0500146 main.cleanup()
147 main.exit()
148
kelvin-onlabd3b64892015-01-20 13:26:24 -0800149 def setCell( self, cellname ):
kelvin8ec71442015-01-15 16:57:00 -0800150 """
andrewonlab95ce8322014-10-13 14:12:04 -0400151 Calls 'cell <name>' to set the environment variables on ONOSbench
kelvin8ec71442015-01-15 16:57:00 -0800152
andrewonlab95ce8322014-10-13 14:12:04 -0400153 Before issuing any cli commands, set the environment variable first.
kelvin8ec71442015-01-15 16:57:00 -0800154 """
andrewonlab95ce8322014-10-13 14:12:04 -0400155 try:
156 if not cellname:
kelvin8ec71442015-01-15 16:57:00 -0800157 main.log.error( "Must define cellname" )
andrewonlab95ce8322014-10-13 14:12:04 -0400158 main.cleanup()
159 main.exit()
160 else:
kelvin8ec71442015-01-15 16:57:00 -0800161 self.handle.sendline( "cell " + str( cellname ) )
kelvin-onlabd3b64892015-01-20 13:26:24 -0800162 # Expect the cellname in the ONOSCELL variable.
kelvin8ec71442015-01-15 16:57:00 -0800163 # Note that this variable name is subject to change
andrewonlab95ce8322014-10-13 14:12:04 -0400164 # and that this driver will have to change accordingly
pingping-lin763ee042015-05-20 17:45:30 -0700165 self.handle.expect(str(cellname))
kelvin-onlabd3b64892015-01-20 13:26:24 -0800166 handleBefore = self.handle.before
167 handleAfter = self.handle.after
kelvin8ec71442015-01-15 16:57:00 -0800168 # Get the rest of the handle
pingping-lin763ee042015-05-20 17:45:30 -0700169 self.handle.sendline("")
170 self.handle.expect("\$")
kelvin-onlabd3b64892015-01-20 13:26:24 -0800171 handleMore = self.handle.before
andrewonlab95ce8322014-10-13 14:12:04 -0400172
kelvin-onlabd3b64892015-01-20 13:26:24 -0800173 main.log.info( "Cell call returned: " + handleBefore +
174 handleAfter + handleMore )
andrewonlab95ce8322014-10-13 14:12:04 -0400175
176 return main.TRUE
177
pingping-lin763ee042015-05-20 17:45:30 -0700178 except TypeError:
179 main.log.exception( self.name + ": Object not as expected" )
180 return None
andrewonlab95ce8322014-10-13 14:12:04 -0400181 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -0800182 main.log.error( self.name + ": eof exception found" )
183 main.log.error( self.name + ": " + self.handle.before )
andrewonlab95ce8322014-10-13 14:12:04 -0400184 main.cleanup()
185 main.exit()
pingping-lin763ee042015-05-20 17:45:30 -0700186 except Exception:
187 main.log.exception( self.name + ": Uncaught exception!" )
andrewonlab95ce8322014-10-13 14:12:04 -0400188 main.cleanup()
189 main.exit()
kelvin8ec71442015-01-15 16:57:00 -0800190
pingping-lin57a56ce2015-05-20 16:43:48 -0700191 def startOnosCli( self, ONOSIp, karafTimeout="",
192 commandlineTimeout=10, onosStartTimeout=60 ):
kelvin8ec71442015-01-15 16:57:00 -0800193 """
pingping-lin763ee042015-05-20 17:45:30 -0700194 karafTimeout is an optional argument. karafTimeout value passed
kelvin-onlabd3b64892015-01-20 13:26:24 -0800195 by user would be used to set the current karaf shell idle timeout.
196 Note that when ever this property is modified the shell will exit and
Hari Krishnad7b9c202015-01-05 10:38:14 -0800197 the subsequent login would reflect new idle timeout.
kelvin-onlabd3b64892015-01-20 13:26:24 -0800198 Below is an example to start a session with 60 seconds idle timeout
199 ( input value is in milliseconds ):
kelvin8ec71442015-01-15 16:57:00 -0800200
Hari Krishna25d42f72015-01-05 15:08:28 -0800201 tValue = "60000"
kelvin-onlabd3b64892015-01-20 13:26:24 -0800202 main.ONOScli1.startOnosCli( ONOSIp, karafTimeout=tValue )
kelvin8ec71442015-01-15 16:57:00 -0800203
kelvin-onlabd3b64892015-01-20 13:26:24 -0800204 Note: karafTimeout is left as str so that this could be read
205 and passed to startOnosCli from PARAMS file as str.
kelvin8ec71442015-01-15 16:57:00 -0800206 """
andrewonlab95ce8322014-10-13 14:12:04 -0400207 try:
kelvin8ec71442015-01-15 16:57:00 -0800208 self.handle.sendline( "" )
209 x = self.handle.expect( [
pingping-lin57a56ce2015-05-20 16:43:48 -0700210 "\$", "onos>" ], commandlineTimeout)
andrewonlab48829f62014-11-17 13:49:01 -0500211
212 if x == 1:
kelvin8ec71442015-01-15 16:57:00 -0800213 main.log.info( "ONOS cli is already running" )
andrewonlab48829f62014-11-17 13:49:01 -0500214 return main.TRUE
andrewonlab95ce8322014-10-13 14:12:04 -0400215
kelvin8ec71442015-01-15 16:57:00 -0800216 # Wait for onos start ( -w ) and enter onos cli
kelvin-onlabd3b64892015-01-20 13:26:24 -0800217 self.handle.sendline( "onos -w " + str( ONOSIp ) )
kelvin8ec71442015-01-15 16:57:00 -0800218 i = self.handle.expect( [
219 "onos>",
pingping-lin57a56ce2015-05-20 16:43:48 -0700220 pexpect.TIMEOUT ], onosStartTimeout )
andrewonlab2a7ea9b2014-10-24 12:21:05 -0400221
222 if i == 0:
kelvin-onlabd3b64892015-01-20 13:26:24 -0800223 main.log.info( str( ONOSIp ) + " CLI Started successfully" )
Hari Krishnae36ef212015-01-04 14:09:13 -0800224 if karafTimeout:
kelvin8ec71442015-01-15 16:57:00 -0800225 self.handle.sendline(
Hari Krishnaac4e1782015-01-26 12:09:12 -0800226 "config:property-set -p org.apache.karaf.shell\
227 sshIdleTimeout " +
kelvin8ec71442015-01-15 16:57:00 -0800228 karafTimeout )
229 self.handle.expect( "\$" )
kelvin-onlabd3b64892015-01-20 13:26:24 -0800230 self.handle.sendline( "onos -w " + str( ONOSIp ) )
kelvin8ec71442015-01-15 16:57:00 -0800231 self.handle.expect( "onos>" )
andrewonlab2a7ea9b2014-10-24 12:21:05 -0400232 return main.TRUE
233 else:
kelvin8ec71442015-01-15 16:57:00 -0800234 # If failed, send ctrl+c to process and try again
235 main.log.info( "Starting CLI failed. Retrying..." )
236 self.handle.send( "\x03" )
kelvin-onlabd3b64892015-01-20 13:26:24 -0800237 self.handle.sendline( "onos -w " + str( ONOSIp ) )
kelvin8ec71442015-01-15 16:57:00 -0800238 i = self.handle.expect( [ "onos>", pexpect.TIMEOUT ],
239 timeout=30 )
andrewonlab3a7c3c72014-10-24 17:21:03 -0400240 if i == 0:
kelvin-onlabd3b64892015-01-20 13:26:24 -0800241 main.log.info( str( ONOSIp ) + " CLI Started " +
kelvin8ec71442015-01-15 16:57:00 -0800242 "successfully after retry attempt" )
Hari Krishnae36ef212015-01-04 14:09:13 -0800243 if karafTimeout:
kelvin8ec71442015-01-15 16:57:00 -0800244 self.handle.sendline(
kelvin-onlabd3b64892015-01-20 13:26:24 -0800245 "config:property-set -p org.apache.karaf.shell\
246 sshIdleTimeout " +
kelvin8ec71442015-01-15 16:57:00 -0800247 karafTimeout )
248 self.handle.expect( "\$" )
kelvin-onlabd3b64892015-01-20 13:26:24 -0800249 self.handle.sendline( "onos -w " + str( ONOSIp ) )
kelvin8ec71442015-01-15 16:57:00 -0800250 self.handle.expect( "onos>" )
andrewonlab3a7c3c72014-10-24 17:21:03 -0400251 return main.TRUE
252 else:
kelvin8ec71442015-01-15 16:57:00 -0800253 main.log.error( "Connection to CLI " +
kelvin-onlabd3b64892015-01-20 13:26:24 -0800254 str( ONOSIp ) + " timeout" )
andrewonlab3a7c3c72014-10-24 17:21:03 -0400255 return main.FALSE
andrewonlab95ce8322014-10-13 14:12:04 -0400256
pingping-lin763ee042015-05-20 17:45:30 -0700257 except TypeError:
258 main.log.exception( self.name + ": Object not as expected" )
259 return None
andrewonlab95ce8322014-10-13 14:12:04 -0400260 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -0800261 main.log.error( self.name + ": EOF exception found" )
262 main.log.error( self.name + ": " + self.handle.before )
andrewonlab95ce8322014-10-13 14:12:04 -0400263 main.cleanup()
264 main.exit()
pingping-lin763ee042015-05-20 17:45:30 -0700265 except Exception:
266 main.log.exception( self.name + ": Uncaught exception!" )
andrewonlab95ce8322014-10-13 14:12:04 -0400267 main.cleanup()
268 main.exit()
269
pingping-lin763ee042015-05-20 17:45:30 -0700270 def log( self, cmdStr, level="" ):
271 """
272 log the commands in the onos CLI.
273 returns main.TRUE on success
274 returns main.FALSE if Error occurred
275 Available level: DEBUG, TRACE, INFO, WARN, ERROR
276 Level defaults to INFO
277 """
278 try:
279 lvlStr = ""
280 if level:
281 lvlStr = "--level=" + level
282
283 self.handle.sendline( "" )
284 self.handle.expect( "onos>" )
285 self.handle.sendline( "log:log " + lvlStr + " " + cmdStr )
286 self.handle.expect( "log:log" )
287 self.handle.expect( "onos>" )
288
289 response = self.handle.before
290 if re.search( "Error", response ):
291 return main.FALSE
292 return main.TRUE
293
294 except pexpect.EOF:
295 main.log.error( self.name + ": EOF exception found" )
296 main.log.error( self.name + ": " + self.handle.before )
297 main.cleanup()
298 main.exit()
299 except Exception:
300 main.log.exception( self.name + ": Uncaught exception!" )
301 main.cleanup()
302 main.exit()
303
304 def sendline( self, cmdStr, debug=False ):
kelvin8ec71442015-01-15 16:57:00 -0800305 """
Jon Halle3f39ff2015-01-13 11:50:53 -0800306 Send a completely user specified string to
307 the onos> prompt. Use this function if you have
andrewonlaba18f6bf2014-10-13 19:31:54 -0400308 a very specific command to send.
Jon Halle3f39ff2015-01-13 11:50:53 -0800309
andrewonlaba18f6bf2014-10-13 19:31:54 -0400310 Warning: There are no sanity checking to commands
311 sent using this method.
kelvin8ec71442015-01-15 16:57:00 -0800312 """
andrewonlaba18f6bf2014-10-13 19:31:54 -0400313 try:
pingping-lin763ee042015-05-20 17:45:30 -0700314 logStr = "\"Sending CLI command: '" + cmdStr + "'\""
315 self.log( logStr )
kelvin-onlabd3b64892015-01-20 13:26:24 -0800316 self.handle.sendline( cmdStr )
pingping-lin763ee042015-05-20 17:45:30 -0700317 i = self.handle.expect( ["onos>", "\$", pexpect.TIMEOUT] )
318 response = self.handle.before
319 if i == 2:
320 self.handle.sendline()
321 self.handle.expect( ["\$", pexpect.TIMEOUT] )
322 response += self.handle.before
323 print response
324 try:
325 print self.handle.after
326 except TypeError:
327 pass
328 # TODO: do something with i
Jon Hallaea67aa2015-01-23 13:30:57 -0800329 main.log.info( "Command '" + str( cmdStr ) + "' sent to "
330 + self.name + "." )
pingping-lin763ee042015-05-20 17:45:30 -0700331 if debug:
332 main.log.debug( self.name + ": Raw output" )
333 main.log.debug( self.name + ": " + repr( response ) )
andrewonlaba18f6bf2014-10-13 19:31:54 -0400334
pingping-lin763ee042015-05-20 17:45:30 -0700335 # Remove ANSI color control strings from output
Jon Hall7bdfc122015-01-23 11:45:32 -0800336 ansiEscape = re.compile( r'\x1b[^m]*m' )
pingping-lin763ee042015-05-20 17:45:30 -0700337 response = ansiEscape.sub( '', response )
338 if debug:
339 main.log.debug( self.name + ": ansiEscape output" )
340 main.log.debug( self.name + ": " + repr( response ) )
kelvin8ec71442015-01-15 16:57:00 -0800341
pingping-lin763ee042015-05-20 17:45:30 -0700342 # Remove extra return chars that get added
343 response = re.sub( r"\s\r", "", response )
344 if debug:
345 main.log.debug( self.name + ": Removed extra returns " +
346 "from output" )
347 main.log.debug( self.name + ": " + repr( response ) )
andrewonlaba18f6bf2014-10-13 19:31:54 -0400348
pingping-lin763ee042015-05-20 17:45:30 -0700349 # Strip excess whitespace
350 response = response.strip()
351 if debug:
352 main.log.debug( self.name + ": parsed and stripped output" )
353 main.log.debug( self.name + ": " + repr( response ) )
354
355 # parse for just the output, remove the cmd from response
356 output = response.split( cmdStr.strip(), 1 )
357 if debug:
358 main.log.debug( self.name + ": split output" )
359 for r in output:
360 main.log.debug( self.name + ": " + repr( r ) )
361 return output[1].strip()
362 except IndexError:
363 main.log.exception( self.name + ": Object not as expected" )
364 return None
365 except TypeError:
366 main.log.exception( self.name + ": Object not as expected" )
367 return None
andrewonlaba18f6bf2014-10-13 19:31:54 -0400368 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -0800369 main.log.error( self.name + ": EOF exception found" )
370 main.log.error( self.name + ": " + self.handle.before )
andrewonlaba18f6bf2014-10-13 19:31:54 -0400371 main.cleanup()
372 main.exit()
pingping-lin763ee042015-05-20 17:45:30 -0700373 except Exception:
374 main.log.exception( self.name + ": Uncaught exception!" )
andrewonlaba18f6bf2014-10-13 19:31:54 -0400375 main.cleanup()
376 main.exit()
377
kelvin8ec71442015-01-15 16:57:00 -0800378 # IMPORTANT NOTE:
379 # For all cli commands, naming convention should match
kelvin-onlabd3b64892015-01-20 13:26:24 -0800380 # the cli command changing 'a:b' with 'aB'.
381 # Ex ) onos:topology > onosTopology
382 # onos:links > onosLinks
383 # feature:list > featureList
Jon Halle3f39ff2015-01-13 11:50:53 -0800384
kelvin-onlabd3b64892015-01-20 13:26:24 -0800385 def addNode( self, nodeId, ONOSIp, tcpPort="" ):
kelvin8ec71442015-01-15 16:57:00 -0800386 """
andrewonlabc2d05aa2014-10-13 16:51:10 -0400387 Adds a new cluster node by ID and address information.
388 Required:
kelvin-onlabd3b64892015-01-20 13:26:24 -0800389 * nodeId
390 * ONOSIp
andrewonlabc2d05aa2014-10-13 16:51:10 -0400391 Optional:
kelvin-onlabd3b64892015-01-20 13:26:24 -0800392 * tcpPort
kelvin8ec71442015-01-15 16:57:00 -0800393 """
andrewonlabc2d05aa2014-10-13 16:51:10 -0400394 try:
kelvin-onlabd3b64892015-01-20 13:26:24 -0800395 cmdStr = "add-node " + str( nodeId ) + " " +\
396 str( ONOSIp ) + " " + str( tcpPort )
397 handle = self.sendline( cmdStr )
kelvin-onlab898a6c62015-01-16 14:13:53 -0800398 if re.search( "Error", handle ):
kelvin8ec71442015-01-15 16:57:00 -0800399 main.log.error( "Error in adding node" )
400 main.log.error( handle )
Jon Halle3f39ff2015-01-13 11:50:53 -0800401 return main.FALSE
andrewonlabc2d05aa2014-10-13 16:51:10 -0400402 else:
kelvin-onlabd3b64892015-01-20 13:26:24 -0800403 main.log.info( "Node " + str( ONOSIp ) + " added" )
andrewonlabc2d05aa2014-10-13 16:51:10 -0400404 return main.TRUE
pingping-lin763ee042015-05-20 17:45:30 -0700405 except TypeError:
406 main.log.exception( self.name + ": Object not as expected" )
407 return None
andrewonlabc2d05aa2014-10-13 16:51:10 -0400408 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -0800409 main.log.error( self.name + ": EOF exception found" )
410 main.log.error( self.name + ": " + self.handle.before )
andrewonlabc2d05aa2014-10-13 16:51:10 -0400411 main.cleanup()
412 main.exit()
pingping-lin763ee042015-05-20 17:45:30 -0700413 except Exception:
414 main.log.exception( self.name + ": Uncaught exception!" )
andrewonlabc2d05aa2014-10-13 16:51:10 -0400415 main.cleanup()
416 main.exit()
417
kelvin-onlabd3b64892015-01-20 13:26:24 -0800418 def removeNode( self, nodeId ):
kelvin8ec71442015-01-15 16:57:00 -0800419 """
andrewonlab86dc3082014-10-13 18:18:38 -0400420 Removes a cluster by ID
421 Issues command: 'remove-node [<node-id>]'
422 Required:
kelvin-onlabd3b64892015-01-20 13:26:24 -0800423 * nodeId
kelvin8ec71442015-01-15 16:57:00 -0800424 """
andrewonlab86dc3082014-10-13 18:18:38 -0400425 try:
andrewonlab86dc3082014-10-13 18:18:38 -0400426
kelvin-onlabd3b64892015-01-20 13:26:24 -0800427 cmdStr = "remove-node " + str( nodeId )
pingping-lin763ee042015-05-20 17:45:30 -0700428 handle = self.sendline( cmdStr )
429 if re.search( "Error", handle ):
430 main.log.error( "Error in removing node" )
431 main.log.error( handle )
432 return main.FALSE
433 else:
434 return main.TRUE
435 except TypeError:
436 main.log.exception( self.name + ": Object not as expected" )
437 return None
andrewonlab86dc3082014-10-13 18:18:38 -0400438 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -0800439 main.log.error( self.name + ": EOF exception found" )
440 main.log.error( self.name + ": " + self.handle.before )
andrewonlab86dc3082014-10-13 18:18:38 -0400441 main.cleanup()
442 main.exit()
pingping-lin763ee042015-05-20 17:45:30 -0700443 except Exception:
444 main.log.exception( self.name + ": Uncaught exception!" )
andrewonlab86dc3082014-10-13 18:18:38 -0400445 main.cleanup()
446 main.exit()
andrewonlabc2d05aa2014-10-13 16:51:10 -0400447
pingping-lin763ee042015-05-20 17:45:30 -0700448 def nodes( self, jsonFormat=True):
kelvin8ec71442015-01-15 16:57:00 -0800449 """
andrewonlab7c211572014-10-15 16:45:20 -0400450 List the nodes currently visible
451 Issues command: 'nodes'
pingping-lin763ee042015-05-20 17:45:30 -0700452 Optional argument:
453 * jsonFormat - boolean indicating if you want output in json
kelvin8ec71442015-01-15 16:57:00 -0800454 """
andrewonlab7c211572014-10-15 16:45:20 -0400455 try:
kelvin-onlabd3b64892015-01-20 13:26:24 -0800456 cmdStr = "nodes"
pingping-lin763ee042015-05-20 17:45:30 -0700457 if jsonFormat:
458 cmdStr += " -j"
459 output = self.sendline( cmdStr )
460 return output
461 except TypeError:
462 main.log.exception( self.name + ": Object not as expected" )
463 return None
andrewonlab7c211572014-10-15 16:45:20 -0400464 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -0800465 main.log.error( self.name + ": EOF exception found" )
466 main.log.error( self.name + ": " + self.handle.before )
andrewonlab7c211572014-10-15 16:45:20 -0400467 main.cleanup()
468 main.exit()
pingping-lin763ee042015-05-20 17:45:30 -0700469 except Exception:
470 main.log.exception( self.name + ": Uncaught exception!" )
andrewonlab7c211572014-10-15 16:45:20 -0400471 main.cleanup()
472 main.exit()
473
kelvin8ec71442015-01-15 16:57:00 -0800474 def topology( self ):
475 """
pingping-lin763ee042015-05-20 17:45:30 -0700476 Definition:
477 Returns the output of topology command.
478 Return:
479 topology = current ONOS topology
kelvin8ec71442015-01-15 16:57:00 -0800480 """
andrewonlab95ce8322014-10-13 14:12:04 -0400481 try:
pingping-lin763ee042015-05-20 17:45:30 -0700482 cmdStr = "topology -j"
kelvin-onlabd3b64892015-01-20 13:26:24 -0800483 handle = self.sendline( cmdStr )
pingping-lin763ee042015-05-20 17:45:30 -0700484 main.log.info( cmdStr + " returned: " + str( handle ) )
andrewonlab95ce8322014-10-13 14:12:04 -0400485 return handle
pingping-lin763ee042015-05-20 17:45:30 -0700486 except TypeError:
487 main.log.exception( self.name + ": Object not as expected" )
488 return None
andrewonlab95ce8322014-10-13 14:12:04 -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 )
andrewonlab95ce8322014-10-13 14:12:04 -0400492 main.cleanup()
493 main.exit()
pingping-lin763ee042015-05-20 17:45:30 -0700494 except Exception:
495 main.log.exception( self.name + ": Uncaught exception!" )
andrewonlab95ce8322014-10-13 14:12:04 -0400496 main.cleanup()
497 main.exit()
Jon Halle3f39ff2015-01-13 11:50:53 -0800498
kelvin-onlabd3b64892015-01-20 13:26:24 -0800499 def featureInstall( self, featureStr ):
kelvin8ec71442015-01-15 16:57:00 -0800500 """
pingping-lin763ee042015-05-20 17:45:30 -0700501 Installs a specified feature by issuing command:
502 'feature:install <feature_str>'
503 NOTE: This is now deprecated, you should use the activateApp method
504 instead
kelvin8ec71442015-01-15 16:57:00 -0800505 """
andrewonlabc2d05aa2014-10-13 16:51:10 -0400506 try:
kelvin-onlabd3b64892015-01-20 13:26:24 -0800507 cmdStr = "feature:install " + str( featureStr )
pingping-lin763ee042015-05-20 17:45:30 -0700508 handle = self.sendline( cmdStr )
509 if re.search( "Error", handle ):
510 main.log.error( "Error in installing feature" )
511 main.log.error( handle )
512 return main.FALSE
513 else:
514 return main.TRUE
515 except TypeError:
516 main.log.exception( self.name + ": Object not as expected" )
517 return None
andrewonlabc2d05aa2014-10-13 16:51:10 -0400518 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -0800519 main.log.error( self.name + ": EOF exception found" )
520 main.log.error( self.name + ": " + self.handle.before )
521 main.log.report( "Failed to install feature" )
522 main.log.report( "Exiting test" )
andrewonlabc2d05aa2014-10-13 16:51:10 -0400523 main.cleanup()
524 main.exit()
pingping-lin763ee042015-05-20 17:45:30 -0700525 except Exception:
526 main.log.exception( self.name + ": Uncaught exception!" )
kelvin8ec71442015-01-15 16:57:00 -0800527 main.log.report( "Failed to install feature" )
528 main.log.report( "Exiting test" )
andrewonlabc2d05aa2014-10-13 16:51:10 -0400529 main.cleanup()
530 main.exit()
Jon Halle3f39ff2015-01-13 11:50:53 -0800531
kelvin-onlabd3b64892015-01-20 13:26:24 -0800532 def featureUninstall( self, featureStr ):
kelvin8ec71442015-01-15 16:57:00 -0800533 """
pingping-lin763ee042015-05-20 17:45:30 -0700534 Uninstalls a specified feature by issuing command:
535 'feature:uninstall <feature_str>'
536 NOTE: This is now deprecated, you should use the deactivateApp method
537 instead
kelvin8ec71442015-01-15 16:57:00 -0800538 """
andrewonlabc2d05aa2014-10-13 16:51:10 -0400539 try:
pingping-lin763ee042015-05-20 17:45:30 -0700540 cmdStr = 'feature:list -i | grep "' + featureStr + '"'
541 handle = self.sendline( cmdStr )
542 if handle != '':
543 cmdStr = "feature:uninstall " + str( featureStr )
544 output = self.sendline( cmdStr )
545 # TODO: Check for possible error responses from karaf
546 else:
547 main.log.info( "Feature needs to be installed before " +
548 "uninstalling it" )
549 return main.TRUE
550 if re.search( "Error", output ):
551 main.log.error( "Error in uninstalling feature" )
552 main.log.error( output )
553 return main.FALSE
554 else:
555 return main.TRUE
556 except TypeError:
557 main.log.exception( self.name + ": Object not as expected" )
558 return None
andrewonlabc2d05aa2014-10-13 16:51:10 -0400559 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -0800560 main.log.error( self.name + ": EOF exception found" )
561 main.log.error( self.name + ": " + self.handle.before )
andrewonlabc2d05aa2014-10-13 16:51:10 -0400562 main.cleanup()
563 main.exit()
pingping-lin763ee042015-05-20 17:45:30 -0700564 except Exception:
565 main.log.exception( self.name + ": Uncaught exception!" )
566 main.cleanup()
567 main.exit()
568
569 def deviceRemove( self, deviceId ):
570 """
571 Removes particular device from storage
572
573 TODO: refactor this function
574 """
575 try:
576 cmdStr = "device-remove " + str( deviceId )
577 handle = self.sendline( cmdStr )
578 if re.search( "Error", handle ):
579 main.log.error( "Error in removing device" )
580 main.log.error( handle )
581 return main.FALSE
582 else:
583 return main.TRUE
584 except TypeError:
585 main.log.exception( self.name + ": Object not as expected" )
586 return None
587 except pexpect.EOF:
588 main.log.error( self.name + ": EOF exception found" )
589 main.log.error( self.name + ": " + self.handle.before )
590 main.cleanup()
591 main.exit()
592 except Exception:
593 main.log.exception( self.name + ": Uncaught exception!" )
andrewonlabc2d05aa2014-10-13 16:51:10 -0400594 main.cleanup()
595 main.exit()
Jon Hallffb386d2014-11-21 13:43:38 -0800596
kelvin-onlabd3b64892015-01-20 13:26:24 -0800597 def devices( self, jsonFormat=True ):
kelvin8ec71442015-01-15 16:57:00 -0800598 """
Jon Hall7b02d952014-10-17 20:14:54 -0400599 Lists all infrastructure devices or switches
andrewonlab86dc3082014-10-13 18:18:38 -0400600 Optional argument:
kelvin-onlabd3b64892015-01-20 13:26:24 -0800601 * jsonFormat - boolean indicating if you want output in json
kelvin8ec71442015-01-15 16:57:00 -0800602 """
andrewonlab86dc3082014-10-13 18:18:38 -0400603 try:
pingping-lin763ee042015-05-20 17:45:30 -0700604 cmdStr = "devices"
kelvin-onlabd3b64892015-01-20 13:26:24 -0800605 if jsonFormat:
pingping-lin763ee042015-05-20 17:45:30 -0700606 cmdStr += " -j"
607 handle = self.sendline( cmdStr )
608 return handle
609 except TypeError:
610 main.log.exception( self.name + ": Object not as expected" )
611 return None
andrewonlab7c211572014-10-15 16:45:20 -0400612 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -0800613 main.log.error( self.name + ": EOF exception found" )
614 main.log.error( self.name + ": " + self.handle.before )
andrewonlab7c211572014-10-15 16:45:20 -0400615 main.cleanup()
616 main.exit()
pingping-lin763ee042015-05-20 17:45:30 -0700617 except Exception:
618 main.log.exception( self.name + ": Uncaught exception!" )
andrewonlab7c211572014-10-15 16:45:20 -0400619 main.cleanup()
620 main.exit()
621
kelvin-onlabd3b64892015-01-20 13:26:24 -0800622 def balanceMasters( self ):
kelvin8ec71442015-01-15 16:57:00 -0800623 """
Hari Krishnaa43d4e92014-12-19 13:22:40 -0800624 This balances the devices across all controllers
625 by issuing command: 'onos> onos:balance-masters'
626 If required this could be extended to return devices balanced output.
kelvin8ec71442015-01-15 16:57:00 -0800627 """
Hari Krishnaa43d4e92014-12-19 13:22:40 -0800628 try:
kelvin-onlabd3b64892015-01-20 13:26:24 -0800629 cmdStr = "onos:balance-masters"
pingping-lin763ee042015-05-20 17:45:30 -0700630 handle = self.sendline( cmdStr )
631 if re.search( "Error", handle ):
632 main.log.error( "Error in balancing masters" )
633 main.log.error( handle )
634 return main.FALSE
635 else:
636 return main.TRUE
637 except TypeError:
638 main.log.exception( self.name + ": Object not as expected" )
639 return None
Hari Krishnaa43d4e92014-12-19 13:22:40 -0800640 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -0800641 main.log.error( self.name + ": EOF exception found" )
642 main.log.error( self.name + ": " + self.handle.before )
Hari Krishnaa43d4e92014-12-19 13:22:40 -0800643 main.cleanup()
644 main.exit()
pingping-lin763ee042015-05-20 17:45:30 -0700645 except Exception:
646 main.log.exception( self.name + ": Uncaught exception!" )
Hari Krishnaa43d4e92014-12-19 13:22:40 -0800647 main.cleanup()
648 main.exit()
649
kelvin-onlabd3b64892015-01-20 13:26:24 -0800650 def links( self, jsonFormat=True ):
kelvin8ec71442015-01-15 16:57:00 -0800651 """
Jon Halle8217482014-10-17 13:49:14 -0400652 Lists all core links
653 Optional argument:
kelvin-onlabd3b64892015-01-20 13:26:24 -0800654 * jsonFormat - boolean indicating if you want output in json
kelvin8ec71442015-01-15 16:57:00 -0800655 """
Jon Halle8217482014-10-17 13:49:14 -0400656 try:
pingping-lin763ee042015-05-20 17:45:30 -0700657 cmdStr = "links"
kelvin-onlabd3b64892015-01-20 13:26:24 -0800658 if jsonFormat:
pingping-lin763ee042015-05-20 17:45:30 -0700659 cmdStr += " -j"
660 handle = self.sendline( cmdStr )
661 return handle
662 except TypeError:
663 main.log.exception( self.name + ": Object not as expected" )
664 return None
Jon Halle8217482014-10-17 13:49:14 -0400665 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -0800666 main.log.error( self.name + ": EOF exception found" )
667 main.log.error( self.name + ": " + self.handle.before )
Jon Halle8217482014-10-17 13:49:14 -0400668 main.cleanup()
669 main.exit()
pingping-lin763ee042015-05-20 17:45:30 -0700670 except Exception:
671 main.log.exception( self.name + ": Uncaught exception!" )
Jon Halle8217482014-10-17 13:49:14 -0400672 main.cleanup()
673 main.exit()
674
kelvin-onlabd3b64892015-01-20 13:26:24 -0800675 def ports( self, jsonFormat=True ):
kelvin8ec71442015-01-15 16:57:00 -0800676 """
Jon Halle8217482014-10-17 13:49:14 -0400677 Lists all ports
678 Optional argument:
kelvin-onlabd3b64892015-01-20 13:26:24 -0800679 * jsonFormat - boolean indicating if you want output in json
kelvin8ec71442015-01-15 16:57:00 -0800680 """
Jon Halle8217482014-10-17 13:49:14 -0400681 try:
pingping-lin763ee042015-05-20 17:45:30 -0700682 cmdStr = "ports"
kelvin-onlabd3b64892015-01-20 13:26:24 -0800683 if jsonFormat:
pingping-lin763ee042015-05-20 17:45:30 -0700684 cmdStr += " -j"
685 handle = self.sendline( cmdStr )
686 return handle
687 except TypeError:
688 main.log.exception( self.name + ": Object not as expected" )
689 return None
Jon Halle8217482014-10-17 13:49:14 -0400690 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -0800691 main.log.error( self.name + ": EOF exception found" )
692 main.log.error( self.name + ": " + self.handle.before )
Jon Halle8217482014-10-17 13:49:14 -0400693 main.cleanup()
694 main.exit()
pingping-lin763ee042015-05-20 17:45:30 -0700695 except Exception:
696 main.log.exception( self.name + ": Uncaught exception!" )
Jon Halle8217482014-10-17 13:49:14 -0400697 main.cleanup()
698 main.exit()
699
kelvin-onlabd3b64892015-01-20 13:26:24 -0800700 def roles( self, jsonFormat=True ):
kelvin8ec71442015-01-15 16:57:00 -0800701 """
Jon Hall983a1702014-10-28 18:44:22 -0400702 Lists all devices and the controllers with roles assigned to them
703 Optional argument:
kelvin-onlabd3b64892015-01-20 13:26:24 -0800704 * jsonFormat - boolean indicating if you want output in json
kelvin8ec71442015-01-15 16:57:00 -0800705 """
andrewonlab7c211572014-10-15 16:45:20 -0400706 try:
pingping-lin763ee042015-05-20 17:45:30 -0700707 cmdStr = "roles"
kelvin-onlabd3b64892015-01-20 13:26:24 -0800708 if jsonFormat:
pingping-lin763ee042015-05-20 17:45:30 -0700709 cmdStr += " -j"
710 handle = self.sendline( cmdStr )
711 return handle
712 except TypeError:
713 main.log.exception( self.name + ": Object not as expected" )
714 return None
Jon Hall983a1702014-10-28 18:44:22 -0400715 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -0800716 main.log.error( self.name + ": EOF exception found" )
717 main.log.error( self.name + ": " + self.handle.before )
Jon Hall983a1702014-10-28 18:44:22 -0400718 main.cleanup()
719 main.exit()
pingping-lin763ee042015-05-20 17:45:30 -0700720 except Exception:
721 main.log.exception( self.name + ": Uncaught exception!" )
Jon Hall983a1702014-10-28 18:44:22 -0400722 main.cleanup()
723 main.exit()
724
kelvin-onlabd3b64892015-01-20 13:26:24 -0800725 def getRole( self, deviceId ):
kelvin-onlab898a6c62015-01-16 14:13:53 -0800726 """
Jon Halle3f39ff2015-01-13 11:50:53 -0800727 Given the a string containing the json representation of the "roles"
728 cli command and a partial or whole device id, returns a json object
729 containing the roles output for the first device whose id contains
730 "device_id"
Jon Hall983a1702014-10-28 18:44:22 -0400731
732 Returns:
Jon Halle3f39ff2015-01-13 11:50:53 -0800733 A dict of the role assignments for the given device or
734 None if no match
kelvin8ec71442015-01-15 16:57:00 -0800735 """
Jon Hall983a1702014-10-28 18:44:22 -0400736 try:
kelvin-onlabd3b64892015-01-20 13:26:24 -0800737 if deviceId is None:
Jon Hall983a1702014-10-28 18:44:22 -0400738 return None
739 else:
kelvin-onlabd3b64892015-01-20 13:26:24 -0800740 rawRoles = self.roles()
741 rolesJson = json.loads( rawRoles )
kelvin8ec71442015-01-15 16:57:00 -0800742 # search json for the device with id then return the device
kelvin-onlabd3b64892015-01-20 13:26:24 -0800743 for device in rolesJson:
kelvin8ec71442015-01-15 16:57:00 -0800744 # print device
kelvin-onlabd3b64892015-01-20 13:26:24 -0800745 if str( deviceId ) in device[ 'id' ]:
Jon Hall983a1702014-10-28 18:44:22 -0400746 return device
747 return None
pingping-lin763ee042015-05-20 17:45:30 -0700748 except TypeError:
749 main.log.exception( self.name + ": Object not as expected" )
750 return None
andrewonlab86dc3082014-10-13 18:18:38 -0400751 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -0800752 main.log.error( self.name + ": EOF exception found" )
753 main.log.error( self.name + ": " + self.handle.before )
andrewonlab86dc3082014-10-13 18:18:38 -0400754 main.cleanup()
755 main.exit()
pingping-lin763ee042015-05-20 17:45:30 -0700756 except Exception:
757 main.log.exception( self.name + ": Uncaught exception!" )
andrewonlab86dc3082014-10-13 18:18:38 -0400758 main.cleanup()
759 main.exit()
Jon Hall94fd0472014-12-08 11:52:42 -0800760
kelvin-onlabd3b64892015-01-20 13:26:24 -0800761 def rolesNotNull( self ):
kelvin8ec71442015-01-15 16:57:00 -0800762 """
Jon Hall94fd0472014-12-08 11:52:42 -0800763 Iterates through each device and checks if there is a master assigned
764 Returns: main.TRUE if each device has a master
765 main.FALSE any device has no master
kelvin8ec71442015-01-15 16:57:00 -0800766 """
Jon Hall94fd0472014-12-08 11:52:42 -0800767 try:
kelvin-onlabd3b64892015-01-20 13:26:24 -0800768 rawRoles = self.roles()
769 rolesJson = json.loads( rawRoles )
kelvin8ec71442015-01-15 16:57:00 -0800770 # search json for the device with id then return the device
kelvin-onlabd3b64892015-01-20 13:26:24 -0800771 for device in rolesJson:
kelvin8ec71442015-01-15 16:57:00 -0800772 # print device
773 if device[ 'master' ] == "none":
774 main.log.warn( "Device has no master: " + str( device ) )
Jon Hall94fd0472014-12-08 11:52:42 -0800775 return main.FALSE
776 return main.TRUE
777
pingping-lin763ee042015-05-20 17:45:30 -0700778 except TypeError:
779 main.log.exception( self.name + ": Object not as expected" )
780 return None
Jon Hall94fd0472014-12-08 11:52:42 -0800781 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -0800782 main.log.error( self.name + ": EOF exception found" )
783 main.log.error( self.name + ": " + self.handle.before )
Jon Hall94fd0472014-12-08 11:52:42 -0800784 main.cleanup()
785 main.exit()
pingping-lin763ee042015-05-20 17:45:30 -0700786 except Exception:
787 main.log.exception( self.name + ": Uncaught exception!" )
Jon Hall94fd0472014-12-08 11:52:42 -0800788 main.cleanup()
789 main.exit()
790
kelvin-onlabd3b64892015-01-20 13:26:24 -0800791 def paths( self, srcId, dstId ):
kelvin8ec71442015-01-15 16:57:00 -0800792 """
andrewonlab3e15ead2014-10-15 14:21:34 -0400793 Returns string of paths, and the cost.
794 Issues command: onos:paths <src> <dst>
kelvin8ec71442015-01-15 16:57:00 -0800795 """
andrewonlab3e15ead2014-10-15 14:21:34 -0400796 try:
kelvin-onlabd3b64892015-01-20 13:26:24 -0800797 cmdStr = "onos:paths " + str( srcId ) + " " + str( dstId )
798 handle = self.sendline( cmdStr )
Jon Halle3f39ff2015-01-13 11:50:53 -0800799 if re.search( "Error", handle ):
kelvin8ec71442015-01-15 16:57:00 -0800800 main.log.error( "Error in getting paths" )
801 return ( handle, "Error" )
andrewonlab3e15ead2014-10-15 14:21:34 -0400802 else:
kelvin8ec71442015-01-15 16:57:00 -0800803 path = handle.split( ";" )[ 0 ]
804 cost = handle.split( ";" )[ 1 ]
805 return ( path, cost )
pingping-lin763ee042015-05-20 17:45:30 -0700806 except TypeError:
807 main.log.exception( self.name + ": Object not as expected" )
808 return ( handle, "Error" )
andrewonlab3e15ead2014-10-15 14:21:34 -0400809 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -0800810 main.log.error( self.name + ": EOF exception found" )
811 main.log.error( self.name + ": " + self.handle.before )
andrewonlab3e15ead2014-10-15 14:21:34 -0400812 main.cleanup()
813 main.exit()
pingping-lin763ee042015-05-20 17:45:30 -0700814 except Exception:
815 main.log.exception( self.name + ": Uncaught exception!" )
andrewonlab3e15ead2014-10-15 14:21:34 -0400816 main.cleanup()
817 main.exit()
Jon Hallffb386d2014-11-21 13:43:38 -0800818
kelvin-onlabd3b64892015-01-20 13:26:24 -0800819 def hosts( self, jsonFormat=True ):
kelvin8ec71442015-01-15 16:57:00 -0800820 """
Jon Hallffb386d2014-11-21 13:43:38 -0800821 Lists all discovered hosts
Jon Hall42db6dc2014-10-24 19:03:48 -0400822 Optional argument:
kelvin-onlabd3b64892015-01-20 13:26:24 -0800823 * jsonFormat - boolean indicating if you want output in json
kelvin8ec71442015-01-15 16:57:00 -0800824 """
Jon Hall42db6dc2014-10-24 19:03:48 -0400825 try:
pingping-lin763ee042015-05-20 17:45:30 -0700826 cmdStr = "hosts"
kelvin-onlabd3b64892015-01-20 13:26:24 -0800827 if jsonFormat:
pingping-lin763ee042015-05-20 17:45:30 -0700828 cmdStr += " -j"
829 handle = self.sendline( cmdStr )
830 return handle
831 except TypeError:
832 main.log.exception( self.name + ": Object not as expected" )
833 return None
Jon Hall42db6dc2014-10-24 19:03:48 -0400834 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -0800835 main.log.error( self.name + ": EOF exception found" )
836 main.log.error( self.name + ": " + self.handle.before )
Jon Hall42db6dc2014-10-24 19:03:48 -0400837 main.cleanup()
838 main.exit()
pingping-lin763ee042015-05-20 17:45:30 -0700839 except Exception:
840 main.log.exception( self.name + ": Uncaught exception!" )
Jon Hall42db6dc2014-10-24 19:03:48 -0400841 main.cleanup()
842 main.exit()
843
kelvin-onlabd3b64892015-01-20 13:26:24 -0800844 def getHost( self, mac ):
kelvin8ec71442015-01-15 16:57:00 -0800845 """
Jon Hall42db6dc2014-10-24 19:03:48 -0400846 Return the first host from the hosts api whose 'id' contains 'mac'
Jon Halle3f39ff2015-01-13 11:50:53 -0800847
pingping-lin763ee042015-05-20 17:45:30 -0700848 Note: mac must be a colon separated mac address, but could be a
Jon Halle3f39ff2015-01-13 11:50:53 -0800849 partial mac address
850
Jon Hall42db6dc2014-10-24 19:03:48 -0400851 Return None if there is no match
kelvin8ec71442015-01-15 16:57:00 -0800852 """
Jon Hall42db6dc2014-10-24 19:03:48 -0400853 try:
kelvin8ec71442015-01-15 16:57:00 -0800854 if mac is None:
Jon Hall42db6dc2014-10-24 19:03:48 -0400855 return None
856 else:
857 mac = mac
kelvin-onlabd3b64892015-01-20 13:26:24 -0800858 rawHosts = self.hosts()
859 hostsJson = json.loads( rawHosts )
kelvin8ec71442015-01-15 16:57:00 -0800860 # search json for the host with mac then return the device
kelvin-onlabd3b64892015-01-20 13:26:24 -0800861 for host in hostsJson:
kelvin8ec71442015-01-15 16:57:00 -0800862 # print "%s in %s?" % ( mac, host[ 'id' ] )
pingping-lin763ee042015-05-20 17:45:30 -0700863 if not host:
864 pass
865 elif mac in host[ 'id' ]:
Jon Hall42db6dc2014-10-24 19:03:48 -0400866 return host
867 return None
pingping-lin763ee042015-05-20 17:45:30 -0700868 except TypeError:
869 main.log.exception( self.name + ": Object not as expected" )
870 return None
Jon Hall42db6dc2014-10-24 19:03:48 -0400871 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -0800872 main.log.error( self.name + ": EOF exception found" )
873 main.log.error( self.name + ": " + self.handle.before )
Jon Hall42db6dc2014-10-24 19:03:48 -0400874 main.cleanup()
875 main.exit()
pingping-lin763ee042015-05-20 17:45:30 -0700876 except Exception:
877 main.log.exception( self.name + ": Uncaught exception!" )
Jon Hall42db6dc2014-10-24 19:03:48 -0400878 main.cleanup()
879 main.exit()
880
kelvin-onlabd3b64892015-01-20 13:26:24 -0800881 def getHostsId( self, hostList ):
kelvin8ec71442015-01-15 16:57:00 -0800882 """
883 Obtain list of hosts
andrewonlab3f0a4af2014-10-17 12:25:14 -0400884 Issues command: 'onos> hosts'
kelvin8ec71442015-01-15 16:57:00 -0800885
andrewonlab3f0a4af2014-10-17 12:25:14 -0400886 Required:
kelvin-onlabd3b64892015-01-20 13:26:24 -0800887 * hostList: List of hosts obtained by Mininet
andrewonlab3f0a4af2014-10-17 12:25:14 -0400888 IMPORTANT:
889 This function assumes that you started your
kelvin8ec71442015-01-15 16:57:00 -0800890 topology with the option '--mac'.
andrewonlab3f0a4af2014-10-17 12:25:14 -0400891 Furthermore, it assumes that value of VLAN is '-1'
892 Description:
kelvin8ec71442015-01-15 16:57:00 -0800893 Converts mininet hosts ( h1, h2, h3... ) into
894 ONOS format ( 00:00:00:00:00:01/-1 , ... )
895 """
andrewonlab3f0a4af2014-10-17 12:25:14 -0400896 try:
kelvin-onlabd3b64892015-01-20 13:26:24 -0800897 onosHostList = []
andrewonlab3f0a4af2014-10-17 12:25:14 -0400898
kelvin-onlabd3b64892015-01-20 13:26:24 -0800899 for host in hostList:
kelvin8ec71442015-01-15 16:57:00 -0800900 host = host.replace( "h", "" )
kelvin-onlabd3b64892015-01-20 13:26:24 -0800901 hostHex = hex( int( host ) ).zfill( 12 )
902 hostHex = str( hostHex ).replace( 'x', '0' )
903 i = iter( str( hostHex ) )
904 hostHex = ":".join( a + b for a, b in zip( i, i ) )
905 hostHex = hostHex + "/-1"
906 onosHostList.append( hostHex )
andrewonlab3f0a4af2014-10-17 12:25:14 -0400907
kelvin-onlabd3b64892015-01-20 13:26:24 -0800908 return onosHostList
andrewonlab3f0a4af2014-10-17 12:25:14 -0400909
pingping-lin763ee042015-05-20 17:45:30 -0700910 except TypeError:
911 main.log.exception( self.name + ": Object not as expected" )
912 return None
andrewonlab3f0a4af2014-10-17 12:25:14 -0400913 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -0800914 main.log.error( self.name + ": EOF exception found" )
915 main.log.error( self.name + ": " + self.handle.before )
andrewonlab3f0a4af2014-10-17 12:25:14 -0400916 main.cleanup()
917 main.exit()
pingping-lin763ee042015-05-20 17:45:30 -0700918 except Exception:
919 main.log.exception( self.name + ": Uncaught exception!" )
andrewonlab3f0a4af2014-10-17 12:25:14 -0400920 main.cleanup()
921 main.exit()
andrewonlab3e15ead2014-10-15 14:21:34 -0400922
kelvin-onlabd3b64892015-01-20 13:26:24 -0800923 def addHostIntent( self, hostIdOne, hostIdTwo ):
kelvin8ec71442015-01-15 16:57:00 -0800924 """
andrewonlabe6745342014-10-17 14:29:13 -0400925 Required:
kelvin-onlabd3b64892015-01-20 13:26:24 -0800926 * hostIdOne: ONOS host id for host1
927 * hostIdTwo: ONOS host id for host2
andrewonlabe6745342014-10-17 14:29:13 -0400928 Description:
pingping-lin763ee042015-05-20 17:45:30 -0700929 Adds a host-to-host intent ( bidirectional ) by
Jon Hallb1290e82014-11-18 16:17:48 -0500930 specifying the two hosts.
pingping-lin763ee042015-05-20 17:45:30 -0700931 Returns:
932 A string of the intent id or None on Error
kelvin8ec71442015-01-15 16:57:00 -0800933 """
andrewonlabe6745342014-10-17 14:29:13 -0400934 try:
kelvin-onlabd3b64892015-01-20 13:26:24 -0800935 cmdStr = "add-host-intent " + str( hostIdOne ) +\
936 " " + str( hostIdTwo )
937 handle = self.sendline( cmdStr )
Hari Krishnaac4e1782015-01-26 12:09:12 -0800938 if re.search( "Error", handle ):
939 main.log.error( "Error in adding Host intent" )
pingping-lin763ee042015-05-20 17:45:30 -0700940 main.log.debug( "Response from ONOS was: " + repr( handle ) )
941 return None
Hari Krishnaac4e1782015-01-26 12:09:12 -0800942 else:
943 main.log.info( "Host intent installed between " +
pingping-lin763ee042015-05-20 17:45:30 -0700944 str( hostIdOne ) + " and " + str( hostIdTwo ) )
945 match = re.search('id=0x([\da-f]+),', handle)
946 if match:
947 return match.group()[3:-1]
948 else:
949 main.log.error( "Error, intent ID not found" )
950 main.log.debug( "Response from ONOS was: " +
951 repr( handle ) )
952 return None
953 except TypeError:
954 main.log.exception( self.name + ": Object not as expected" )
955 return None
andrewonlabe6745342014-10-17 14:29:13 -0400956 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -0800957 main.log.error( self.name + ": EOF exception found" )
958 main.log.error( self.name + ": " + self.handle.before )
andrewonlabe6745342014-10-17 14:29:13 -0400959 main.cleanup()
960 main.exit()
pingping-lin763ee042015-05-20 17:45:30 -0700961 except Exception:
962 main.log.exception( self.name + ": Uncaught exception!" )
andrewonlabe6745342014-10-17 14:29:13 -0400963 main.cleanup()
964 main.exit()
965
kelvin-onlabd3b64892015-01-20 13:26:24 -0800966 def addOpticalIntent( self, ingressDevice, egressDevice ):
kelvin8ec71442015-01-15 16:57:00 -0800967 """
andrewonlab7b31d232014-10-24 13:31:47 -0400968 Required:
kelvin-onlabd3b64892015-01-20 13:26:24 -0800969 * ingressDevice: device id of ingress device
970 * egressDevice: device id of egress device
andrewonlab7b31d232014-10-24 13:31:47 -0400971 Optional:
972 TODO: Still needs to be implemented via dev side
pingping-lin763ee042015-05-20 17:45:30 -0700973 Description:
974 Adds an optical intent by specifying an ingress and egress device
975 Returns:
976 A string of the intent id or None on error
kelvin-onlab898a6c62015-01-16 14:13:53 -0800977 """
andrewonlab7b31d232014-10-24 13:31:47 -0400978 try:
kelvin-onlabd3b64892015-01-20 13:26:24 -0800979 cmdStr = "add-optical-intent " + str( ingressDevice ) +\
980 " " + str( egressDevice )
981 handle = self.sendline( cmdStr )
kelvin-onlab898a6c62015-01-16 14:13:53 -0800982 # If error, return error message
Jon Halle3f39ff2015-01-13 11:50:53 -0800983 if re.search( "Error", handle ):
pingping-lin763ee042015-05-20 17:45:30 -0700984 main.log.error( "Error in adding Optical intent" )
985 return None
andrewonlab7b31d232014-10-24 13:31:47 -0400986 else:
pingping-lin763ee042015-05-20 17:45:30 -0700987 main.log.info( "Optical intent installed between " +
988 str( ingressDevice ) + " and " +
989 str( egressDevice ) )
990 match = re.search('id=0x([\da-f]+),', handle)
991 if match:
992 return match.group()[3:-1]
993 else:
994 main.log.error( "Error, intent ID not found" )
995 return None
996 except TypeError:
997 main.log.exception( self.name + ": Object not as expected" )
998 return None
andrewonlab7b31d232014-10-24 13:31:47 -0400999 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08001000 main.log.error( self.name + ": EOF exception found" )
1001 main.log.error( self.name + ": " + self.handle.before )
andrewonlab7b31d232014-10-24 13:31:47 -04001002 main.cleanup()
1003 main.exit()
pingping-lin763ee042015-05-20 17:45:30 -07001004 except Exception:
1005 main.log.exception( self.name + ": Uncaught exception!" )
andrewonlab7b31d232014-10-24 13:31:47 -04001006 main.cleanup()
1007 main.exit()
1008
kelvin-onlabd3b64892015-01-20 13:26:24 -08001009 def addPointIntent(
kelvin-onlab898a6c62015-01-16 14:13:53 -08001010 self,
kelvin-onlabd3b64892015-01-20 13:26:24 -08001011 ingressDevice,
1012 egressDevice,
1013 portIngress="",
1014 portEgress="",
kelvin-onlab898a6c62015-01-16 14:13:53 -08001015 ethType="",
1016 ethSrc="",
1017 ethDst="",
1018 bandwidth="",
kelvin-onlabd3b64892015-01-20 13:26:24 -08001019 lambdaAlloc=False,
kelvin-onlab898a6c62015-01-16 14:13:53 -08001020 ipProto="",
1021 ipSrc="",
1022 ipDst="",
1023 tcpSrc="",
1024 tcpDst="" ):
kelvin8ec71442015-01-15 16:57:00 -08001025 """
andrewonlab4dbb4d82014-10-17 18:22:31 -04001026 Required:
kelvin-onlabd3b64892015-01-20 13:26:24 -08001027 * ingressDevice: device id of ingress device
1028 * egressDevice: device id of egress device
andrewonlab289e4b72014-10-21 21:24:18 -04001029 Optional:
1030 * ethType: specify ethType
kelvin8ec71442015-01-15 16:57:00 -08001031 * ethSrc: specify ethSrc ( i.e. src mac addr )
1032 * ethDst: specify ethDst ( i.e. dst mac addr )
andrewonlab0dbb6ec2014-11-06 13:46:55 -05001033 * bandwidth: specify bandwidth capacity of link
kelvin-onlabd3b64892015-01-20 13:26:24 -08001034 * lambdaAlloc: if True, intent will allocate lambda
andrewonlab40ccd8b2014-11-06 16:23:34 -05001035 for the specified intent
Jon Halle3f39ff2015-01-13 11:50:53 -08001036 * ipProto: specify ip protocol
andrewonlabf77e0cb2014-11-11 17:17:59 -05001037 * ipSrc: specify ip source address
1038 * ipDst: specify ip destination address
1039 * tcpSrc: specify tcp source port
1040 * tcpDst: specify tcp destination port
andrewonlab4dbb4d82014-10-17 18:22:31 -04001041 Description:
kelvin8ec71442015-01-15 16:57:00 -08001042 Adds a point-to-point intent ( uni-directional ) by
andrewonlab289e4b72014-10-21 21:24:18 -04001043 specifying device id's and optional fields
pingping-lin763ee042015-05-20 17:45:30 -07001044 Returns:
1045 A string of the intent id or None on error
andrewonlab289e4b72014-10-21 21:24:18 -04001046
Jon Halle3f39ff2015-01-13 11:50:53 -08001047 NOTE: This function may change depending on the
andrewonlab4dbb4d82014-10-17 18:22:31 -04001048 options developers provide for point-to-point
1049 intent via cli
kelvin8ec71442015-01-15 16:57:00 -08001050 """
andrewonlab4dbb4d82014-10-17 18:22:31 -04001051 try:
kelvin8ec71442015-01-15 16:57:00 -08001052 # If there are no optional arguments
andrewonlab0dbb6ec2014-11-06 13:46:55 -05001053 if not ethType and not ethSrc and not ethDst\
kelvin-onlabd3b64892015-01-20 13:26:24 -08001054 and not bandwidth and not lambdaAlloc \
andrewonlabfa4ff502014-11-11 16:41:30 -05001055 and not ipProto and not ipSrc and not ipDst \
1056 and not tcpSrc and not tcpDst:
andrewonlab36af3822014-11-18 17:48:18 -05001057 cmd = "add-point-intent"
andrewonlab36af3822014-11-18 17:48:18 -05001058
andrewonlab289e4b72014-10-21 21:24:18 -04001059 else:
andrewonlab36af3822014-11-18 17:48:18 -05001060 cmd = "add-point-intent"
Jon Halle3f39ff2015-01-13 11:50:53 -08001061
andrewonlab0c0a6772014-10-22 12:31:18 -04001062 if ethType:
kelvin8ec71442015-01-15 16:57:00 -08001063 cmd += " --ethType " + str( ethType )
andrewonlab289e4b72014-10-21 21:24:18 -04001064 if ethSrc:
kelvin8ec71442015-01-15 16:57:00 -08001065 cmd += " --ethSrc " + str( ethSrc )
1066 if ethDst:
1067 cmd += " --ethDst " + str( ethDst )
andrewonlab0dbb6ec2014-11-06 13:46:55 -05001068 if bandwidth:
kelvin8ec71442015-01-15 16:57:00 -08001069 cmd += " --bandwidth " + str( bandwidth )
kelvin-onlabd3b64892015-01-20 13:26:24 -08001070 if lambdaAlloc:
andrewonlabfa4ff502014-11-11 16:41:30 -05001071 cmd += " --lambda "
1072 if ipProto:
kelvin8ec71442015-01-15 16:57:00 -08001073 cmd += " --ipProto " + str( ipProto )
andrewonlabfa4ff502014-11-11 16:41:30 -05001074 if ipSrc:
kelvin8ec71442015-01-15 16:57:00 -08001075 cmd += " --ipSrc " + str( ipSrc )
andrewonlabfa4ff502014-11-11 16:41:30 -05001076 if ipDst:
kelvin8ec71442015-01-15 16:57:00 -08001077 cmd += " --ipDst " + str( ipDst )
andrewonlabfa4ff502014-11-11 16:41:30 -05001078 if tcpSrc:
kelvin8ec71442015-01-15 16:57:00 -08001079 cmd += " --tcpSrc " + str( tcpSrc )
andrewonlabfa4ff502014-11-11 16:41:30 -05001080 if tcpDst:
kelvin8ec71442015-01-15 16:57:00 -08001081 cmd += " --tcpDst " + str( tcpDst )
andrewonlab289e4b72014-10-21 21:24:18 -04001082
kelvin8ec71442015-01-15 16:57:00 -08001083 # Check whether the user appended the port
1084 # or provided it as an input
kelvin-onlabd3b64892015-01-20 13:26:24 -08001085 if "/" in ingressDevice:
1086 cmd += " " + str( ingressDevice )
andrewonlab36af3822014-11-18 17:48:18 -05001087 else:
kelvin-onlabd3b64892015-01-20 13:26:24 -08001088 if not portIngress:
pingping-lin763ee042015-05-20 17:45:30 -07001089 main.log.error( "You must specify the ingress port" )
kelvin8ec71442015-01-15 16:57:00 -08001090 # TODO: perhaps more meaningful return
pingping-lin763ee042015-05-20 17:45:30 -07001091 # Would it make sense to throw an exception and exit
1092 # the test?
1093 return None
andrewonlab36af3822014-11-18 17:48:18 -05001094
kelvin8ec71442015-01-15 16:57:00 -08001095 cmd += " " + \
kelvin-onlabd3b64892015-01-20 13:26:24 -08001096 str( ingressDevice ) + "/" +\
1097 str( portIngress ) + " "
andrewonlab36af3822014-11-18 17:48:18 -05001098
kelvin-onlabd3b64892015-01-20 13:26:24 -08001099 if "/" in egressDevice:
1100 cmd += " " + str( egressDevice )
andrewonlab36af3822014-11-18 17:48:18 -05001101 else:
kelvin-onlabd3b64892015-01-20 13:26:24 -08001102 if not portEgress:
pingping-lin763ee042015-05-20 17:45:30 -07001103 main.log.error( "You must specify the egress port" )
1104 return None
Jon Halle3f39ff2015-01-13 11:50:53 -08001105
kelvin8ec71442015-01-15 16:57:00 -08001106 cmd += " " +\
kelvin-onlabd3b64892015-01-20 13:26:24 -08001107 str( egressDevice ) + "/" +\
1108 str( portEgress )
kelvin8ec71442015-01-15 16:57:00 -08001109
kelvin-onlab898a6c62015-01-16 14:13:53 -08001110 handle = self.sendline( cmd )
pingping-lin763ee042015-05-20 17:45:30 -07001111 # If error, return error message
kelvin-onlab898a6c62015-01-16 14:13:53 -08001112 if re.search( "Error", handle ):
kelvin8ec71442015-01-15 16:57:00 -08001113 main.log.error( "Error in adding point-to-point intent" )
pingping-lin763ee042015-05-20 17:45:30 -07001114 return None
andrewonlab4dbb4d82014-10-17 18:22:31 -04001115 else:
pingping-lin763ee042015-05-20 17:45:30 -07001116 # TODO: print out all the options in this message?
1117 main.log.info( "Point-to-point intent installed between " +
1118 str( ingressDevice ) + " and " +
1119 str( egressDevice ) )
1120 match = re.search('id=0x([\da-f]+),', handle)
1121 if match:
1122 return match.group()[3:-1]
1123 else:
1124 main.log.error( "Error, intent ID not found" )
1125 return None
1126 except TypeError:
1127 main.log.exception( self.name + ": Object not as expected" )
1128 return None
andrewonlab4dbb4d82014-10-17 18:22:31 -04001129 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08001130 main.log.error( self.name + ": EOF exception found" )
1131 main.log.error( self.name + ": " + self.handle.before )
andrewonlab4dbb4d82014-10-17 18:22:31 -04001132 main.cleanup()
1133 main.exit()
pingping-lin763ee042015-05-20 17:45:30 -07001134 except Exception:
1135 main.log.exception( self.name + ": Uncaught exception!" )
andrewonlab4dbb4d82014-10-17 18:22:31 -04001136 main.cleanup()
1137 main.exit()
1138
kelvin-onlabd3b64892015-01-20 13:26:24 -08001139 def addMultipointToSinglepointIntent(
kelvin-onlab898a6c62015-01-16 14:13:53 -08001140 self,
pingping-lin763ee042015-05-20 17:45:30 -07001141 ingressDeviceList,
kelvin-onlabd3b64892015-01-20 13:26:24 -08001142 egressDevice,
pingping-lin763ee042015-05-20 17:45:30 -07001143 portIngressList=None,
kelvin-onlabd3b64892015-01-20 13:26:24 -08001144 portEgress="",
kelvin-onlab898a6c62015-01-16 14:13:53 -08001145 ethType="",
1146 ethSrc="",
1147 ethDst="",
1148 bandwidth="",
kelvin-onlabd3b64892015-01-20 13:26:24 -08001149 lambdaAlloc=False,
kelvin-onlab898a6c62015-01-16 14:13:53 -08001150 ipProto="",
1151 ipSrc="",
1152 ipDst="",
1153 tcpSrc="",
1154 tcpDst="",
1155 setEthSrc="",
1156 setEthDst="" ):
kelvin8ec71442015-01-15 16:57:00 -08001157 """
shahshreyad0c80432014-12-04 16:56:05 -08001158 Note:
pingping-lin763ee042015-05-20 17:45:30 -07001159 This function assumes the format of all ingress devices
1160 is same. That is, all ingress devices include port numbers
1161 with a "/" or all ingress devices could specify device
1162 ids and port numbers seperately.
shahshreyad0c80432014-12-04 16:56:05 -08001163 Required:
pingping-lin763ee042015-05-20 17:45:30 -07001164 * ingressDeviceList: List of device ids of ingress device
1165 ( Atleast 2 ingress devices required in the list )
kelvin-onlabd3b64892015-01-20 13:26:24 -08001166 * egressDevice: device id of egress device
shahshreyad0c80432014-12-04 16:56:05 -08001167 Optional:
1168 * ethType: specify ethType
kelvin8ec71442015-01-15 16:57:00 -08001169 * ethSrc: specify ethSrc ( i.e. src mac addr )
1170 * ethDst: specify ethDst ( i.e. dst mac addr )
shahshreyad0c80432014-12-04 16:56:05 -08001171 * bandwidth: specify bandwidth capacity of link
kelvin-onlabd3b64892015-01-20 13:26:24 -08001172 * lambdaAlloc: if True, intent will allocate lambda
shahshreyad0c80432014-12-04 16:56:05 -08001173 for the specified intent
Jon Halle3f39ff2015-01-13 11:50:53 -08001174 * ipProto: specify ip protocol
shahshreyad0c80432014-12-04 16:56:05 -08001175 * ipSrc: specify ip source address
1176 * ipDst: specify ip destination address
1177 * tcpSrc: specify tcp source port
1178 * tcpDst: specify tcp destination port
1179 * setEthSrc: action to Rewrite Source MAC Address
1180 * setEthDst: action to Rewrite Destination MAC Address
1181 Description:
kelvin8ec71442015-01-15 16:57:00 -08001182 Adds a multipoint-to-singlepoint intent ( uni-directional ) by
shahshreyad0c80432014-12-04 16:56:05 -08001183 specifying device id's and optional fields
pingping-lin763ee042015-05-20 17:45:30 -07001184 Returns:
1185 A string of the intent id or None on error
shahshreyad0c80432014-12-04 16:56:05 -08001186
Jon Halle3f39ff2015-01-13 11:50:53 -08001187 NOTE: This function may change depending on the
pingping-lin763ee042015-05-20 17:45:30 -07001188 options developers provide for multipoint-to-singlepoint
shahshreyad0c80432014-12-04 16:56:05 -08001189 intent via cli
kelvin8ec71442015-01-15 16:57:00 -08001190 """
shahshreyad0c80432014-12-04 16:56:05 -08001191 try:
kelvin8ec71442015-01-15 16:57:00 -08001192 # If there are no optional arguments
shahshreyad0c80432014-12-04 16:56:05 -08001193 if not ethType and not ethSrc and not ethDst\
kelvin-onlabd3b64892015-01-20 13:26:24 -08001194 and not bandwidth and not lambdaAlloc\
Jon Halle3f39ff2015-01-13 11:50:53 -08001195 and not ipProto and not ipSrc and not ipDst\
1196 and not tcpSrc and not tcpDst and not setEthSrc\
1197 and not setEthDst:
shahshreyad0c80432014-12-04 16:56:05 -08001198 cmd = "add-multi-to-single-intent"
shahshreyad0c80432014-12-04 16:56:05 -08001199
1200 else:
1201 cmd = "add-multi-to-single-intent"
Jon Halle3f39ff2015-01-13 11:50:53 -08001202
shahshreyad0c80432014-12-04 16:56:05 -08001203 if ethType:
kelvin8ec71442015-01-15 16:57:00 -08001204 cmd += " --ethType " + str( ethType )
shahshreyad0c80432014-12-04 16:56:05 -08001205 if ethSrc:
kelvin8ec71442015-01-15 16:57:00 -08001206 cmd += " --ethSrc " + str( ethSrc )
1207 if ethDst:
1208 cmd += " --ethDst " + str( ethDst )
shahshreyad0c80432014-12-04 16:56:05 -08001209 if bandwidth:
kelvin8ec71442015-01-15 16:57:00 -08001210 cmd += " --bandwidth " + str( bandwidth )
kelvin-onlabd3b64892015-01-20 13:26:24 -08001211 if lambdaAlloc:
shahshreyad0c80432014-12-04 16:56:05 -08001212 cmd += " --lambda "
1213 if ipProto:
kelvin8ec71442015-01-15 16:57:00 -08001214 cmd += " --ipProto " + str( ipProto )
shahshreyad0c80432014-12-04 16:56:05 -08001215 if ipSrc:
kelvin8ec71442015-01-15 16:57:00 -08001216 cmd += " --ipSrc " + str( ipSrc )
shahshreyad0c80432014-12-04 16:56:05 -08001217 if ipDst:
kelvin8ec71442015-01-15 16:57:00 -08001218 cmd += " --ipDst " + str( ipDst )
shahshreyad0c80432014-12-04 16:56:05 -08001219 if tcpSrc:
kelvin8ec71442015-01-15 16:57:00 -08001220 cmd += " --tcpSrc " + str( tcpSrc )
shahshreyad0c80432014-12-04 16:56:05 -08001221 if tcpDst:
kelvin8ec71442015-01-15 16:57:00 -08001222 cmd += " --tcpDst " + str( tcpDst )
shahshreyad0c80432014-12-04 16:56:05 -08001223 if setEthSrc:
kelvin8ec71442015-01-15 16:57:00 -08001224 cmd += " --setEthSrc " + str( setEthSrc )
shahshreyad0c80432014-12-04 16:56:05 -08001225 if setEthDst:
kelvin8ec71442015-01-15 16:57:00 -08001226 cmd += " --setEthDst " + str( setEthDst )
shahshreyad0c80432014-12-04 16:56:05 -08001227
kelvin8ec71442015-01-15 16:57:00 -08001228 # Check whether the user appended the port
1229 # or provided it as an input
pingping-lin763ee042015-05-20 17:45:30 -07001230
1231 if portIngressList is None:
1232 for ingressDevice in ingressDeviceList:
1233 if "/" in ingressDevice:
1234 cmd += " " + str( ingressDevice )
1235 else:
1236 main.log.error( "You must specify " +
1237 "the ingress port" )
1238 # TODO: perhaps more meaningful return
1239 return main.FALSE
shahshreyad0c80432014-12-04 16:56:05 -08001240 else:
pingping-lin763ee042015-05-20 17:45:30 -07001241 if len( ingressDeviceList ) == len( portIngressList ):
1242 for ingressDevice, portIngress in zip( ingressDeviceList,
1243 portIngressList ):
1244 cmd += " " + \
1245 str( ingressDevice ) + "/" +\
1246 str( portIngress ) + " "
1247 else:
1248 main.log.error( "Device list and port list does not " +
1249 "have the same length" )
shahshreyad0c80432014-12-04 16:56:05 -08001250 return main.FALSE
kelvin-onlabd3b64892015-01-20 13:26:24 -08001251 if "/" in egressDevice:
1252 cmd += " " + str( egressDevice )
shahshreyad0c80432014-12-04 16:56:05 -08001253 else:
kelvin-onlabd3b64892015-01-20 13:26:24 -08001254 if not portEgress:
kelvin8ec71442015-01-15 16:57:00 -08001255 main.log.error( "You must specify " +
1256 "the egress port" )
shahshreyad0c80432014-12-04 16:56:05 -08001257 return main.FALSE
Jon Halle3f39ff2015-01-13 11:50:53 -08001258
kelvin8ec71442015-01-15 16:57:00 -08001259 cmd += " " +\
kelvin-onlabd3b64892015-01-20 13:26:24 -08001260 str( egressDevice ) + "/" +\
1261 str( portEgress )
kelvin-onlab898a6c62015-01-16 14:13:53 -08001262 handle = self.sendline( cmd )
pingping-lin763ee042015-05-20 17:45:30 -07001263 # If error, return error message
kelvin-onlab898a6c62015-01-16 14:13:53 -08001264 if re.search( "Error", handle ):
pingping-lin763ee042015-05-20 17:45:30 -07001265 main.log.error( "Error in adding multipoint-to-singlepoint " +
1266 "intent" )
1267 return None
shahshreyad0c80432014-12-04 16:56:05 -08001268 else:
pingping-lin763ee042015-05-20 17:45:30 -07001269 match = re.search('id=0x([\da-f]+),', handle)
1270 if match:
1271 return match.group()[3:-1]
1272 else:
1273 main.log.error( "Error, intent ID not found" )
1274 return None
1275 except TypeError:
1276 main.log.exception( self.name + ": Object not as expected" )
1277 return None
shahshreyad0c80432014-12-04 16:56:05 -08001278 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08001279 main.log.error( self.name + ": EOF exception found" )
1280 main.log.error( self.name + ": " + self.handle.before )
shahshreyad0c80432014-12-04 16:56:05 -08001281 main.cleanup()
1282 main.exit()
pingping-lin763ee042015-05-20 17:45:30 -07001283 except Exception:
1284 main.log.exception( self.name + ": Uncaught exception!" )
shahshreyad0c80432014-12-04 16:56:05 -08001285 main.cleanup()
1286 main.exit()
1287
pingping-lin763ee042015-05-20 17:45:30 -07001288 def addSinglepointToMultipointIntent(
1289 self,
1290 ingressDevice,
1291 egressDeviceList,
1292 portIngress="",
1293 portEgressList=None,
1294 ethType="",
1295 ethSrc="",
1296 ethDst="",
1297 bandwidth="",
1298 lambdaAlloc=False,
1299 ipProto="",
1300 ipSrc="",
1301 ipDst="",
1302 tcpSrc="",
1303 tcpDst="",
1304 setEthSrc="",
1305 setEthDst="" ):
kelvin-onlab898a6c62015-01-16 14:13:53 -08001306 """
pingping-lin763ee042015-05-20 17:45:30 -07001307 Note:
1308 This function assumes the format of all egress devices
1309 is same. That is, all egress devices include port numbers
1310 with a "/" or all egress devices could specify device
1311 ids and port numbers seperately.
1312 Required:
1313 * EgressDeviceList: List of device ids of egress device
1314 ( Atleast 2 eress devices required in the list )
1315 * ingressDevice: device id of ingress device
1316 Optional:
1317 * ethType: specify ethType
1318 * ethSrc: specify ethSrc ( i.e. src mac addr )
1319 * ethDst: specify ethDst ( i.e. dst mac addr )
1320 * bandwidth: specify bandwidth capacity of link
1321 * lambdaAlloc: if True, intent will allocate lambda
1322 for the specified intent
1323 * ipProto: specify ip protocol
1324 * ipSrc: specify ip source address
1325 * ipDst: specify ip destination address
1326 * tcpSrc: specify tcp source port
1327 * tcpDst: specify tcp destination port
1328 * setEthSrc: action to Rewrite Source MAC Address
1329 * setEthDst: action to Rewrite Destination MAC Address
1330 Description:
1331 Adds a singlepoint-to-multipoint intent ( uni-directional ) by
1332 specifying device id's and optional fields
1333 Returns:
1334 A string of the intent id or None on error
1335
1336 NOTE: This function may change depending on the
1337 options developers provide for singlepoint-to-multipoint
1338 intent via cli
1339 """
1340 try:
1341 # If there are no optional arguments
1342 if not ethType and not ethSrc and not ethDst\
1343 and not bandwidth and not lambdaAlloc\
1344 and not ipProto and not ipSrc and not ipDst\
1345 and not tcpSrc and not tcpDst and not setEthSrc\
1346 and not setEthDst:
1347 cmd = "add-single-to-multi-intent"
1348
1349 else:
1350 cmd = "add-single-to-multi-intent"
1351
1352 if ethType:
1353 cmd += " --ethType " + str( ethType )
1354 if ethSrc:
1355 cmd += " --ethSrc " + str( ethSrc )
1356 if ethDst:
1357 cmd += " --ethDst " + str( ethDst )
1358 if bandwidth:
1359 cmd += " --bandwidth " + str( bandwidth )
1360 if lambdaAlloc:
1361 cmd += " --lambda "
1362 if ipProto:
1363 cmd += " --ipProto " + str( ipProto )
1364 if ipSrc:
1365 cmd += " --ipSrc " + str( ipSrc )
1366 if ipDst:
1367 cmd += " --ipDst " + str( ipDst )
1368 if tcpSrc:
1369 cmd += " --tcpSrc " + str( tcpSrc )
1370 if tcpDst:
1371 cmd += " --tcpDst " + str( tcpDst )
1372 if setEthSrc:
1373 cmd += " --setEthSrc " + str( setEthSrc )
1374 if setEthDst:
1375 cmd += " --setEthDst " + str( setEthDst )
1376
1377 # Check whether the user appended the port
1378 # or provided it as an input
1379
1380 if "/" in ingressDevice:
1381 cmd += " " + str( ingressDevice )
1382 else:
1383 if not portIngress:
1384 main.log.error( "You must specify " +
1385 "the Ingress port" )
1386 return main.FALSE
1387
1388 cmd += " " +\
1389 str( ingressDevice ) + "/" +\
1390 str( portIngress )
1391
1392 if portEgressList is None:
1393 for egressDevice in egressDeviceList:
1394 if "/" in egressDevice:
1395 cmd += " " + str( egressDevice )
1396 else:
1397 main.log.error( "You must specify " +
1398 "the egress port" )
1399 # TODO: perhaps more meaningful return
1400 return main.FALSE
1401 else:
1402 if len( egressDeviceList ) == len( portEgressList ):
1403 for egressDevice, portEgress in zip( egressDeviceList,
1404 portEgressList ):
1405 cmd += " " + \
1406 str( egressDevice ) + "/" +\
1407 str( portEgress )
1408 else:
1409 main.log.error( "Device list and port list does not " +
1410 "have the same length" )
1411 return main.FALSE
1412 handle = self.sendline( cmd )
1413 # If error, return error message
1414 if re.search( "Error", handle ):
1415 main.log.error( "Error in adding singlepoint-to-multipoint " +
1416 "intent" )
1417 return None
1418 else:
1419 match = re.search('id=0x([\da-f]+),', handle)
1420 if match:
1421 return match.group()[3:-1]
1422 else:
1423 main.log.error( "Error, intent ID not found" )
1424 return None
1425 except TypeError:
1426 main.log.exception( self.name + ": Object not as expected" )
1427 return None
1428 except pexpect.EOF:
1429 main.log.error( self.name + ": EOF exception found" )
1430 main.log.error( self.name + ": " + self.handle.before )
1431 main.cleanup()
1432 main.exit()
1433 except Exception:
1434 main.log.exception( self.name + ": Uncaught exception!" )
1435 main.cleanup()
1436 main.exit()
1437
1438 def addMplsIntent(
1439 self,
1440 ingressDevice,
1441 egressDevice,
1442 ingressPort="",
1443 egressPort="",
1444 ethType="",
1445 ethSrc="",
1446 ethDst="",
1447 bandwidth="",
1448 lambdaAlloc=False,
1449 ipProto="",
1450 ipSrc="",
1451 ipDst="",
1452 tcpSrc="",
1453 tcpDst="",
1454 ingressLabel="",
1455 egressLabel="",
1456 priority=""):
1457 """
1458 Required:
1459 * ingressDevice: device id of ingress device
1460 * egressDevice: device id of egress device
1461 Optional:
1462 * ethType: specify ethType
1463 * ethSrc: specify ethSrc ( i.e. src mac addr )
1464 * ethDst: specify ethDst ( i.e. dst mac addr )
1465 * bandwidth: specify bandwidth capacity of link
1466 * lambdaAlloc: if True, intent will allocate lambda
1467 for the specified intent
1468 * ipProto: specify ip protocol
1469 * ipSrc: specify ip source address
1470 * ipDst: specify ip destination address
1471 * tcpSrc: specify tcp source port
1472 * tcpDst: specify tcp destination port
1473 * ingressLabel: Ingress MPLS label
1474 * egressLabel: Egress MPLS label
1475 Description:
1476 Adds MPLS intent by
1477 specifying device id's and optional fields
1478 Returns:
1479 A string of the intent id or None on error
1480
1481 NOTE: This function may change depending on the
1482 options developers provide for MPLS
1483 intent via cli
1484 """
1485 try:
1486 # If there are no optional arguments
1487 if not ethType and not ethSrc and not ethDst\
1488 and not bandwidth and not lambdaAlloc \
1489 and not ipProto and not ipSrc and not ipDst \
1490 and not tcpSrc and not tcpDst and not ingressLabel \
1491 and not egressLabel:
1492 cmd = "add-mpls-intent"
1493
1494 else:
1495 cmd = "add-mpls-intent"
1496
1497 if ethType:
1498 cmd += " --ethType " + str( ethType )
1499 if ethSrc:
1500 cmd += " --ethSrc " + str( ethSrc )
1501 if ethDst:
1502 cmd += " --ethDst " + str( ethDst )
1503 if bandwidth:
1504 cmd += " --bandwidth " + str( bandwidth )
1505 if lambdaAlloc:
1506 cmd += " --lambda "
1507 if ipProto:
1508 cmd += " --ipProto " + str( ipProto )
1509 if ipSrc:
1510 cmd += " --ipSrc " + str( ipSrc )
1511 if ipDst:
1512 cmd += " --ipDst " + str( ipDst )
1513 if tcpSrc:
1514 cmd += " --tcpSrc " + str( tcpSrc )
1515 if tcpDst:
1516 cmd += " --tcpDst " + str( tcpDst )
1517 if ingressLabel:
1518 cmd += " --ingressLabel " + str( ingressLabel )
1519 if egressLabel:
1520 cmd += " --egressLabel " + str( egressLabel )
1521 if priority:
1522 cmd += " --priority " + str( priority )
1523
1524 # Check whether the user appended the port
1525 # or provided it as an input
1526 if "/" in ingressDevice:
1527 cmd += " " + str( ingressDevice )
1528 else:
1529 if not ingressPort:
1530 main.log.error( "You must specify the ingress port" )
1531 return None
1532
1533 cmd += " " + \
1534 str( ingressDevice ) + "/" +\
1535 str( ingressPort ) + " "
1536
1537 if "/" in egressDevice:
1538 cmd += " " + str( egressDevice )
1539 else:
1540 if not egressPort:
1541 main.log.error( "You must specify the egress port" )
1542 return None
1543
1544 cmd += " " +\
1545 str( egressDevice ) + "/" +\
1546 str( egressPort )
1547
1548 handle = self.sendline( cmd )
1549 # If error, return error message
1550 if re.search( "Error", handle ):
1551 main.log.error( "Error in adding mpls intent" )
1552 return None
1553 else:
1554 # TODO: print out all the options in this message?
1555 main.log.info( "MPLS intent installed between " +
1556 str( ingressDevice ) + " and " +
1557 str( egressDevice ) )
1558 match = re.search('id=0x([\da-f]+),', handle)
1559 if match:
1560 return match.group()[3:-1]
1561 else:
1562 main.log.error( "Error, intent ID not found" )
1563 return None
1564 except TypeError:
1565 main.log.exception( self.name + ": Object not as expected" )
1566 return None
1567 except pexpect.EOF:
1568 main.log.error( self.name + ": EOF exception found" )
1569 main.log.error( self.name + ": " + self.handle.before )
1570 main.cleanup()
1571 main.exit()
1572 except Exception:
1573 main.log.exception( self.name + ": Uncaught exception!" )
1574 main.cleanup()
1575 main.exit()
1576
1577 def removeIntent( self, intentId, app='org.onosproject.cli',
1578 purge=False, sync=False ):
1579 """
1580 Remove intent for specified application id and intent id
1581 Optional args:-
1582 -s or --sync: Waits for the removal before returning
1583 -p or --purge: Purge the intent from the store after removal
Jon Halle3f39ff2015-01-13 11:50:53 -08001584
1585 Returns:
1586 main.False on error and
1587 cli output otherwise
kelvin-onlab898a6c62015-01-16 14:13:53 -08001588 """
andrewonlab9a50dfe2014-10-17 17:22:31 -04001589 try:
pingping-lin763ee042015-05-20 17:45:30 -07001590 cmdStr = "remove-intent"
1591 if purge:
1592 cmdStr += " -p"
1593 if sync:
1594 cmdStr += " -s"
1595
1596 cmdStr += " " + app + " " + str( intentId )
kelvin-onlabd3b64892015-01-20 13:26:24 -08001597 handle = self.sendline( cmdStr )
Jon Halle3f39ff2015-01-13 11:50:53 -08001598 if re.search( "Error", handle ):
kelvin-onlab898a6c62015-01-16 14:13:53 -08001599 main.log.error( "Error in removing intent" )
Jon Halle3f39ff2015-01-13 11:50:53 -08001600 return main.FALSE
andrewonlab9a50dfe2014-10-17 17:22:31 -04001601 else:
Jon Halle3f39ff2015-01-13 11:50:53 -08001602 # TODO: Should this be main.TRUE
1603 return handle
pingping-lin763ee042015-05-20 17:45:30 -07001604 except TypeError:
1605 main.log.exception( self.name + ": Object not as expected" )
1606 return None
andrewonlab9a50dfe2014-10-17 17:22:31 -04001607 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08001608 main.log.error( self.name + ": EOF exception found" )
1609 main.log.error( self.name + ": " + self.handle.before )
andrewonlab9a50dfe2014-10-17 17:22:31 -04001610 main.cleanup()
1611 main.exit()
pingping-lin763ee042015-05-20 17:45:30 -07001612 except Exception:
1613 main.log.exception( self.name + ": Uncaught exception!" )
andrewonlab9a50dfe2014-10-17 17:22:31 -04001614 main.cleanup()
1615 main.exit()
1616
kelvin-onlabd3b64892015-01-20 13:26:24 -08001617 def routes( self, jsonFormat=False ):
kelvin8ec71442015-01-15 16:57:00 -08001618 """
kelvin-onlab898a6c62015-01-16 14:13:53 -08001619 NOTE: This method should be used after installing application:
1620 onos-app-sdnip
pingping-lin8b306ac2014-11-17 18:13:51 -08001621 Optional:
kelvin-onlabd3b64892015-01-20 13:26:24 -08001622 * jsonFormat: enable output formatting in json
pingping-lin8b306ac2014-11-17 18:13:51 -08001623 Description:
1624 Obtain all routes in the system
kelvin8ec71442015-01-15 16:57:00 -08001625 """
pingping-lin8b306ac2014-11-17 18:13:51 -08001626 try:
pingping-lin763ee042015-05-20 17:45:30 -07001627 cmdStr = "routes"
kelvin-onlabd3b64892015-01-20 13:26:24 -08001628 if jsonFormat:
pingping-lin763ee042015-05-20 17:45:30 -07001629 cmdStr += " -j"
1630 handle = self.sendline( cmdStr )
pingping-lin8b306ac2014-11-17 18:13:51 -08001631 return handle
pingping-lin763ee042015-05-20 17:45:30 -07001632 except TypeError:
1633 main.log.exception( self.name + ": Object not as expected" )
1634 return None
pingping-lin8b306ac2014-11-17 18:13:51 -08001635 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08001636 main.log.error( self.name + ": EOF exception found" )
1637 main.log.error( self.name + ": " + self.handle.before )
pingping-lin8b306ac2014-11-17 18:13:51 -08001638 main.cleanup()
1639 main.exit()
pingping-lin763ee042015-05-20 17:45:30 -07001640 except Exception:
1641 main.log.exception( self.name + ": Uncaught exception!" )
pingping-lin8b306ac2014-11-17 18:13:51 -08001642 main.cleanup()
1643 main.exit()
1644
kelvin-onlabd3b64892015-01-20 13:26:24 -08001645 def intents( self, jsonFormat=True ):
kelvin8ec71442015-01-15 16:57:00 -08001646 """
andrewonlab377693f2014-10-21 16:00:30 -04001647 Optional:
kelvin-onlabd3b64892015-01-20 13:26:24 -08001648 * jsonFormat: enable output formatting in json
andrewonlabe6745342014-10-17 14:29:13 -04001649 Description:
Jon Halle3f39ff2015-01-13 11:50:53 -08001650 Obtain intents currently installed
kelvin-onlab898a6c62015-01-16 14:13:53 -08001651 """
andrewonlabe6745342014-10-17 14:29:13 -04001652 try:
pingping-lin763ee042015-05-20 17:45:30 -07001653 cmdStr = "intents"
kelvin-onlabd3b64892015-01-20 13:26:24 -08001654 if jsonFormat:
pingping-lin763ee042015-05-20 17:45:30 -07001655 cmdStr += " -j"
1656 handle = self.sendline( cmdStr )
andrewonlabe6745342014-10-17 14:29:13 -04001657 return handle
pingping-lin763ee042015-05-20 17:45:30 -07001658 except TypeError:
1659 main.log.exception( self.name + ": Object not as expected" )
1660 return None
andrewonlabe6745342014-10-17 14:29:13 -04001661 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08001662 main.log.error( self.name + ": EOF exception found" )
1663 main.log.error( self.name + ": " + self.handle.before )
andrewonlabe6745342014-10-17 14:29:13 -04001664 main.cleanup()
1665 main.exit()
pingping-lin763ee042015-05-20 17:45:30 -07001666 except Exception:
1667 main.log.exception( self.name + ": Uncaught exception!" )
1668 main.cleanup()
1669 main.exit()
1670
1671 def getIntentState(self, intentsId, intentsJson=None):
1672 """
1673 Check intent state.
1674 Accepts a single intent ID (string type) or a list of intent IDs.
1675 Returns the state(string type) of the id if a single intent ID is
1676 accepted.
1677 Returns a dictionary with intent IDs as the key and its
1678 corresponding states as the values
1679 Parameters:
1680 intentId: intent ID (string type)
1681 intentsJson: parsed json object from the onos:intents api
1682 Returns:
1683 state = An intent's state- INSTALL,WITHDRAWN etc.
1684 stateDict = Dictionary of intent's state. intent ID as the keys and
1685 state as the values.
1686 """
1687 try:
1688 state = "State is Undefined"
1689 if not intentsJson:
1690 intentsJsonTemp = json.loads( self.intents() )
1691 else:
1692 intentsJsonTemp = json.loads( intentsJson )
1693 if isinstance( intentsId, types.StringType ):
1694 for intent in intentsJsonTemp:
1695 if intentsId == intent[ 'id' ]:
1696 state = intent[ 'state' ]
1697 return state
1698 main.log.info( "Cannot find intent ID" + str( intentsId ) +
1699 " on the list" )
1700 return state
1701 elif isinstance( intentsId, types.ListType ):
1702 dictList = []
1703 for i in xrange( len( intentsId ) ):
1704 stateDict = {}
1705 for intents in intentsJsonTemp:
1706 if intentsId[ i ] == intents[ 'id' ]:
1707 stateDict[ 'state' ] = intents[ 'state' ]
1708 stateDict[ 'id' ] = intentsId[ i ]
1709 dictList.append( stateDict )
1710 break
1711 if len( intentsId ) != len( dictList ):
1712 main.log.info( "Cannot find some of the intent ID state" )
1713 return dictList
1714 else:
1715 main.log.info( "Invalid intents ID entry" )
1716 return None
1717 except TypeError:
1718 main.log.exception( self.name + ": Object not as expected" )
1719 return None
1720 except pexpect.EOF:
1721 main.log.error( self.name + ": EOF exception found" )
1722 main.log.error( self.name + ": " + self.handle.before )
1723 main.cleanup()
1724 main.exit()
1725 except Exception:
1726 main.log.exception( self.name + ": Uncaught exception!" )
1727 main.cleanup()
1728 main.exit()
1729
1730 def checkIntentState( self, intentsId, expectedState = 'INSTALLED' ):
1731 """
1732 Description:
1733 Check intents state
1734 Required:
1735 intentsId - List of intents ID to be checked
1736 Optional:
1737 expectedState - Check this expected state of each intents state
1738 in the list. Defaults to INSTALLED
1739 Return:
1740 Returns main.TRUE only if all intent are the same as expectedState,
1741 , otherwise,returns main.FALSE.
1742 """
1743 try:
1744 # Generating a dictionary: intent id as a key and state as value
1745 intentsDict = self.getIntentState( intentsId )
1746 #print "len of intentsDict ", str( len( intentsDict ) )
1747 if len( intentsId ) != len( intentsDict ):
1748 main.log.info( self.name + "There is something wrong " +
1749 "getting intents state" )
1750 return main.FALSE
1751 returnValue = main.TRUE
1752 for intents in intentsDict:
1753 if intents.get( 'state' ) != expectedState:
1754 main.log.info( self.name + " : " + intents.get( 'id' ) +
1755 " actual state = " + intents.get( 'state' )
1756 + " does not equal expected state = "
1757 + expectedState )
1758 returnValue = main.FALSE
1759 if returnValue == main.TRUE:
1760 main.log.info( self.name + ": All " +
1761 str( len( intentsDict ) ) +
1762 " intents are in " + expectedState + " state")
1763 return returnValue
1764 except TypeError:
1765 main.log.exception( self.name + ": Object not as expected" )
1766 return None
1767 except pexpect.EOF:
1768 main.log.error( self.name + ": EOF exception found" )
1769 main.log.error( self.name + ": " + self.handle.before )
1770 main.cleanup()
1771 main.exit()
1772 except Exception:
1773 main.log.exception( self.name + ": Uncaught exception!" )
andrewonlabe6745342014-10-17 14:29:13 -04001774 main.cleanup()
1775 main.exit()
1776
kelvin-onlabd3b64892015-01-20 13:26:24 -08001777 def flows( self, jsonFormat=True ):
kelvin8ec71442015-01-15 16:57:00 -08001778 """
Shreya Shah0f01c812014-10-26 20:15:28 -04001779 Optional:
kelvin-onlabd3b64892015-01-20 13:26:24 -08001780 * jsonFormat: enable output formatting in json
Shreya Shah0f01c812014-10-26 20:15:28 -04001781 Description:
Jon Halle3f39ff2015-01-13 11:50:53 -08001782 Obtain flows currently installed
kelvin-onlab898a6c62015-01-16 14:13:53 -08001783 """
Shreya Shah0f01c812014-10-26 20:15:28 -04001784 try:
pingping-lin763ee042015-05-20 17:45:30 -07001785 cmdStr = "flows"
kelvin-onlabd3b64892015-01-20 13:26:24 -08001786 if jsonFormat:
pingping-lin763ee042015-05-20 17:45:30 -07001787 cmdStr += " -j"
1788 handle = self.sendline( cmdStr )
1789 if re.search( "Error:", handle ):
kelvin-onlab898a6c62015-01-16 14:13:53 -08001790 main.log.error( self.name + ".flows() response: " +
1791 str( handle ) )
Shreya Shah0f01c812014-10-26 20:15:28 -04001792 return handle
pingping-lin763ee042015-05-20 17:45:30 -07001793 except TypeError:
1794 main.log.exception( self.name + ": Object not as expected" )
1795 return None
Shreya Shah0f01c812014-10-26 20:15:28 -04001796 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08001797 main.log.error( self.name + ": EOF exception found" )
1798 main.log.error( self.name + ": " + self.handle.before )
Shreya Shah0f01c812014-10-26 20:15:28 -04001799 main.cleanup()
1800 main.exit()
pingping-lin763ee042015-05-20 17:45:30 -07001801 except Exception:
1802 main.log.exception( self.name + ": Uncaught exception!" )
1803 main.cleanup()
1804 main.exit()
1805
1806 def checkFlowsState( self ):
1807 """
1808 Description:
1809 Check the if all the current flows are in ADDED state or
1810 PENDING_ADD state
1811 Return:
1812 returnValue - Returns main.TRUE only if all flows are in
1813 ADDED state or PENDING_ADD, return main.FALSE
1814 otherwise.
1815 """
1816 try:
1817 tempFlows = json.loads( self.flows() )
kelvin-onlabf0594d72015-05-19 17:25:12 -07001818 #print tempFlows[0]
pingping-lin763ee042015-05-20 17:45:30 -07001819 returnValue = main.TRUE
kelvin-onlabf0594d72015-05-19 17:25:12 -07001820
pingping-lin763ee042015-05-20 17:45:30 -07001821 for device in tempFlows:
1822 for flow in device.get( 'flows' ):
1823 if flow.get( 'state' ) != 'ADDED' and flow.get( 'state' ) != \
1824 'PENDING_ADD':
1825 main.log.info( self.name + ": flow Id: " +
kelvin-onlabf0594d72015-05-19 17:25:12 -07001826 flow.get( 'groupId' ) +
pingping-lin763ee042015-05-20 17:45:30 -07001827 " | state:" + flow.get( 'state' ) )
1828 returnValue = main.FALSE
kelvin-onlabf0594d72015-05-19 17:25:12 -07001829
pingping-lin763ee042015-05-20 17:45:30 -07001830 return returnValue
1831 except TypeError:
1832 main.log.exception( self.name + ": Object not as expected" )
1833 return None
1834 except pexpect.EOF:
1835 main.log.error( self.name + ": EOF exception found" )
1836 main.log.error( self.name + ": " + self.handle.before )
1837 main.cleanup()
1838 main.exit()
1839 except Exception:
1840 main.log.exception( self.name + ": Uncaught exception!" )
Shreya Shah0f01c812014-10-26 20:15:28 -04001841 main.cleanup()
1842 main.exit()
1843
kelvin-onlabd3b64892015-01-20 13:26:24 -08001844 def pushTestIntents( self, dpidSrc, dpidDst, numIntents,
pingping-lin763ee042015-05-20 17:45:30 -07001845 numMult="", appId="", report=True ):
kelvin8ec71442015-01-15 16:57:00 -08001846 """
andrewonlab87852b02014-11-19 18:44:19 -05001847 Description:
Jon Halle3f39ff2015-01-13 11:50:53 -08001848 Push a number of intents in a batch format to
andrewonlab87852b02014-11-19 18:44:19 -05001849 a specific point-to-point intent definition
1850 Required:
kelvin-onlabd3b64892015-01-20 13:26:24 -08001851 * dpidSrc: specify source dpid
1852 * dpidDst: specify destination dpid
1853 * numIntents: specify number of intents to push
andrewonlab87852b02014-11-19 18:44:19 -05001854 Optional:
kelvin-onlabd3b64892015-01-20 13:26:24 -08001855 * numMult: number multiplier for multiplying
andrewonlabb66dfa12014-12-02 15:51:10 -05001856 the number of intents specified
kelvin-onlabd3b64892015-01-20 13:26:24 -08001857 * appId: specify the application id init to further
andrewonlabb66dfa12014-12-02 15:51:10 -05001858 modularize the intents
andrewonlab87852b02014-11-19 18:44:19 -05001859 * report: default True, returns latency information
kelvin8ec71442015-01-15 16:57:00 -08001860 """
andrewonlab87852b02014-11-19 18:44:19 -05001861 try:
kelvin8ec71442015-01-15 16:57:00 -08001862 cmd = "push-test-intents " +\
kelvin-onlabd3b64892015-01-20 13:26:24 -08001863 str( dpidSrc ) + " " + str( dpidDst ) + " " +\
1864 str( numIntents )
1865 if numMult:
1866 cmd += " " + str( numMult )
1867 # If app id is specified, then numMult
kelvin8ec71442015-01-15 16:57:00 -08001868 # must exist because of the way this command
kelvin-onlabd3b64892015-01-20 13:26:24 -08001869 if appId:
1870 cmd += " " + str( appId )
kelvin-onlab898a6c62015-01-16 14:13:53 -08001871 handle = self.sendline( cmd )
andrewonlab87852b02014-11-19 18:44:19 -05001872 if report:
kelvin-onlabd3b64892015-01-20 13:26:24 -08001873 latResult = []
kelvin8ec71442015-01-15 16:57:00 -08001874 main.log.info( handle )
1875 # Split result by newline
1876 newline = handle.split( "\r\r\n" )
1877 # Ignore the first object of list, which is empty
1878 newline = newline[ 1: ]
1879 # Some sloppy parsing method to get the latency
andrewonlabb66dfa12014-12-02 15:51:10 -05001880 for result in newline:
kelvin8ec71442015-01-15 16:57:00 -08001881 result = result.split( ": " )
1882 # Append the first result of second parse
kelvin-onlabd3b64892015-01-20 13:26:24 -08001883 latResult.append( result[ 1 ].split( " " )[ 0 ] )
1884 main.log.info( latResult )
1885 return latResult
andrewonlab87852b02014-11-19 18:44:19 -05001886 else:
1887 return main.TRUE
pingping-lin763ee042015-05-20 17:45:30 -07001888 except TypeError:
1889 main.log.exception( self.name + ": Object not as expected" )
1890 return None
andrewonlab87852b02014-11-19 18:44:19 -05001891 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08001892 main.log.error( self.name + ": EOF exception found" )
1893 main.log.error( self.name + ": " + self.handle.before )
andrewonlab87852b02014-11-19 18:44:19 -05001894 main.cleanup()
1895 main.exit()
pingping-lin763ee042015-05-20 17:45:30 -07001896 except Exception:
1897 main.log.exception( self.name + ": Uncaught exception!" )
andrewonlab87852b02014-11-19 18:44:19 -05001898 main.cleanup()
1899 main.exit()
1900
kelvin-onlabd3b64892015-01-20 13:26:24 -08001901 def intentsEventsMetrics( self, jsonFormat=True ):
kelvin8ec71442015-01-15 16:57:00 -08001902 """
Jon Halle3f39ff2015-01-13 11:50:53 -08001903 Description:Returns topology metrics
andrewonlab0dbb6ec2014-11-06 13:46:55 -05001904 Optional:
kelvin-onlabd3b64892015-01-20 13:26:24 -08001905 * jsonFormat: enable json formatting of output
kelvin8ec71442015-01-15 16:57:00 -08001906 """
andrewonlab0dbb6ec2014-11-06 13:46:55 -05001907 try:
pingping-lin763ee042015-05-20 17:45:30 -07001908 cmdStr = "intents-events-metrics"
kelvin-onlabd3b64892015-01-20 13:26:24 -08001909 if jsonFormat:
pingping-lin763ee042015-05-20 17:45:30 -07001910 cmdStr += " -j"
1911 handle = self.sendline( cmdStr )
andrewonlab0dbb6ec2014-11-06 13:46:55 -05001912 return handle
pingping-lin763ee042015-05-20 17:45:30 -07001913 except TypeError:
1914 main.log.exception( self.name + ": Object not as expected" )
1915 return None
andrewonlab0dbb6ec2014-11-06 13:46:55 -05001916 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08001917 main.log.error( self.name + ": EOF exception found" )
1918 main.log.error( self.name + ": " + self.handle.before )
andrewonlab0dbb6ec2014-11-06 13:46:55 -05001919 main.cleanup()
1920 main.exit()
pingping-lin763ee042015-05-20 17:45:30 -07001921 except Exception:
1922 main.log.exception( self.name + ": Uncaught exception!" )
andrewonlab0dbb6ec2014-11-06 13:46:55 -05001923 main.cleanup()
1924 main.exit()
Shreya Shah0f01c812014-10-26 20:15:28 -04001925
kelvin-onlabd3b64892015-01-20 13:26:24 -08001926 def topologyEventsMetrics( self, jsonFormat=True ):
kelvin8ec71442015-01-15 16:57:00 -08001927 """
1928 Description:Returns topology metrics
andrewonlab867212a2014-10-22 20:13:38 -04001929 Optional:
kelvin-onlabd3b64892015-01-20 13:26:24 -08001930 * jsonFormat: enable json formatting of output
kelvin8ec71442015-01-15 16:57:00 -08001931 """
andrewonlab867212a2014-10-22 20:13:38 -04001932 try:
pingping-lin763ee042015-05-20 17:45:30 -07001933 cmdStr = "topology-events-metrics"
kelvin-onlabd3b64892015-01-20 13:26:24 -08001934 if jsonFormat:
pingping-lin763ee042015-05-20 17:45:30 -07001935 cmdStr += " -j"
1936 handle = self.sendline( cmdStr )
1937 if handle:
1938 return handle
1939 elif jsonFormat:
1940 # Return empty json
1941 return '{}'
andrewonlab867212a2014-10-22 20:13:38 -04001942 else:
pingping-lin763ee042015-05-20 17:45:30 -07001943 return handle
1944 except TypeError:
1945 main.log.exception( self.name + ": Object not as expected" )
1946 return None
andrewonlab867212a2014-10-22 20:13:38 -04001947 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08001948 main.log.error( self.name + ": EOF exception found" )
1949 main.log.error( self.name + ": " + self.handle.before )
andrewonlab867212a2014-10-22 20:13:38 -04001950 main.cleanup()
1951 main.exit()
pingping-lin763ee042015-05-20 17:45:30 -07001952 except Exception:
1953 main.log.exception( self.name + ": Uncaught exception!" )
andrewonlab867212a2014-10-22 20:13:38 -04001954 main.cleanup()
1955 main.exit()
1956
kelvin8ec71442015-01-15 16:57:00 -08001957 # Wrapper functions ****************
1958 # Wrapper functions use existing driver
1959 # functions and extends their use case.
1960 # For example, we may use the output of
1961 # a normal driver function, and parse it
1962 # using a wrapper function
andrewonlabc2d05aa2014-10-13 16:51:10 -04001963
kelvin-onlabd3b64892015-01-20 13:26:24 -08001964 def getAllIntentsId( self ):
kelvin8ec71442015-01-15 16:57:00 -08001965 """
andrewonlab9a50dfe2014-10-17 17:22:31 -04001966 Description:
1967 Obtain all intent id's in a list
kelvin8ec71442015-01-15 16:57:00 -08001968 """
andrewonlab9a50dfe2014-10-17 17:22:31 -04001969 try:
kelvin8ec71442015-01-15 16:57:00 -08001970 # Obtain output of intents function
pingping-lin763ee042015-05-20 17:45:30 -07001971 intentsStr = self.intents(jsonFormat=False)
kelvin-onlabd3b64892015-01-20 13:26:24 -08001972 intentIdList = []
andrewonlab9a50dfe2014-10-17 17:22:31 -04001973
kelvin8ec71442015-01-15 16:57:00 -08001974 # Parse the intents output for ID's
kelvin-onlabd3b64892015-01-20 13:26:24 -08001975 intentsList = [ s.strip() for s in intentsStr.splitlines() ]
1976 for intents in intentsList:
pingping-lin763ee042015-05-20 17:45:30 -07001977 match = re.search('id=0x([\da-f]+),', intents)
1978 if match:
1979 tmpId = match.group()[3:-1]
1980 intentIdList.append( tmpId )
kelvin-onlabd3b64892015-01-20 13:26:24 -08001981 return intentIdList
andrewonlab9a50dfe2014-10-17 17:22:31 -04001982
pingping-lin763ee042015-05-20 17:45:30 -07001983 except TypeError:
1984 main.log.exception( self.name + ": Object not as expected" )
1985 return None
andrewonlab9a50dfe2014-10-17 17:22:31 -04001986 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08001987 main.log.error( self.name + ": EOF exception found" )
1988 main.log.error( self.name + ": " + self.handle.before )
andrewonlab9a50dfe2014-10-17 17:22:31 -04001989 main.cleanup()
1990 main.exit()
pingping-lin763ee042015-05-20 17:45:30 -07001991 except Exception:
1992 main.log.exception( self.name + ": Uncaught exception!" )
1993 main.cleanup()
1994 main.exit()
1995
1996 def FlowAddedCount( self, deviceId ):
1997 """
1998 Determine the number of flow rules for the given device id that are
1999 in the added state
2000 """
2001 try:
2002 cmdStr = "flows any " + str( deviceId ) + " | " +\
2003 "grep 'state=ADDED' | wc -l"
2004 handle = self.sendline( cmdStr )
2005 return handle
2006 except pexpect.EOF:
2007 main.log.error( self.name + ": EOF exception found" )
2008 main.log.error( self.name + ": " + self.handle.before )
2009 main.cleanup()
2010 main.exit()
2011 except Exception:
2012 main.log.exception( self.name + ": Uncaught exception!" )
andrewonlab9a50dfe2014-10-17 17:22:31 -04002013 main.cleanup()
2014 main.exit()
2015
kelvin-onlabd3b64892015-01-20 13:26:24 -08002016 def getAllDevicesId( self ):
kelvin8ec71442015-01-15 16:57:00 -08002017 """
andrewonlab7e4d2d32014-10-15 13:23:21 -04002018 Use 'devices' function to obtain list of all devices
2019 and parse the result to obtain a list of all device
2020 id's. Returns this list. Returns empty list if no
2021 devices exist
kelvin8ec71442015-01-15 16:57:00 -08002022 List is ordered sequentially
2023
andrewonlab3e15ead2014-10-15 14:21:34 -04002024 This function may be useful if you are not sure of the
kelvin8ec71442015-01-15 16:57:00 -08002025 device id, and wish to execute other commands using
andrewonlab3e15ead2014-10-15 14:21:34 -04002026 the ids. By obtaining the list of device ids on the fly,
2027 you can iterate through the list to get mastership, etc.
kelvin8ec71442015-01-15 16:57:00 -08002028 """
andrewonlab7e4d2d32014-10-15 13:23:21 -04002029 try:
kelvin8ec71442015-01-15 16:57:00 -08002030 # Call devices and store result string
kelvin-onlabd3b64892015-01-20 13:26:24 -08002031 devicesStr = self.devices( jsonFormat=False )
2032 idList = []
kelvin8ec71442015-01-15 16:57:00 -08002033
kelvin-onlabd3b64892015-01-20 13:26:24 -08002034 if not devicesStr:
kelvin8ec71442015-01-15 16:57:00 -08002035 main.log.info( "There are no devices to get id from" )
kelvin-onlabd3b64892015-01-20 13:26:24 -08002036 return idList
kelvin8ec71442015-01-15 16:57:00 -08002037
2038 # Split the string into list by comma
kelvin-onlabd3b64892015-01-20 13:26:24 -08002039 deviceList = devicesStr.split( "," )
kelvin8ec71442015-01-15 16:57:00 -08002040 # Get temporary list of all arguments with string 'id='
kelvin-onlabd3b64892015-01-20 13:26:24 -08002041 tempList = [ dev for dev in deviceList if "id=" in dev ]
kelvin8ec71442015-01-15 16:57:00 -08002042 # Split list further into arguments before and after string
2043 # 'id='. Get the latter portion ( the actual device id ) and
kelvin-onlabd3b64892015-01-20 13:26:24 -08002044 # append to idList
2045 for arg in tempList:
2046 idList.append( arg.split( "id=" )[ 1 ] )
2047 return idList
andrewonlab7e4d2d32014-10-15 13:23:21 -04002048
pingping-lin763ee042015-05-20 17:45:30 -07002049 except TypeError:
2050 main.log.exception( self.name + ": Object not as expected" )
2051 return None
andrewonlab7e4d2d32014-10-15 13:23:21 -04002052 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08002053 main.log.error( self.name + ": EOF exception found" )
2054 main.log.error( self.name + ": " + self.handle.before )
andrewonlab7e4d2d32014-10-15 13:23:21 -04002055 main.cleanup()
2056 main.exit()
pingping-lin763ee042015-05-20 17:45:30 -07002057 except Exception:
2058 main.log.exception( self.name + ": Uncaught exception!" )
andrewonlab7e4d2d32014-10-15 13:23:21 -04002059 main.cleanup()
2060 main.exit()
2061
kelvin-onlabd3b64892015-01-20 13:26:24 -08002062 def getAllNodesId( self ):
kelvin8ec71442015-01-15 16:57:00 -08002063 """
andrewonlab7c211572014-10-15 16:45:20 -04002064 Uses 'nodes' function to obtain list of all nodes
2065 and parse the result of nodes to obtain just the
kelvin8ec71442015-01-15 16:57:00 -08002066 node id's.
andrewonlab7c211572014-10-15 16:45:20 -04002067 Returns:
2068 list of node id's
kelvin8ec71442015-01-15 16:57:00 -08002069 """
andrewonlab7c211572014-10-15 16:45:20 -04002070 try:
pingping-lin763ee042015-05-20 17:45:30 -07002071 nodesStr = self.nodes( jsonFormat=True )
kelvin-onlabd3b64892015-01-20 13:26:24 -08002072 idList = []
pingping-lin763ee042015-05-20 17:45:30 -07002073 # Sample nodesStr output
2074 # id=local, address=127.0.0.1:9876, state=ACTIVE *
kelvin-onlabd3b64892015-01-20 13:26:24 -08002075 if not nodesStr:
kelvin8ec71442015-01-15 16:57:00 -08002076 main.log.info( "There are no nodes to get id from" )
kelvin-onlabd3b64892015-01-20 13:26:24 -08002077 return idList
pingping-lin763ee042015-05-20 17:45:30 -07002078 nodesJson = json.loads( nodesStr )
2079 idList = [ node.get('id') for node in nodesJson ]
kelvin-onlabd3b64892015-01-20 13:26:24 -08002080 return idList
kelvin8ec71442015-01-15 16:57:00 -08002081
pingping-lin763ee042015-05-20 17:45:30 -07002082 except TypeError:
2083 main.log.exception( self.name + ": Object not as expected" )
2084 return None
andrewonlab7c211572014-10-15 16:45:20 -04002085 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 )
andrewonlab7c211572014-10-15 16:45:20 -04002088 main.cleanup()
2089 main.exit()
pingping-lin763ee042015-05-20 17:45:30 -07002090 except Exception:
2091 main.log.exception( self.name + ": Uncaught exception!" )
andrewonlab7c211572014-10-15 16:45:20 -04002092 main.cleanup()
2093 main.exit()
andrewonlab7e4d2d32014-10-15 13:23:21 -04002094
kelvin-onlabd3b64892015-01-20 13:26:24 -08002095 def getDevice( self, dpid=None ):
kelvin8ec71442015-01-15 16:57:00 -08002096 """
Jon Halla91c4dc2014-10-22 12:57:04 -04002097 Return the first device from the devices api whose 'id' contains 'dpid'
2098 Return None if there is no match
kelvin8ec71442015-01-15 16:57:00 -08002099 """
Jon Halla91c4dc2014-10-22 12:57:04 -04002100 try:
kelvin8ec71442015-01-15 16:57:00 -08002101 if dpid is None:
Jon Halla91c4dc2014-10-22 12:57:04 -04002102 return None
2103 else:
kelvin8ec71442015-01-15 16:57:00 -08002104 dpid = dpid.replace( ':', '' )
kelvin-onlabd3b64892015-01-20 13:26:24 -08002105 rawDevices = self.devices()
2106 devicesJson = json.loads( rawDevices )
kelvin8ec71442015-01-15 16:57:00 -08002107 # search json for the device with dpid then return the device
kelvin-onlabd3b64892015-01-20 13:26:24 -08002108 for device in devicesJson:
kelvin8ec71442015-01-15 16:57:00 -08002109 # print "%s in %s?" % ( dpid, device[ 'id' ] )
2110 if dpid in device[ 'id' ]:
Jon Halla91c4dc2014-10-22 12:57:04 -04002111 return device
2112 return None
pingping-lin763ee042015-05-20 17:45:30 -07002113 except TypeError:
2114 main.log.exception( self.name + ": Object not as expected" )
2115 return None
Jon Halla91c4dc2014-10-22 12:57:04 -04002116 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08002117 main.log.error( self.name + ": EOF exception found" )
2118 main.log.error( self.name + ": " + self.handle.before )
Jon Halla91c4dc2014-10-22 12:57:04 -04002119 main.cleanup()
2120 main.exit()
pingping-lin763ee042015-05-20 17:45:30 -07002121 except Exception:
2122 main.log.exception( self.name + ": Uncaught exception!" )
Jon Halla91c4dc2014-10-22 12:57:04 -04002123 main.cleanup()
2124 main.exit()
2125
kelvin-onlabd3b64892015-01-20 13:26:24 -08002126 def checkStatus( self, ip, numoswitch, numolink, logLevel="info" ):
kelvin8ec71442015-01-15 16:57:00 -08002127 """
pingping-lin763ee042015-05-20 17:45:30 -07002128 Checks the number of switches & links that ONOS sees against the
kelvin8ec71442015-01-15 16:57:00 -08002129 supplied values. By default this will report to main.log, but the
pingping-lin763ee042015-05-20 17:45:30 -07002130 log level can be specified.
kelvin8ec71442015-01-15 16:57:00 -08002131
Jon Hall42db6dc2014-10-24 19:03:48 -04002132 Params: ip = ip used for the onos cli
2133 numoswitch = expected number of switches
pingping-lin763ee042015-05-20 17:45:30 -07002134 numolink = expected number of links
kelvin-onlabd3b64892015-01-20 13:26:24 -08002135 logLevel = level to log to. Currently accepts
2136 'info', 'warn' and 'report'
Jon Hall42db6dc2014-10-24 19:03:48 -04002137
2138
kelvin-onlabd3b64892015-01-20 13:26:24 -08002139 logLevel can
Jon Hall42db6dc2014-10-24 19:03:48 -04002140
pingping-lin763ee042015-05-20 17:45:30 -07002141 Returns: main.TRUE if the number of switches and links are correct,
2142 main.FALSE if the number of switches and links is incorrect,
Jon Hall42db6dc2014-10-24 19:03:48 -04002143 and main.ERROR otherwise
kelvin8ec71442015-01-15 16:57:00 -08002144 """
Jon Hall42db6dc2014-10-24 19:03:48 -04002145 try:
kelvin-onlabd3b64892015-01-20 13:26:24 -08002146 topology = self.getTopology( ip )
Jon Hall42db6dc2014-10-24 19:03:48 -04002147 if topology == {}:
2148 return main.ERROR
2149 output = ""
kelvin8ec71442015-01-15 16:57:00 -08002150 # Is the number of switches is what we expected
2151 devices = topology.get( 'devices', False )
2152 links = topology.get( 'links', False )
pingping-lin763ee042015-05-20 17:45:30 -07002153 if devices is False or links is False:
Jon Hall42db6dc2014-10-24 19:03:48 -04002154 return main.ERROR
kelvin-onlabd3b64892015-01-20 13:26:24 -08002155 switchCheck = ( int( devices ) == int( numoswitch ) )
kelvin8ec71442015-01-15 16:57:00 -08002156 # Is the number of links is what we expected
kelvin-onlabd3b64892015-01-20 13:26:24 -08002157 linkCheck = ( int( links ) == int( numolink ) )
2158 if ( switchCheck and linkCheck ):
kelvin8ec71442015-01-15 16:57:00 -08002159 # We expected the correct numbers
pingping-lin763ee042015-05-20 17:45:30 -07002160 output += "The number of links and switches match " +\
2161 "what was expected"
Jon Hall42db6dc2014-10-24 19:03:48 -04002162 result = main.TRUE
2163 else:
pingping-lin763ee042015-05-20 17:45:30 -07002164 output += "The number of links and switches does not match " +\
2165 "what was expected"
Jon Hall42db6dc2014-10-24 19:03:48 -04002166 result = main.FALSE
kelvin-onlabd3b64892015-01-20 13:26:24 -08002167 output = output + "\n ONOS sees %i devices (%i expected) \
2168 and %i links (%i expected)" % (
2169 int( devices ), int( numoswitch ), int( links ),
2170 int( numolink ) )
2171 if logLevel == "report":
kelvin8ec71442015-01-15 16:57:00 -08002172 main.log.report( output )
kelvin-onlabd3b64892015-01-20 13:26:24 -08002173 elif logLevel == "warn":
kelvin8ec71442015-01-15 16:57:00 -08002174 main.log.warn( output )
Jon Hall42db6dc2014-10-24 19:03:48 -04002175 else:
pingping-lin763ee042015-05-20 17:45:30 -07002176 main.log.info( self.name + ": " + output )
kelvin8ec71442015-01-15 16:57:00 -08002177 return result
pingping-lin763ee042015-05-20 17:45:30 -07002178 except TypeError:
2179 main.log.exception( self.name + ": Object not as expected" )
2180 return None
Jon Hall42db6dc2014-10-24 19:03:48 -04002181 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08002182 main.log.error( self.name + ": EOF exception found" )
2183 main.log.error( self.name + ": " + self.handle.before )
Jon Hall42db6dc2014-10-24 19:03:48 -04002184 main.cleanup()
2185 main.exit()
pingping-lin763ee042015-05-20 17:45:30 -07002186 except Exception:
2187 main.log.exception( self.name + ": Uncaught exception!" )
Jon Hall42db6dc2014-10-24 19:03:48 -04002188 main.cleanup()
2189 main.exit()
Jon Hall1c9e8732014-10-27 19:29:27 -04002190
kelvin-onlabd3b64892015-01-20 13:26:24 -08002191 def deviceRole( self, deviceId, onosNode, role="master" ):
kelvin8ec71442015-01-15 16:57:00 -08002192 """
Jon Hall1c9e8732014-10-27 19:29:27 -04002193 Calls the device-role cli command.
kelvin-onlabd3b64892015-01-20 13:26:24 -08002194 deviceId must be the id of a device as seen in the onos devices command
2195 onosNode is the ip of one of the onos nodes in the cluster
Jon Hall1c9e8732014-10-27 19:29:27 -04002196 role must be either master, standby, or none
2197
Jon Halle3f39ff2015-01-13 11:50:53 -08002198 Returns:
2199 main.TRUE or main.FALSE based on argument verification and
2200 main.ERROR if command returns and error
kelvin-onlab898a6c62015-01-16 14:13:53 -08002201 """
Jon Hall1c9e8732014-10-27 19:29:27 -04002202 try:
Jon Halle3f39ff2015-01-13 11:50:53 -08002203 if role.lower() == "master" or role.lower() == "standby" or\
Jon Hall1c9e8732014-10-27 19:29:27 -04002204 role.lower() == "none":
kelvin-onlabd3b64892015-01-20 13:26:24 -08002205 cmdStr = "device-role " +\
2206 str( deviceId ) + " " +\
2207 str( onosNode ) + " " +\
kelvin-onlab898a6c62015-01-16 14:13:53 -08002208 str( role )
kelvin-onlabd3b64892015-01-20 13:26:24 -08002209 handle = self.sendline( cmdStr )
kelvin-onlab898a6c62015-01-16 14:13:53 -08002210 if re.search( "Error", handle ):
2211 # end color output to escape any colours
2212 # from the cli
kelvin8ec71442015-01-15 16:57:00 -08002213 main.log.error( self.name + ": " +
kelvin-onlab898a6c62015-01-16 14:13:53 -08002214 handle + '\033[0m' )
kelvin8ec71442015-01-15 16:57:00 -08002215 return main.ERROR
kelvin8ec71442015-01-15 16:57:00 -08002216 return main.TRUE
Jon Hall1c9e8732014-10-27 19:29:27 -04002217 else:
kelvin-onlab898a6c62015-01-16 14:13:53 -08002218 main.log.error( "Invalid 'role' given to device_role(). " +
2219 "Value was '" + str(role) + "'." )
Jon Hall1c9e8732014-10-27 19:29:27 -04002220 return main.FALSE
pingping-lin763ee042015-05-20 17:45:30 -07002221 except TypeError:
2222 main.log.exception( self.name + ": Object not as expected" )
2223 return None
Jon Hall1c9e8732014-10-27 19:29:27 -04002224 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08002225 main.log.error( self.name + ": EOF exception found" )
2226 main.log.error( self.name + ": " + self.handle.before )
Jon Hall1c9e8732014-10-27 19:29:27 -04002227 main.cleanup()
2228 main.exit()
pingping-lin763ee042015-05-20 17:45:30 -07002229 except Exception:
2230 main.log.exception( self.name + ": Uncaught exception!" )
Jon Hall1c9e8732014-10-27 19:29:27 -04002231 main.cleanup()
2232 main.exit()
2233
kelvin-onlabd3b64892015-01-20 13:26:24 -08002234 def clusters( self, jsonFormat=True ):
kelvin8ec71442015-01-15 16:57:00 -08002235 """
Jon Hall73cf9cc2014-11-20 22:28:38 -08002236 Lists all clusters
Jon Hallffb386d2014-11-21 13:43:38 -08002237 Optional argument:
kelvin-onlabd3b64892015-01-20 13:26:24 -08002238 * jsonFormat - boolean indicating if you want output in json
kelvin8ec71442015-01-15 16:57:00 -08002239 """
Jon Hall73cf9cc2014-11-20 22:28:38 -08002240 try:
pingping-lin763ee042015-05-20 17:45:30 -07002241 cmdStr = "clusters"
kelvin-onlabd3b64892015-01-20 13:26:24 -08002242 if jsonFormat:
pingping-lin763ee042015-05-20 17:45:30 -07002243 cmdStr += " -j"
2244 handle = self.sendline( cmdStr )
2245 return handle
2246 except TypeError:
2247 main.log.exception( self.name + ": Object not as expected" )
2248 return None
Jon Hall73cf9cc2014-11-20 22:28:38 -08002249 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08002250 main.log.error( self.name + ": EOF exception found" )
2251 main.log.error( self.name + ": " + self.handle.before )
Jon Hall73cf9cc2014-11-20 22:28:38 -08002252 main.cleanup()
2253 main.exit()
pingping-lin763ee042015-05-20 17:45:30 -07002254 except Exception:
2255 main.log.exception( self.name + ": Uncaught exception!" )
Jon Hall73cf9cc2014-11-20 22:28:38 -08002256 main.cleanup()
2257 main.exit()
2258
kelvin-onlabd3b64892015-01-20 13:26:24 -08002259 def electionTestLeader( self ):
kelvin-onlab898a6c62015-01-16 14:13:53 -08002260 """
Jon Halle3f39ff2015-01-13 11:50:53 -08002261 CLI command to get the current leader for the Election test application
2262 NOTE: Requires installation of the onos-app-election feature
2263 Returns: Node IP of the leader if one exists
2264 None if none exists
2265 Main.FALSE on error
kelvin-onlab898a6c62015-01-16 14:13:53 -08002266 """
Jon Hall94fd0472014-12-08 11:52:42 -08002267 try:
kelvin-onlabd3b64892015-01-20 13:26:24 -08002268 cmdStr = "election-test-leader"
2269 response = self.sendline( cmdStr )
Jon Halle3f39ff2015-01-13 11:50:53 -08002270 # Leader
2271 leaderPattern = "The\scurrent\sleader\sfor\sthe\sElection\s" +\
kelvin-onlab898a6c62015-01-16 14:13:53 -08002272 "app\sis\s(?P<node>.+)\."
kelvin-onlabd3b64892015-01-20 13:26:24 -08002273 nodeSearch = re.search( leaderPattern, response )
2274 if nodeSearch:
2275 node = nodeSearch.group( 'node' )
Jon Halle3f39ff2015-01-13 11:50:53 -08002276 main.log.info( "Election-test-leader on " + str( self.name ) +
kelvin-onlab898a6c62015-01-16 14:13:53 -08002277 " found " + node + " as the leader" )
Jon Hall94fd0472014-12-08 11:52:42 -08002278 return node
Jon Halle3f39ff2015-01-13 11:50:53 -08002279 # no leader
2280 nullPattern = "There\sis\scurrently\sno\sleader\selected\sfor\s" +\
kelvin-onlab898a6c62015-01-16 14:13:53 -08002281 "the\sElection\sapp"
kelvin-onlabd3b64892015-01-20 13:26:24 -08002282 nullSearch = re.search( nullPattern, response )
2283 if nullSearch:
Jon Halle3f39ff2015-01-13 11:50:53 -08002284 main.log.info( "Election-test-leader found no leader on " +
kelvin-onlab898a6c62015-01-16 14:13:53 -08002285 self.name )
Jon Hall94fd0472014-12-08 11:52:42 -08002286 return None
kelvin-onlab898a6c62015-01-16 14:13:53 -08002287 # error
Jon Halle3f39ff2015-01-13 11:50:53 -08002288 errorPattern = "Command\snot\sfound"
kelvin-onlab898a6c62015-01-16 14:13:53 -08002289 if re.search( errorPattern, response ):
2290 main.log.error( "Election app is not loaded on " + self.name )
Jon Halle3f39ff2015-01-13 11:50:53 -08002291 # TODO: Should this be main.ERROR?
Jon Hall669173b2014-12-17 11:36:30 -08002292 return main.FALSE
2293 else:
pingping-lin763ee042015-05-20 17:45:30 -07002294 main.log.error( "Error in electionTestLeader on " + self.name +
2295 ": " + "unexpected response" )
kelvin8ec71442015-01-15 16:57:00 -08002296 main.log.error( repr( response ) )
Jon Hall669173b2014-12-17 11:36:30 -08002297 return main.FALSE
pingping-lin763ee042015-05-20 17:45:30 -07002298 except TypeError:
2299 main.log.exception( self.name + ": Object not as expected" )
2300 return main.FALSE
Jon Hall94fd0472014-12-08 11:52:42 -08002301 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08002302 main.log.error( self.name + ": EOF exception found" )
2303 main.log.error( self.name + ": " + self.handle.before )
Jon Hall94fd0472014-12-08 11:52:42 -08002304 main.cleanup()
2305 main.exit()
pingping-lin763ee042015-05-20 17:45:30 -07002306 except Exception:
2307 main.log.exception( self.name + ": Uncaught exception!" )
Jon Hall94fd0472014-12-08 11:52:42 -08002308 main.cleanup()
2309 main.exit()
2310
kelvin-onlabd3b64892015-01-20 13:26:24 -08002311 def electionTestRun( self ):
kelvin-onlab898a6c62015-01-16 14:13:53 -08002312 """
Jon Halle3f39ff2015-01-13 11:50:53 -08002313 CLI command to run for leadership of the Election test application.
2314 NOTE: Requires installation of the onos-app-election feature
2315 Returns: Main.TRUE on success
2316 Main.FALSE on error
kelvin-onlab898a6c62015-01-16 14:13:53 -08002317 """
Jon Hall94fd0472014-12-08 11:52:42 -08002318 try:
kelvin-onlabd3b64892015-01-20 13:26:24 -08002319 cmdStr = "election-test-run"
2320 response = self.sendline( cmdStr )
kelvin-onlab898a6c62015-01-16 14:13:53 -08002321 # success
Jon Halle3f39ff2015-01-13 11:50:53 -08002322 successPattern = "Entering\sleadership\selections\sfor\sthe\s" +\
kelvin-onlab898a6c62015-01-16 14:13:53 -08002323 "Election\sapp."
Jon Halle3f39ff2015-01-13 11:50:53 -08002324 search = re.search( successPattern, response )
Jon Hall94fd0472014-12-08 11:52:42 -08002325 if search:
Jon Halle3f39ff2015-01-13 11:50:53 -08002326 main.log.info( self.name + " entering leadership elections " +
kelvin-onlab898a6c62015-01-16 14:13:53 -08002327 "for the Election app." )
Jon Hall94fd0472014-12-08 11:52:42 -08002328 return main.TRUE
kelvin-onlab898a6c62015-01-16 14:13:53 -08002329 # error
Jon Halle3f39ff2015-01-13 11:50:53 -08002330 errorPattern = "Command\snot\sfound"
2331 if re.search( errorPattern, response ):
2332 main.log.error( "Election app is not loaded on " + self.name )
Jon Hall669173b2014-12-17 11:36:30 -08002333 return main.FALSE
2334 else:
pingping-lin763ee042015-05-20 17:45:30 -07002335 main.log.error( "Error in electionTestRun on " + self.name +
2336 ": " + "unexpected response" )
Jon Halle3f39ff2015-01-13 11:50:53 -08002337 main.log.error( repr( response ) )
Jon Hall669173b2014-12-17 11:36:30 -08002338 return main.FALSE
pingping-lin763ee042015-05-20 17:45:30 -07002339 except TypeError:
2340 main.log.exception( self.name + ": Object not as expected" )
2341 return main.FALSE
Jon Hall94fd0472014-12-08 11:52:42 -08002342 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08002343 main.log.error( self.name + ": EOF exception found" )
2344 main.log.error( self.name + ": " + self.handle.before )
Jon Hall94fd0472014-12-08 11:52:42 -08002345 main.cleanup()
2346 main.exit()
pingping-lin763ee042015-05-20 17:45:30 -07002347 except Exception:
2348 main.log.exception( self.name + ": Uncaught exception!" )
Jon Hall94fd0472014-12-08 11:52:42 -08002349 main.cleanup()
2350 main.exit()
2351
kelvin-onlabd3b64892015-01-20 13:26:24 -08002352 def electionTestWithdraw( self ):
kelvin8ec71442015-01-15 16:57:00 -08002353 """
Jon Hall94fd0472014-12-08 11:52:42 -08002354 * CLI command to withdraw the local node from leadership election for
2355 * the Election test application.
2356 #NOTE: Requires installation of the onos-app-election feature
2357 Returns: Main.TRUE on success
2358 Main.FALSE on error
kelvin8ec71442015-01-15 16:57:00 -08002359 """
Jon Hall94fd0472014-12-08 11:52:42 -08002360 try:
kelvin-onlabd3b64892015-01-20 13:26:24 -08002361 cmdStr = "election-test-withdraw"
2362 response = self.sendline( cmdStr )
kelvin-onlab898a6c62015-01-16 14:13:53 -08002363 # success
Jon Halle3f39ff2015-01-13 11:50:53 -08002364 successPattern = "Withdrawing\sfrom\sleadership\selections\sfor" +\
kelvin-onlab898a6c62015-01-16 14:13:53 -08002365 "\sthe\sElection\sapp."
Jon Halle3f39ff2015-01-13 11:50:53 -08002366 if re.search( successPattern, response ):
2367 main.log.info( self.name + " withdrawing from leadership " +
kelvin-onlab898a6c62015-01-16 14:13:53 -08002368 "elections for the Election app." )
Jon Hall94fd0472014-12-08 11:52:42 -08002369 return main.TRUE
kelvin-onlab898a6c62015-01-16 14:13:53 -08002370 # error
Jon Halle3f39ff2015-01-13 11:50:53 -08002371 errorPattern = "Command\snot\sfound"
2372 if re.search( errorPattern, response ):
2373 main.log.error( "Election app is not loaded on " + self.name )
Jon Hall669173b2014-12-17 11:36:30 -08002374 return main.FALSE
2375 else:
pingping-lin763ee042015-05-20 17:45:30 -07002376 main.log.error( "Error in electionTestWithdraw on " +
2377 self.name + ": " + "unexpected response" )
Jon Halle3f39ff2015-01-13 11:50:53 -08002378 main.log.error( repr( response ) )
Jon Hall669173b2014-12-17 11:36:30 -08002379 return main.FALSE
pingping-lin763ee042015-05-20 17:45:30 -07002380 except TypeError:
2381 main.log.exception( self.name + ": Object not as expected" )
2382 return main.FALSE
Jon Hall94fd0472014-12-08 11:52:42 -08002383 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08002384 main.log.error( self.name + ": EOF exception found" )
2385 main.log.error( self.name + ": " + self.handle.before )
Jon Hall94fd0472014-12-08 11:52:42 -08002386 main.cleanup()
2387 main.exit()
pingping-lin763ee042015-05-20 17:45:30 -07002388 except Exception:
2389 main.log.exception( self.name + ": Uncaught exception!" )
Jon Hall94fd0472014-12-08 11:52:42 -08002390 main.cleanup()
2391 main.exit()
Jon Hall1c9e8732014-10-27 19:29:27 -04002392
kelvin8ec71442015-01-15 16:57:00 -08002393 def getDevicePortsEnabledCount( self, dpid ):
2394 """
Hari Krishnaa43d4e92014-12-19 13:22:40 -08002395 Get the count of all enabled ports on a particular device/switch
kelvin8ec71442015-01-15 16:57:00 -08002396 """
Hari Krishnaa43d4e92014-12-19 13:22:40 -08002397 try:
Jon Halle3f39ff2015-01-13 11:50:53 -08002398 dpid = str( dpid )
kelvin-onlabd3b64892015-01-20 13:26:24 -08002399 cmdStr = "onos:ports -e " + dpid + " | wc -l"
2400 output = self.sendline( cmdStr )
Jon Halle3f39ff2015-01-13 11:50:53 -08002401 if re.search( "No such device", output ):
2402 main.log.error( "Error in getting ports" )
2403 return ( output, "Error" )
Hari Krishnaa43d4e92014-12-19 13:22:40 -08002404 else:
Jon Halle3f39ff2015-01-13 11:50:53 -08002405 return output
pingping-lin763ee042015-05-20 17:45:30 -07002406 except TypeError:
2407 main.log.exception( self.name + ": Object not as expected" )
2408 return ( output, "Error" )
Hari Krishnaa43d4e92014-12-19 13:22:40 -08002409 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08002410 main.log.error( self.name + ": EOF exception found" )
2411 main.log.error( self.name + ": " + self.handle.before )
Hari Krishnaa43d4e92014-12-19 13:22:40 -08002412 main.cleanup()
2413 main.exit()
pingping-lin763ee042015-05-20 17:45:30 -07002414 except Exception:
2415 main.log.exception( self.name + ": Uncaught exception!" )
Hari Krishnaa43d4e92014-12-19 13:22:40 -08002416 main.cleanup()
2417 main.exit()
2418
kelvin8ec71442015-01-15 16:57:00 -08002419 def getDeviceLinksActiveCount( self, dpid ):
2420 """
Hari Krishnaa43d4e92014-12-19 13:22:40 -08002421 Get the count of all enabled ports on a particular device/switch
kelvin8ec71442015-01-15 16:57:00 -08002422 """
Hari Krishnaa43d4e92014-12-19 13:22:40 -08002423 try:
kelvin-onlab898a6c62015-01-16 14:13:53 -08002424 dpid = str( dpid )
kelvin-onlabd3b64892015-01-20 13:26:24 -08002425 cmdStr = "onos:links " + dpid + " | grep ACTIVE | wc -l"
2426 output = self.sendline( cmdStr )
Jon Halle3f39ff2015-01-13 11:50:53 -08002427 if re.search( "No such device", output ):
kelvin-onlab898a6c62015-01-16 14:13:53 -08002428 main.log.error( "Error in getting ports " )
2429 return ( output, "Error " )
Hari Krishnaa43d4e92014-12-19 13:22:40 -08002430 else:
Jon Halle3f39ff2015-01-13 11:50:53 -08002431 return output
pingping-lin763ee042015-05-20 17:45:30 -07002432 except TypeError:
2433 main.log.exception( self.name + ": Object not as expected" )
2434 return ( output, "Error " )
Hari Krishnaa43d4e92014-12-19 13:22:40 -08002435 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08002436 main.log.error( self.name + ": EOF exception found" )
2437 main.log.error( self.name + ": " + self.handle.before )
Hari Krishnaa43d4e92014-12-19 13:22:40 -08002438 main.cleanup()
2439 main.exit()
pingping-lin763ee042015-05-20 17:45:30 -07002440 except Exception:
2441 main.log.exception( self.name + ": Uncaught exception!" )
Hari Krishnaa43d4e92014-12-19 13:22:40 -08002442 main.cleanup()
2443 main.exit()
2444
kelvin8ec71442015-01-15 16:57:00 -08002445 def getAllIntentIds( self ):
2446 """
Hari Krishnaa43d4e92014-12-19 13:22:40 -08002447 Return a list of all Intent IDs
kelvin8ec71442015-01-15 16:57:00 -08002448 """
Hari Krishnaa43d4e92014-12-19 13:22:40 -08002449 try:
kelvin-onlabd3b64892015-01-20 13:26:24 -08002450 cmdStr = "onos:intents | grep id="
2451 output = self.sendline( cmdStr )
Jon Halle3f39ff2015-01-13 11:50:53 -08002452 if re.search( "Error", output ):
2453 main.log.error( "Error in getting ports" )
2454 return ( output, "Error" )
Hari Krishnaa43d4e92014-12-19 13:22:40 -08002455 else:
Jon Halle3f39ff2015-01-13 11:50:53 -08002456 return output
pingping-lin763ee042015-05-20 17:45:30 -07002457 except TypeError:
2458 main.log.exception( self.name + ": Object not as expected" )
2459 return ( output, "Error" )
Hari Krishnaa43d4e92014-12-19 13:22:40 -08002460 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08002461 main.log.error( self.name + ": EOF exception found" )
2462 main.log.error( self.name + ": " + self.handle.before )
Hari Krishnaa43d4e92014-12-19 13:22:40 -08002463 main.cleanup()
2464 main.exit()
pingping-lin763ee042015-05-20 17:45:30 -07002465 except Exception:
2466 main.log.exception( self.name + ": Uncaught exception!" )
Hari Krishnaa43d4e92014-12-19 13:22:40 -08002467 main.cleanup()
2468 main.exit()
pingping-lin763ee042015-05-20 17:45:30 -07002469
2470 def intentSummary( self ):
2471 """
2472 Returns a dictionary containing the current intent states and the count
2473 """
2474 try:
2475 intents = self.intents( )
2476 states = []
2477 for intent in json.loads( intents ):
2478 states.append( intent.get( 'state', None ) )
2479 out = [ ( i, states.count( i ) ) for i in set( states ) ]
2480 main.log.info( dict( out ) )
2481 return dict( out )
2482 except TypeError:
2483 main.log.exception( self.name + ": Object not as expected" )
2484 return None
2485 except pexpect.EOF:
2486 main.log.error( self.name + ": EOF exception found" )
2487 main.log.error( self.name + ": " + self.handle.before )
2488 main.cleanup()
2489 main.exit()
2490 except Exception:
2491 main.log.exception( self.name + ": Uncaught exception!" )
2492 main.cleanup()
2493 main.exit()
2494
2495 def leaders( self, jsonFormat=True ):
2496 """
2497 Returns the output of the leaders command.
2498 Optional argument:
2499 * jsonFormat - boolean indicating if you want output in json
2500 """
2501 # FIXME: add json output
2502 # Sample JSON
2503 # {
2504 # "electedTime": "13m ago",
2505 # "epoch": 4,
2506 # "leader": "10.128.30.17",
2507 # "topic": "intent-partition-3"
2508 # },
2509 try:
2510 cmdStr = "onos:leaders"
2511 if jsonFormat:
2512 cmdStr += " -j"
2513 output = self.sendline( cmdStr )
2514 return output
2515 except TypeError:
2516 main.log.exception( self.name + ": Object not as expected" )
2517 return None
2518 except pexpect.EOF:
2519 main.log.error( self.name + ": EOF exception found" )
2520 main.log.error( self.name + ": " + self.handle.before )
2521 main.cleanup()
2522 main.exit()
2523 except Exception:
2524 main.log.exception( self.name + ": Uncaught exception!" )
2525 main.cleanup()
2526 main.exit()
2527
2528 def pendingMap( self, jsonFormat=True ):
2529 """
2530 Returns the output of the intent Pending map.
2531 """
2532 try:
2533 cmdStr = "onos:intents -p"
2534 if jsonFormat:
2535 cmdStr += " -j"
2536 output = self.sendline( cmdStr )
2537 return output
2538 except TypeError:
2539 main.log.exception( self.name + ": Object not as expected" )
2540 return None
2541 except pexpect.EOF:
2542 main.log.error( self.name + ": EOF exception found" )
2543 main.log.error( self.name + ": " + self.handle.before )
2544 main.cleanup()
2545 main.exit()
2546 except Exception:
2547 main.log.exception( self.name + ": Uncaught exception!" )
2548 main.cleanup()
2549 main.exit()
2550
2551 def partitions( self, jsonFormat=True ):
2552 """
2553 Returns the output of the raft partitions command for ONOS.
2554 """
2555 # Sample JSON
2556 # {
2557 # "leader": "tcp://10.128.30.11:7238",
2558 # "members": [
2559 # "tcp://10.128.30.11:7238",
2560 # "tcp://10.128.30.17:7238",
2561 # "tcp://10.128.30.13:7238",
2562 # ],
2563 # "name": "p1",
2564 # "term": 3
2565 # },
2566 try:
2567 cmdStr = "onos:partitions"
2568 if jsonFormat:
2569 cmdStr += " -j"
2570 output = self.sendline( cmdStr )
2571 return output
2572 except TypeError:
2573 main.log.exception( self.name + ": Object not as expected" )
2574 return None
2575 except pexpect.EOF:
2576 main.log.error( self.name + ": EOF exception found" )
2577 main.log.error( self.name + ": " + self.handle.before )
2578 main.cleanup()
2579 main.exit()
2580 except Exception:
2581 main.log.exception( self.name + ": Uncaught exception!" )
2582 main.cleanup()
2583 main.exit()
2584
2585 def apps( self, jsonFormat=True ):
2586 """
2587 Returns the output of the apps command for ONOS. This command lists
2588 information about installed ONOS applications
2589 """
2590 # Sample JSON object
2591 # [{"name":"org.onosproject.openflow","id":0,"version":"1.2.0",
2592 # "description":"ONOS OpenFlow protocol southbound providers",
2593 # "origin":"ON.Lab","permissions":"[]","featuresRepo":"",
2594 # "features":"[onos-openflow]","state":"ACTIVE"}]
2595 try:
2596 cmdStr = "onos:apps"
2597 if jsonFormat:
2598 cmdStr += " -j"
2599 output = self.sendline( cmdStr )
2600 assert "Error executing command" not in output
2601 return output
2602 # FIXME: look at specific exceptions/Errors
2603 except AssertionError:
2604 main.log.error( "Error in processing onos:app command: " +
2605 str( output ) )
2606 return None
2607 except TypeError:
2608 main.log.exception( self.name + ": Object not as expected" )
2609 return None
2610 except pexpect.EOF:
2611 main.log.error( self.name + ": EOF exception found" )
2612 main.log.error( self.name + ": " + self.handle.before )
2613 main.cleanup()
2614 main.exit()
2615 except Exception:
2616 main.log.exception( self.name + ": Uncaught exception!" )
2617 main.cleanup()
2618 main.exit()
2619
2620 def appStatus( self, appName ):
2621 """
2622 Uses the onos:apps cli command to return the status of an application.
2623 Returns:
2624 "ACTIVE" - If app is installed and activated
2625 "INSTALLED" - If app is installed and deactivated
2626 "UNINSTALLED" - If app is not installed
2627 None - on error
2628 """
2629 try:
2630 if not isinstance( appName, types.StringType ):
2631 main.log.error( self.name + ".appStatus(): appName must be" +
2632 " a string" )
2633 return None
2634 output = self.apps( jsonFormat=True )
2635 appsJson = json.loads( output )
2636 state = None
2637 for app in appsJson:
2638 if appName == app.get('name'):
2639 state = app.get('state')
2640 break
2641 if state == "ACTIVE" or state == "INSTALLED":
2642 return state
2643 elif state is None:
2644 return "UNINSTALLED"
2645 elif state:
2646 main.log.error( "Unexpected state from 'onos:apps': " +
2647 str( state ) )
2648 return state
2649 except TypeError:
2650 main.log.exception( self.name + ": Object not as expected" )
2651 return None
2652 except pexpect.EOF:
2653 main.log.error( self.name + ": EOF exception found" )
2654 main.log.error( self.name + ": " + self.handle.before )
2655 main.cleanup()
2656 main.exit()
2657 except Exception:
2658 main.log.exception( self.name + ": Uncaught exception!" )
2659 main.cleanup()
2660 main.exit()
2661
2662 def app( self, appName, option ):
2663 """
2664 Interacts with the app command for ONOS. This command manages
2665 application inventory.
2666 """
2667 try:
2668 # Validate argument types
2669 valid = True
2670 if not isinstance( appName, types.StringType ):
2671 main.log.error( self.name + ".app(): appName must be a " +
2672 "string" )
2673 valid = False
2674 if not isinstance( option, types.StringType ):
2675 main.log.error( self.name + ".app(): option must be a string" )
2676 valid = False
2677 if not valid:
2678 return main.FALSE
2679 # Validate Option
2680 option = option.lower()
2681 # NOTE: Install may become a valid option
2682 if option == "activate":
2683 pass
2684 elif option == "deactivate":
2685 pass
2686 elif option == "uninstall":
2687 pass
2688 else:
2689 # Invalid option
2690 main.log.error( "The ONOS app command argument only takes " +
2691 "the values: (activate|deactivate|uninstall)" +
2692 "; was given '" + option + "'")
2693 return main.FALSE
2694 cmdStr = "onos:app " + option + " " + appName
2695 output = self.sendline( cmdStr )
2696 if "Error executing command" in output:
2697 main.log.error( "Error in processing onos:app command: " +
2698 str( output ) )
2699 return main.FALSE
2700 elif "No such application" in output:
2701 main.log.error( "The application '" + appName +
2702 "' is not installed in ONOS" )
2703 return main.FALSE
2704 elif "Command not found:" in output:
2705 main.log.error( "Error in processing onos:app command: " +
2706 str( output ) )
2707 return main.FALSE
2708 elif "Unsupported command:" in output:
2709 main.log.error( "Incorrect command given to 'app': " +
2710 str( output ) )
2711 # NOTE: we may need to add more checks here
2712 # else: Command was successful
2713 # main.log.debug( "app response: " + repr( output ) )
2714 return main.TRUE
2715 except TypeError:
2716 main.log.exception( self.name + ": Object not as expected" )
2717 return main.ERROR
2718 except pexpect.EOF:
2719 main.log.error( self.name + ": EOF exception found" )
2720 main.log.error( self.name + ": " + self.handle.before )
2721 main.cleanup()
2722 main.exit()
2723 except Exception:
2724 main.log.exception( self.name + ": Uncaught exception!" )
2725 main.cleanup()
2726 main.exit()
2727
2728 def activateApp( self, appName, check=True ):
2729 """
2730 Activate an app that is already installed in ONOS
2731 appName is the hierarchical app name, not the feature name
2732 If check is True, method will check the status of the app after the
2733 command is issued
2734 Returns main.TRUE if the command was successfully sent
2735 main.FALSE if the cli responded with an error or given
2736 incorrect input
2737 """
2738 try:
2739 if not isinstance( appName, types.StringType ):
2740 main.log.error( self.name + ".activateApp(): appName must be" +
2741 " a string" )
2742 return main.FALSE
2743 status = self.appStatus( appName )
2744 if status == "INSTALLED":
2745 response = self.app( appName, "activate" )
2746 if check and response == main.TRUE:
2747 for i in range(10): # try 10 times then give up
2748 # TODO: Check with Thomas about this delay
2749 status = self.appStatus( appName )
2750 if status == "ACTIVE":
2751 return main.TRUE
2752 else:
2753 main.log.debug( "The state of application " +
2754 appName + " is " + status )
2755 time.sleep( 1 )
2756 return main.FALSE
2757 else: # not 'check' or command didn't succeed
2758 return response
2759 elif status == "ACTIVE":
2760 return main.TRUE
2761 elif status == "UNINSTALLED":
2762 main.log.error( self.name + ": Tried to activate the " +
2763 "application '" + appName + "' which is not " +
2764 "installed." )
2765 else:
2766 main.log.error( "Unexpected return value from appStatus: " +
2767 str( status ) )
2768 return main.ERROR
2769 except TypeError:
2770 main.log.exception( self.name + ": Object not as expected" )
2771 return main.ERROR
2772 except pexpect.EOF:
2773 main.log.error( self.name + ": EOF exception found" )
2774 main.log.error( self.name + ": " + self.handle.before )
2775 main.cleanup()
2776 main.exit()
2777 except Exception:
2778 main.log.exception( self.name + ": Uncaught exception!" )
2779 main.cleanup()
2780 main.exit()
2781
2782 def deactivateApp( self, appName, check=True ):
2783 """
2784 Deactivate an app that is already activated in ONOS
2785 appName is the hierarchical app name, not the feature name
2786 If check is True, method will check the status of the app after the
2787 command is issued
2788 Returns main.TRUE if the command was successfully sent
2789 main.FALSE if the cli responded with an error or given
2790 incorrect input
2791 """
2792 try:
2793 if not isinstance( appName, types.StringType ):
2794 main.log.error( self.name + ".deactivateApp(): appName must " +
2795 "be a string" )
2796 return main.FALSE
2797 status = self.appStatus( appName )
2798 if status == "INSTALLED":
2799 return main.TRUE
2800 elif status == "ACTIVE":
2801 response = self.app( appName, "deactivate" )
2802 if check and response == main.TRUE:
2803 for i in range(10): # try 10 times then give up
2804 status = self.appStatus( appName )
2805 if status == "INSTALLED":
2806 return main.TRUE
2807 else:
2808 time.sleep( 1 )
2809 return main.FALSE
2810 else: # not check or command didn't succeed
2811 return response
2812 elif status == "UNINSTALLED":
2813 main.log.warn( self.name + ": Tried to deactivate the " +
2814 "application '" + appName + "' which is not " +
2815 "installed." )
2816 return main.TRUE
2817 else:
2818 main.log.error( "Unexpected return value from appStatus: " +
2819 str( status ) )
2820 return main.ERROR
2821 except TypeError:
2822 main.log.exception( self.name + ": Object not as expected" )
2823 return main.ERROR
2824 except pexpect.EOF:
2825 main.log.error( self.name + ": EOF exception found" )
2826 main.log.error( self.name + ": " + self.handle.before )
2827 main.cleanup()
2828 main.exit()
2829 except Exception:
2830 main.log.exception( self.name + ": Uncaught exception!" )
2831 main.cleanup()
2832 main.exit()
2833
2834 def uninstallApp( self, appName, check=True ):
2835 """
2836 Uninstall an app that is already installed in ONOS
2837 appName is the hierarchical app name, not the feature name
2838 If check is True, method will check the status of the app after the
2839 command is issued
2840 Returns main.TRUE if the command was successfully sent
2841 main.FALSE if the cli responded with an error or given
2842 incorrect input
2843 """
2844 # TODO: check with Thomas about the state machine for apps
2845 try:
2846 if not isinstance( appName, types.StringType ):
2847 main.log.error( self.name + ".uninstallApp(): appName must " +
2848 "be a string" )
2849 return main.FALSE
2850 status = self.appStatus( appName )
2851 if status == "INSTALLED":
2852 response = self.app( appName, "uninstall" )
2853 if check and response == main.TRUE:
2854 for i in range(10): # try 10 times then give up
2855 status = self.appStatus( appName )
2856 if status == "UNINSTALLED":
2857 return main.TRUE
2858 else:
2859 time.sleep( 1 )
2860 return main.FALSE
2861 else: # not check or command didn't succeed
2862 return response
2863 elif status == "ACTIVE":
2864 main.log.warn( self.name + ": Tried to uninstall the " +
2865 "application '" + appName + "' which is " +
2866 "currently active." )
2867 response = self.app( appName, "uninstall" )
2868 if check and response == main.TRUE:
2869 for i in range(10): # try 10 times then give up
2870 status = self.appStatus( appName )
2871 if status == "UNINSTALLED":
2872 return main.TRUE
2873 else:
2874 time.sleep( 1 )
2875 return main.FALSE
2876 else: # not check or command didn't succeed
2877 return response
2878 elif status == "UNINSTALLED":
2879 return main.TRUE
2880 else:
2881 main.log.error( "Unexpected return value from appStatus: " +
2882 str( status ) )
2883 return main.ERROR
2884 except TypeError:
2885 main.log.exception( self.name + ": Object not as expected" )
2886 return main.ERROR
2887 except pexpect.EOF:
2888 main.log.error( self.name + ": EOF exception found" )
2889 main.log.error( self.name + ": " + self.handle.before )
2890 main.cleanup()
2891 main.exit()
2892 except Exception:
2893 main.log.exception( self.name + ": Uncaught exception!" )
2894 main.cleanup()
2895 main.exit()
2896
2897 def appIDs( self, jsonFormat=True ):
2898 """
2899 Show the mappings between app id and app names given by the 'app-ids'
2900 cli command
2901 """
2902 try:
2903 cmdStr = "app-ids"
2904 if jsonFormat:
2905 cmdStr += " -j"
2906 output = self.sendline( cmdStr )
2907 assert "Error executing command" not in output
2908 return output
2909 except AssertionError:
2910 main.log.error( "Error in processing onos:app-ids command: " +
2911 str( output ) )
2912 return None
2913 except TypeError:
2914 main.log.exception( self.name + ": Object not as expected" )
2915 return None
2916 except pexpect.EOF:
2917 main.log.error( self.name + ": EOF exception found" )
2918 main.log.error( self.name + ": " + self.handle.before )
2919 main.cleanup()
2920 main.exit()
2921 except Exception:
2922 main.log.exception( self.name + ": Uncaught exception!" )
2923 main.cleanup()
2924 main.exit()
2925
2926 def appToIDCheck( self ):
2927 """
2928 This method will check that each application's ID listed in 'apps' is
2929 the same as the ID listed in 'app-ids'. The check will also check that
2930 there are no duplicate IDs issued. Note that an app ID should be
2931 a globaly unique numerical identifier for app/app-like features. Once
2932 an ID is registered, the ID is never freed up so that if an app is
2933 reinstalled it will have the same ID.
2934
2935 Returns: main.TRUE if the check passes and
2936 main.FALSE if the check fails or
2937 main.ERROR if there is some error in processing the test
2938 """
2939 try:
2940 bail = False
2941 ids = self.appIDs( jsonFormat=True )
2942 if ids:
2943 ids = json.loads( ids )
2944 else:
2945 main.log.error( "app-ids returned nothing:" + repr( ids ) )
2946 bail = True
2947 apps = self.apps( jsonFormat=True )
2948 if apps:
2949 apps = json.loads( apps )
2950 else:
2951 main.log.error( "apps returned nothing:" + repr( apps ) )
2952 bail = True
2953 if bail:
2954 return main.FALSE
2955 result = main.TRUE
2956 for app in apps:
2957 appID = app.get( 'id' )
2958 if appID is None:
2959 main.log.error( "Error parsing app: " + str( app ) )
2960 result = main.FALSE
2961 appName = app.get( 'name' )
2962 if appName is None:
2963 main.log.error( "Error parsing app: " + str( app ) )
2964 result = main.FALSE
2965 # get the entry in ids that has the same appID
2966 current = filter( lambda item: item[ 'id' ] == appID, ids )
2967 # main.log.debug( "Comparing " + str( app ) + " to " +
2968 # str( current ) )
2969 if not current: # if ids doesn't have this id
2970 result = main.FALSE
2971 main.log.error( "'app-ids' does not have the ID for " +
2972 str( appName ) + " that apps does." )
2973 elif len( current ) > 1:
2974 # there is more than one app with this ID
2975 result = main.FALSE
2976 # We will log this later in the method
2977 elif not current[0][ 'name' ] == appName:
2978 currentName = current[0][ 'name' ]
2979 result = main.FALSE
2980 main.log.error( "'app-ids' has " + str( currentName ) +
2981 " registered under id:" + str( appID ) +
2982 " but 'apps' has " + str( appName ) )
2983 else:
2984 pass # id and name match!
2985 # now make sure that app-ids has no duplicates
2986 idsList = []
2987 namesList = []
2988 for item in ids:
2989 idsList.append( item[ 'id' ] )
2990 namesList.append( item[ 'name' ] )
2991 if len( idsList ) != len( set( idsList ) ) or\
2992 len( namesList ) != len( set( namesList ) ):
2993 main.log.error( "'app-ids' has some duplicate entries: \n"
2994 + json.dumps( ids,
2995 sort_keys=True,
2996 indent=4,
2997 separators=( ',', ': ' ) ) )
2998 result = main.FALSE
2999 return result
3000 except ( ValueError, TypeError ):
3001 main.log.exception( self.name + ": Object not as expected" )
3002 return main.ERROR
3003 except pexpect.EOF:
3004 main.log.error( self.name + ": EOF exception found" )
3005 main.log.error( self.name + ": " + self.handle.before )
3006 main.cleanup()
3007 main.exit()
3008 except Exception:
3009 main.log.exception( self.name + ": Uncaught exception!" )
3010 main.cleanup()
3011 main.exit()
3012
3013 def getCfg( self, component=None, propName=None, short=False,
3014 jsonFormat=True ):
3015 """
3016 Get configuration settings from onos cli
3017 Optional arguments:
3018 component - Optionally only list configurations for a specific
3019 component. If None, all components with configurations
3020 are displayed. Case Sensitive string.
3021 propName - If component is specified, propName option will show
3022 only this specific configuration from that component.
3023 Case Sensitive string.
3024 jsonFormat - Returns output as json. Note that this will override
3025 the short option
3026 short - Short, less verbose, version of configurations.
3027 This is overridden by the json option
3028 returns:
3029 Output from cli as a string or None on error
3030 """
3031 try:
3032 baseStr = "cfg"
3033 cmdStr = " get"
3034 componentStr = ""
3035 if component:
3036 componentStr += " " + component
3037 if propName:
3038 componentStr += " " + propName
3039 if jsonFormat:
3040 baseStr += " -j"
3041 elif short:
3042 baseStr += " -s"
3043 output = self.sendline( baseStr + cmdStr + componentStr )
3044 assert "Error executing command" not in output
3045 return output
3046 except AssertionError:
3047 main.log.error( "Error in processing 'cfg get' command: " +
3048 str( output ) )
3049 return None
3050 except TypeError:
3051 main.log.exception( self.name + ": Object not as expected" )
3052 return None
3053 except pexpect.EOF:
3054 main.log.error( self.name + ": EOF exception found" )
3055 main.log.error( self.name + ": " + self.handle.before )
3056 main.cleanup()
3057 main.exit()
3058 except Exception:
3059 main.log.exception( self.name + ": Uncaught exception!" )
3060 main.cleanup()
3061 main.exit()
3062
3063 def setCfg( self, component, propName, value=None, check=True ):
3064 """
3065 Set/Unset configuration settings from ONOS cli
3066 Required arguments:
3067 component - The case sensitive name of the component whose
3068 property is to be set
3069 propName - The case sensitive name of the property to be set/unset
3070 Optional arguments:
3071 value - The value to set the property to. If None, will unset the
3072 property and revert it to it's default value(if applicable)
3073 check - Boolean, Check whether the option was successfully set this
3074 only applies when a value is given.
3075 returns:
3076 main.TRUE on success or main.FALSE on failure. If check is False,
3077 will return main.TRUE unless there is an error
3078 """
3079 try:
3080 baseStr = "cfg"
3081 cmdStr = " set " + str( component ) + " " + str( propName )
3082 if value is not None:
3083 cmdStr += " " + str( value )
3084 output = self.sendline( baseStr + cmdStr )
3085 assert "Error executing command" not in output
3086 if value and check:
3087 results = self.getCfg( component=str( component ),
3088 propName=str( propName ),
3089 jsonFormat=True )
3090 # Check if current value is what we just set
3091 try:
3092 jsonOutput = json.loads( results )
3093 current = jsonOutput[ 'value' ]
3094 except ( ValueError, TypeError ):
3095 main.log.exception( "Error parsing cfg output" )
3096 main.log.error( "output:" + repr( results ) )
3097 return main.FALSE
3098 if current == str( value ):
3099 return main.TRUE
3100 return main.FALSE
3101 return main.TRUE
3102 except AssertionError:
3103 main.log.error( "Error in processing 'cfg set' command: " +
3104 str( output ) )
3105 return main.FALSE
3106 except TypeError:
3107 main.log.exception( self.name + ": Object not as expected" )
3108 return main.FALSE
3109 except pexpect.EOF:
3110 main.log.error( self.name + ": EOF exception found" )
3111 main.log.error( self.name + ": " + self.handle.before )
3112 main.cleanup()
3113 main.exit()
3114 except Exception:
3115 main.log.exception( self.name + ": Uncaught exception!" )
3116 main.cleanup()
3117 main.exit()
3118
3119 def setTestAdd( self, setName, values ):
3120 """
3121 CLI command to add elements to a distributed set.
3122 Arguments:
3123 setName - The name of the set to add to.
3124 values - The value(s) to add to the set, space seperated.
3125 Example usages:
3126 setTestAdd( "set1", "a b c" )
3127 setTestAdd( "set2", "1" )
3128 returns:
3129 main.TRUE on success OR
3130 main.FALSE if elements were already in the set OR
3131 main.ERROR on error
3132 """
3133 try:
3134 cmdStr = "set-test-add " + str( setName ) + " " + str( values )
3135 output = self.sendline( cmdStr )
3136 try:
3137 # TODO: Maybe make this less hardcoded
3138 # ConsistentMap Exceptions
3139 assert "org.onosproject.store.service" not in output
3140 # Node not leader
3141 assert "java.lang.IllegalStateException" not in output
3142 except AssertionError:
3143 main.log.error( "Error in processing 'set-test-add' " +
3144 "command: " + str( output ) )
3145 retryTime = 30 # Conservative time, given by Madan
3146 main.log.info( "Waiting " + str( retryTime ) +
3147 "seconds before retrying." )
3148 time.sleep( retryTime ) # Due to change in mastership
3149 output = self.sendline( cmdStr )
3150 assert "Error executing command" not in output
3151 positiveMatch = "\[(.*)\] was added to the set " + str( setName )
3152 negativeMatch = "\[(.*)\] was already in set " + str( setName )
3153 main.log.info( self.name + ": " + output )
3154 if re.search( positiveMatch, output):
3155 return main.TRUE
3156 elif re.search( negativeMatch, output):
3157 return main.FALSE
3158 else:
3159 main.log.error( self.name + ": setTestAdd did not" +
3160 " match expected output" )
3161 main.log.debug( self.name + " expected: " + pattern )
3162 main.log.debug( self.name + " actual: " + repr( output ) )
3163 return main.ERROR
3164 except AssertionError:
3165 main.log.error( "Error in processing 'set-test-add' command: " +
3166 str( output ) )
3167 return main.ERROR
3168 except TypeError:
3169 main.log.exception( self.name + ": Object not as expected" )
3170 return main.ERROR
3171 except pexpect.EOF:
3172 main.log.error( self.name + ": EOF exception found" )
3173 main.log.error( self.name + ": " + self.handle.before )
3174 main.cleanup()
3175 main.exit()
3176 except Exception:
3177 main.log.exception( self.name + ": Uncaught exception!" )
3178 main.cleanup()
3179 main.exit()
3180
3181 def setTestRemove( self, setName, values, clear=False, retain=False ):
3182 """
3183 CLI command to remove elements from a distributed set.
3184 Required arguments:
3185 setName - The name of the set to remove from.
3186 values - The value(s) to remove from the set, space seperated.
3187 Optional arguments:
3188 clear - Clear all elements from the set
3189 retain - Retain only the given values. (intersection of the
3190 original set and the given set)
3191 returns:
3192 main.TRUE on success OR
3193 main.FALSE if the set was not changed OR
3194 main.ERROR on error
3195 """
3196 try:
3197 cmdStr = "set-test-remove "
3198 if clear:
3199 cmdStr += "-c " + str( setName )
3200 elif retain:
3201 cmdStr += "-r " + str( setName ) + " " + str( values )
3202 else:
3203 cmdStr += str( setName ) + " " + str( values )
3204 output = self.sendline( cmdStr )
3205 try:
3206 # TODO: Maybe make this less hardcoded
3207 # ConsistentMap Exceptions
3208 assert "org.onosproject.store.service" not in output
3209 # Node not leader
3210 assert "java.lang.IllegalStateException" not in output
3211 except AssertionError:
3212 main.log.error( "Error in processing 'set-test-add' " +
3213 "command: " + str( output ) )
3214 retryTime = 30 # Conservative time, given by Madan
3215 main.log.info( "Waiting " + str( retryTime ) +
3216 "seconds before retrying." )
3217 time.sleep( retryTime ) # Due to change in mastership
3218 output = self.sendline( cmdStr )
3219 assert "Error executing command" not in output
3220 main.log.info( self.name + ": " + output )
3221 if clear:
3222 pattern = "Set " + str( setName ) + " cleared"
3223 if re.search( pattern, output ):
3224 return main.TRUE
3225 elif retain:
3226 positivePattern = str( setName ) + " was pruned to contain " +\
3227 "only elements of set \[(.*)\]"
3228 negativePattern = str( setName ) + " was not changed by " +\
3229 "retaining only elements of the set " +\
3230 "\[(.*)\]"
3231 if re.search( positivePattern, output ):
3232 return main.TRUE
3233 elif re.search( negativePattern, output ):
3234 return main.FALSE
3235 else:
3236 positivePattern = "\[(.*)\] was removed from the set " +\
3237 str( setName )
3238 if ( len( values.split() ) == 1 ):
3239 negativePattern = "\[(.*)\] was not in set " +\
3240 str( setName )
3241 else:
3242 negativePattern = "No element of \[(.*)\] was in set " +\
3243 str( setName )
3244 if re.search( positivePattern, output ):
3245 return main.TRUE
3246 elif re.search( negativePattern, output ):
3247 return main.FALSE
3248 main.log.error( self.name + ": setTestRemove did not" +
3249 " match expected output" )
3250 main.log.debug( self.name + " expected: " + pattern )
3251 main.log.debug( self.name + " actual: " + repr( output ) )
3252 return main.ERROR
3253 except AssertionError:
3254 main.log.error( "Error in processing 'set-test-remove' command: " +
3255 str( output ) )
3256 return main.ERROR
3257 except TypeError:
3258 main.log.exception( self.name + ": Object not as expected" )
3259 return main.ERROR
3260 except pexpect.EOF:
3261 main.log.error( self.name + ": EOF exception found" )
3262 main.log.error( self.name + ": " + self.handle.before )
3263 main.cleanup()
3264 main.exit()
3265 except Exception:
3266 main.log.exception( self.name + ": Uncaught exception!" )
3267 main.cleanup()
3268 main.exit()
3269
3270 def setTestGet( self, setName, values="" ):
3271 """
3272 CLI command to get the elements in a distributed set.
3273 Required arguments:
3274 setName - The name of the set to remove from.
3275 Optional arguments:
3276 values - The value(s) to check if in the set, space seperated.
3277 returns:
3278 main.ERROR on error OR
3279 A list of elements in the set if no optional arguments are
3280 supplied OR
3281 A tuple containing the list then:
3282 main.FALSE if the given values are not in the set OR
3283 main.TRUE if the given values are in the set OR
3284 """
3285 try:
3286 values = str( values ).strip()
3287 setName = str( setName ).strip()
3288 length = len( values.split() )
3289 containsCheck = None
3290 # Patterns to match
3291 setPattern = "\[(.*)\]"
3292 pattern = "Items in set " + setName + ":\n" + setPattern
3293 containsTrue = "Set " + setName + " contains the value " + values
3294 containsFalse = "Set " + setName + " did not contain the value " +\
3295 values
3296 containsAllTrue = "Set " + setName + " contains the the subset " +\
3297 setPattern
3298 containsAllFalse = "Set " + setName + " did not contain the the" +\
3299 " subset " + setPattern
3300
3301 cmdStr = "set-test-get "
3302 cmdStr += setName + " " + values
3303 output = self.sendline( cmdStr )
3304 try:
3305 # TODO: Maybe make this less hardcoded
3306 # ConsistentMap Exceptions
3307 assert "org.onosproject.store.service" not in output
3308 # Node not leader
3309 assert "java.lang.IllegalStateException" not in output
3310 except AssertionError:
3311 main.log.error( "Error in processing 'set-test-add' " +
3312 "command: " + str( output ) )
3313 retryTime = 30 # Conservative time, given by Madan
3314 main.log.info( "Waiting " + str( retryTime ) +
3315 "seconds before retrying." )
3316 time.sleep( retryTime ) # Due to change in mastership
3317 output = self.sendline( cmdStr )
3318 assert "Error executing command" not in output
3319 main.log.info( self.name + ": " + output )
3320
3321 if length == 0:
3322 match = re.search( pattern, output )
3323 else: # if given values
3324 if length == 1: # Contains output
3325 patternTrue = pattern + "\n" + containsTrue
3326 patternFalse = pattern + "\n" + containsFalse
3327 else: # ContainsAll output
3328 patternTrue = pattern + "\n" + containsAllTrue
3329 patternFalse = pattern + "\n" + containsAllFalse
3330 matchTrue = re.search( patternTrue, output )
3331 matchFalse = re.search( patternFalse, output )
3332 if matchTrue:
3333 containsCheck = main.TRUE
3334 match = matchTrue
3335 elif matchFalse:
3336 containsCheck = main.FALSE
3337 match = matchFalse
3338 else:
3339 main.log.error( self.name + " setTestGet did not match " +\
3340 "expected output" )
3341 main.log.debug( self.name + " expected: " + pattern )
3342 main.log.debug( self.name + " actual: " + repr( output ) )
3343 match = None
3344 if match:
3345 setMatch = match.group( 1 )
3346 if setMatch == '':
3347 setList = []
3348 else:
3349 setList = setMatch.split( ", " )
3350 if length > 0:
3351 return ( setList, containsCheck )
3352 else:
3353 return setList
3354 else: # no match
3355 main.log.error( self.name + ": setTestGet did not" +
3356 " match expected output" )
3357 main.log.debug( self.name + " expected: " + pattern )
3358 main.log.debug( self.name + " actual: " + repr( output ) )
3359 return main.ERROR
3360 except AssertionError:
3361 main.log.error( "Error in processing 'set-test-get' command: " +
3362 str( output ) )
3363 return main.ERROR
3364 except TypeError:
3365 main.log.exception( self.name + ": Object not as expected" )
3366 return main.ERROR
3367 except pexpect.EOF:
3368 main.log.error( self.name + ": EOF exception found" )
3369 main.log.error( self.name + ": " + self.handle.before )
3370 main.cleanup()
3371 main.exit()
3372 except Exception:
3373 main.log.exception( self.name + ": Uncaught exception!" )
3374 main.cleanup()
3375 main.exit()
3376
3377 def setTestSize( self, setName ):
3378 """
3379 CLI command to get the elements in a distributed set.
3380 Required arguments:
3381 setName - The name of the set to remove from.
3382 returns:
3383 The integer value of the size returned or
3384 None on error
3385 """
3386 try:
3387 # TODO: Should this check against the number of elements returned
3388 # and then return true/false based on that?
3389 setName = str( setName ).strip()
3390 # Patterns to match
3391 setPattern = "\[(.*)\]"
3392 pattern = "There are (\d+) items in set " + setName + ":\n" +\
3393 setPattern
3394 cmdStr = "set-test-get -s "
3395 cmdStr += setName
3396 output = self.sendline( cmdStr )
3397 try:
3398 # TODO: Maybe make this less hardcoded
3399 # ConsistentMap Exceptions
3400 assert "org.onosproject.store.service" not in output
3401 # Node not leader
3402 assert "java.lang.IllegalStateException" not in output
3403 except AssertionError:
3404 main.log.error( "Error in processing 'set-test-add' " +
3405 "command: " + str( output ) )
3406 retryTime = 30 # Conservative time, given by Madan
3407 main.log.info( "Waiting " + str( retryTime ) +
3408 "seconds before retrying." )
3409 time.sleep( retryTime ) # Due to change in mastership
3410 output = self.sendline( cmdStr )
3411 assert "Error executing command" not in output
3412 main.log.info( self.name + ": " + output )
3413 match = re.search( pattern, output )
3414 if match:
3415 setSize = int( match.group( 1 ) )
3416 setMatch = match.group( 2 )
3417 if len( setMatch.split() ) == setSize:
3418 main.log.info( "The size returned by " + self.name +
3419 " matches the number of elements in " +
3420 "the returned set" )
3421 else:
3422 main.log.error( "The size returned by " + self.name +
3423 " does not match the number of " +
3424 "elements in the returned set." )
3425 return setSize
3426 else: # no match
3427 main.log.error( self.name + ": setTestGet did not" +
3428 " match expected output" )
3429 main.log.debug( self.name + " expected: " + pattern )
3430 main.log.debug( self.name + " actual: " + repr( output ) )
3431 return None
3432 except AssertionError:
3433 main.log.error( "Error in processing 'set-test-get' command: " +
3434 str( output ) )
3435 return None
3436 except TypeError:
3437 main.log.exception( self.name + ": Object not as expected" )
3438 return None
3439 except pexpect.EOF:
3440 main.log.error( self.name + ": EOF exception found" )
3441 main.log.error( self.name + ": " + self.handle.before )
3442 main.cleanup()
3443 main.exit()
3444 except Exception:
3445 main.log.exception( self.name + ": Uncaught exception!" )
3446 main.cleanup()
3447 main.exit()
3448
3449 def counters( self ):
3450 """
3451 Command to list the various counters in the system.
3452 returns:
3453 A dict containing the counters in the system with the counter
3454 names being the keys and the value of the counters being the
3455 values OR
3456 None on error
3457 """
3458 #FIXME: JSON FORMAT
3459 try:
3460 counters = {}
3461 cmdStr = "counters"
3462 output = self.sendline( cmdStr )
3463 assert "Error executing command" not in output
3464 main.log.info( self.name + ": " + output )
3465 for line in output.splitlines():
3466 match = re.search( "name=(\S+) value=(\d+)", line )
3467 if match:
3468 key = match.group( 1 )
3469 value = int( match.group( 2 ) )
3470 counters[key] = value
3471 else:
3472 main.log.error( self.name + ": counters did not match " +
3473 "expected output" )
3474 main.log.debug( self.name + " expected: " + pattern )
3475 main.log.debug( self.name + " actual: " + repr( output ) )
3476 return None
3477 return counters
3478 except AssertionError:
3479 main.log.error( "Error in processing 'counters' command: " +
3480 str( output ) )
3481 return main.ERROR
3482 except TypeError:
3483 main.log.exception( self.name + ": Object not as expected" )
3484 return main.ERROR
3485 except pexpect.EOF:
3486 main.log.error( self.name + ": EOF exception found" )
3487 main.log.error( self.name + ": " + self.handle.before )
3488 main.cleanup()
3489 main.exit()
3490 except Exception:
3491 main.log.exception( self.name + ": Uncaught exception!" )
3492 main.cleanup()
3493 main.exit()
3494
3495 def counterTestIncrement( self, counter, inMemory=False ):
3496 """
3497 CLI command to increment and get a distributed counter.
3498 Required arguments:
3499 counter - The name of the counter to increment.
3500 Optional arguments:
3501 inMemory - use in memory map for the counter
3502 returns:
3503 integer value of the counter or
3504 None on Error
3505 """
3506 try:
3507 counter = str( counter )
3508 cmdStr = "counter-test-increment "
3509 if inMemory:
3510 cmdStr += "-i "
3511 cmdStr += counter
3512 output = self.sendline( cmdStr )
3513 try:
3514 # TODO: Maybe make this less hardcoded
3515 # ConsistentMap Exceptions
3516 assert "org.onosproject.store.service" not in output
3517 # Node not leader
3518 assert "java.lang.IllegalStateException" not in output
3519 except AssertionError:
3520 main.log.error( "Error in processing 'set-test-add' " +
3521 "command: " + str( output ) )
3522 retryTime = 30 # Conservative time, given by Madan
3523 main.log.info( "Waiting " + str( retryTime ) +
3524 "seconds before retrying." )
3525 time.sleep( retryTime ) # Due to change in mastership
3526 output = self.sendline( cmdStr )
3527 assert "Error executing command" not in output
3528 main.log.info( self.name + ": " + output )
3529 pattern = counter + " was incremented to (\d+)"
3530 match = re.search( pattern, output )
3531 if match:
3532 return int( match.group( 1 ) )
3533 else:
3534 main.log.error( self.name + ": counterTestIncrement did not" +
3535 " match expected output." )
3536 main.log.debug( self.name + " expected: " + pattern )
3537 main.log.debug( self.name + " actual: " + repr( output ) )
3538 return None
3539 except AssertionError:
3540 main.log.error( "Error in processing 'counter-test-increment'" +
3541 " command: " + str( output ) )
3542 return None
3543 except TypeError:
3544 main.log.exception( self.name + ": Object not as expected" )
3545 return None
3546 except pexpect.EOF:
3547 main.log.error( self.name + ": EOF exception found" )
3548 main.log.error( self.name + ": " + self.handle.before )
3549 main.cleanup()
3550 main.exit()
3551 except Exception:
3552 main.log.exception( self.name + ": Uncaught exception!" )
3553 main.cleanup()
3554 main.exit()
3555