blob: 808fe7c7830a6c042c4ffba9857fa8dd71ecd551 [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() )
1818 returnValue = main.TRUE
1819 for device in tempFlows:
1820 for flow in device.get( 'flows' ):
1821 if flow.get( 'state' ) != 'ADDED' and flow.get( 'state' ) != \
1822 'PENDING_ADD':
1823 main.log.info( self.name + ": flow Id: " +
1824 flow.get( 'id' ) +
1825 " | state:" + flow.get( 'state' ) )
1826 returnValue = main.FALSE
1827 return returnValue
1828 except TypeError:
1829 main.log.exception( self.name + ": Object not as expected" )
1830 return None
1831 except pexpect.EOF:
1832 main.log.error( self.name + ": EOF exception found" )
1833 main.log.error( self.name + ": " + self.handle.before )
1834 main.cleanup()
1835 main.exit()
1836 except Exception:
1837 main.log.exception( self.name + ": Uncaught exception!" )
Shreya Shah0f01c812014-10-26 20:15:28 -04001838 main.cleanup()
1839 main.exit()
1840
kelvin-onlabd3b64892015-01-20 13:26:24 -08001841 def pushTestIntents( self, dpidSrc, dpidDst, numIntents,
pingping-lin763ee042015-05-20 17:45:30 -07001842 numMult="", appId="", report=True ):
kelvin8ec71442015-01-15 16:57:00 -08001843 """
andrewonlab87852b02014-11-19 18:44:19 -05001844 Description:
Jon Halle3f39ff2015-01-13 11:50:53 -08001845 Push a number of intents in a batch format to
andrewonlab87852b02014-11-19 18:44:19 -05001846 a specific point-to-point intent definition
1847 Required:
kelvin-onlabd3b64892015-01-20 13:26:24 -08001848 * dpidSrc: specify source dpid
1849 * dpidDst: specify destination dpid
1850 * numIntents: specify number of intents to push
andrewonlab87852b02014-11-19 18:44:19 -05001851 Optional:
kelvin-onlabd3b64892015-01-20 13:26:24 -08001852 * numMult: number multiplier for multiplying
andrewonlabb66dfa12014-12-02 15:51:10 -05001853 the number of intents specified
kelvin-onlabd3b64892015-01-20 13:26:24 -08001854 * appId: specify the application id init to further
andrewonlabb66dfa12014-12-02 15:51:10 -05001855 modularize the intents
andrewonlab87852b02014-11-19 18:44:19 -05001856 * report: default True, returns latency information
kelvin8ec71442015-01-15 16:57:00 -08001857 """
andrewonlab87852b02014-11-19 18:44:19 -05001858 try:
kelvin8ec71442015-01-15 16:57:00 -08001859 cmd = "push-test-intents " +\
kelvin-onlabd3b64892015-01-20 13:26:24 -08001860 str( dpidSrc ) + " " + str( dpidDst ) + " " +\
1861 str( numIntents )
1862 if numMult:
1863 cmd += " " + str( numMult )
1864 # If app id is specified, then numMult
kelvin8ec71442015-01-15 16:57:00 -08001865 # must exist because of the way this command
kelvin-onlabd3b64892015-01-20 13:26:24 -08001866 if appId:
1867 cmd += " " + str( appId )
kelvin-onlab898a6c62015-01-16 14:13:53 -08001868 handle = self.sendline( cmd )
andrewonlab87852b02014-11-19 18:44:19 -05001869 if report:
kelvin-onlabd3b64892015-01-20 13:26:24 -08001870 latResult = []
kelvin8ec71442015-01-15 16:57:00 -08001871 main.log.info( handle )
1872 # Split result by newline
1873 newline = handle.split( "\r\r\n" )
1874 # Ignore the first object of list, which is empty
1875 newline = newline[ 1: ]
1876 # Some sloppy parsing method to get the latency
andrewonlabb66dfa12014-12-02 15:51:10 -05001877 for result in newline:
kelvin8ec71442015-01-15 16:57:00 -08001878 result = result.split( ": " )
1879 # Append the first result of second parse
kelvin-onlabd3b64892015-01-20 13:26:24 -08001880 latResult.append( result[ 1 ].split( " " )[ 0 ] )
1881 main.log.info( latResult )
1882 return latResult
andrewonlab87852b02014-11-19 18:44:19 -05001883 else:
1884 return main.TRUE
pingping-lin763ee042015-05-20 17:45:30 -07001885 except TypeError:
1886 main.log.exception( self.name + ": Object not as expected" )
1887 return None
andrewonlab87852b02014-11-19 18:44:19 -05001888 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08001889 main.log.error( self.name + ": EOF exception found" )
1890 main.log.error( self.name + ": " + self.handle.before )
andrewonlab87852b02014-11-19 18:44:19 -05001891 main.cleanup()
1892 main.exit()
pingping-lin763ee042015-05-20 17:45:30 -07001893 except Exception:
1894 main.log.exception( self.name + ": Uncaught exception!" )
andrewonlab87852b02014-11-19 18:44:19 -05001895 main.cleanup()
1896 main.exit()
1897
kelvin-onlabd3b64892015-01-20 13:26:24 -08001898 def intentsEventsMetrics( self, jsonFormat=True ):
kelvin8ec71442015-01-15 16:57:00 -08001899 """
Jon Halle3f39ff2015-01-13 11:50:53 -08001900 Description:Returns topology metrics
andrewonlab0dbb6ec2014-11-06 13:46:55 -05001901 Optional:
kelvin-onlabd3b64892015-01-20 13:26:24 -08001902 * jsonFormat: enable json formatting of output
kelvin8ec71442015-01-15 16:57:00 -08001903 """
andrewonlab0dbb6ec2014-11-06 13:46:55 -05001904 try:
pingping-lin763ee042015-05-20 17:45:30 -07001905 cmdStr = "intents-events-metrics"
kelvin-onlabd3b64892015-01-20 13:26:24 -08001906 if jsonFormat:
pingping-lin763ee042015-05-20 17:45:30 -07001907 cmdStr += " -j"
1908 handle = self.sendline( cmdStr )
andrewonlab0dbb6ec2014-11-06 13:46:55 -05001909 return handle
pingping-lin763ee042015-05-20 17:45:30 -07001910 except TypeError:
1911 main.log.exception( self.name + ": Object not as expected" )
1912 return None
andrewonlab0dbb6ec2014-11-06 13:46:55 -05001913 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08001914 main.log.error( self.name + ": EOF exception found" )
1915 main.log.error( self.name + ": " + self.handle.before )
andrewonlab0dbb6ec2014-11-06 13:46:55 -05001916 main.cleanup()
1917 main.exit()
pingping-lin763ee042015-05-20 17:45:30 -07001918 except Exception:
1919 main.log.exception( self.name + ": Uncaught exception!" )
andrewonlab0dbb6ec2014-11-06 13:46:55 -05001920 main.cleanup()
1921 main.exit()
Shreya Shah0f01c812014-10-26 20:15:28 -04001922
kelvin-onlabd3b64892015-01-20 13:26:24 -08001923 def topologyEventsMetrics( self, jsonFormat=True ):
kelvin8ec71442015-01-15 16:57:00 -08001924 """
1925 Description:Returns topology metrics
andrewonlab867212a2014-10-22 20:13:38 -04001926 Optional:
kelvin-onlabd3b64892015-01-20 13:26:24 -08001927 * jsonFormat: enable json formatting of output
kelvin8ec71442015-01-15 16:57:00 -08001928 """
andrewonlab867212a2014-10-22 20:13:38 -04001929 try:
pingping-lin763ee042015-05-20 17:45:30 -07001930 cmdStr = "topology-events-metrics"
kelvin-onlabd3b64892015-01-20 13:26:24 -08001931 if jsonFormat:
pingping-lin763ee042015-05-20 17:45:30 -07001932 cmdStr += " -j"
1933 handle = self.sendline( cmdStr )
1934 if handle:
1935 return handle
1936 elif jsonFormat:
1937 # Return empty json
1938 return '{}'
andrewonlab867212a2014-10-22 20:13:38 -04001939 else:
pingping-lin763ee042015-05-20 17:45:30 -07001940 return handle
1941 except TypeError:
1942 main.log.exception( self.name + ": Object not as expected" )
1943 return None
andrewonlab867212a2014-10-22 20:13:38 -04001944 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08001945 main.log.error( self.name + ": EOF exception found" )
1946 main.log.error( self.name + ": " + self.handle.before )
andrewonlab867212a2014-10-22 20:13:38 -04001947 main.cleanup()
1948 main.exit()
pingping-lin763ee042015-05-20 17:45:30 -07001949 except Exception:
1950 main.log.exception( self.name + ": Uncaught exception!" )
andrewonlab867212a2014-10-22 20:13:38 -04001951 main.cleanup()
1952 main.exit()
1953
kelvin8ec71442015-01-15 16:57:00 -08001954 # Wrapper functions ****************
1955 # Wrapper functions use existing driver
1956 # functions and extends their use case.
1957 # For example, we may use the output of
1958 # a normal driver function, and parse it
1959 # using a wrapper function
andrewonlabc2d05aa2014-10-13 16:51:10 -04001960
kelvin-onlabd3b64892015-01-20 13:26:24 -08001961 def getAllIntentsId( self ):
kelvin8ec71442015-01-15 16:57:00 -08001962 """
andrewonlab9a50dfe2014-10-17 17:22:31 -04001963 Description:
1964 Obtain all intent id's in a list
kelvin8ec71442015-01-15 16:57:00 -08001965 """
andrewonlab9a50dfe2014-10-17 17:22:31 -04001966 try:
kelvin8ec71442015-01-15 16:57:00 -08001967 # Obtain output of intents function
pingping-lin763ee042015-05-20 17:45:30 -07001968 intentsStr = self.intents(jsonFormat=False)
kelvin-onlabd3b64892015-01-20 13:26:24 -08001969 intentIdList = []
andrewonlab9a50dfe2014-10-17 17:22:31 -04001970
kelvin8ec71442015-01-15 16:57:00 -08001971 # Parse the intents output for ID's
kelvin-onlabd3b64892015-01-20 13:26:24 -08001972 intentsList = [ s.strip() for s in intentsStr.splitlines() ]
1973 for intents in intentsList:
pingping-lin763ee042015-05-20 17:45:30 -07001974 match = re.search('id=0x([\da-f]+),', intents)
1975 if match:
1976 tmpId = match.group()[3:-1]
1977 intentIdList.append( tmpId )
kelvin-onlabd3b64892015-01-20 13:26:24 -08001978 return intentIdList
andrewonlab9a50dfe2014-10-17 17:22:31 -04001979
pingping-lin763ee042015-05-20 17:45:30 -07001980 except TypeError:
1981 main.log.exception( self.name + ": Object not as expected" )
1982 return None
andrewonlab9a50dfe2014-10-17 17:22:31 -04001983 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08001984 main.log.error( self.name + ": EOF exception found" )
1985 main.log.error( self.name + ": " + self.handle.before )
andrewonlab9a50dfe2014-10-17 17:22:31 -04001986 main.cleanup()
1987 main.exit()
pingping-lin763ee042015-05-20 17:45:30 -07001988 except Exception:
1989 main.log.exception( self.name + ": Uncaught exception!" )
1990 main.cleanup()
1991 main.exit()
1992
1993 def FlowAddedCount( self, deviceId ):
1994 """
1995 Determine the number of flow rules for the given device id that are
1996 in the added state
1997 """
1998 try:
1999 cmdStr = "flows any " + str( deviceId ) + " | " +\
2000 "grep 'state=ADDED' | wc -l"
2001 handle = self.sendline( cmdStr )
2002 return handle
2003 except pexpect.EOF:
2004 main.log.error( self.name + ": EOF exception found" )
2005 main.log.error( self.name + ": " + self.handle.before )
2006 main.cleanup()
2007 main.exit()
2008 except Exception:
2009 main.log.exception( self.name + ": Uncaught exception!" )
andrewonlab9a50dfe2014-10-17 17:22:31 -04002010 main.cleanup()
2011 main.exit()
2012
kelvin-onlabd3b64892015-01-20 13:26:24 -08002013 def getAllDevicesId( self ):
kelvin8ec71442015-01-15 16:57:00 -08002014 """
andrewonlab7e4d2d32014-10-15 13:23:21 -04002015 Use 'devices' function to obtain list of all devices
2016 and parse the result to obtain a list of all device
2017 id's. Returns this list. Returns empty list if no
2018 devices exist
kelvin8ec71442015-01-15 16:57:00 -08002019 List is ordered sequentially
2020
andrewonlab3e15ead2014-10-15 14:21:34 -04002021 This function may be useful if you are not sure of the
kelvin8ec71442015-01-15 16:57:00 -08002022 device id, and wish to execute other commands using
andrewonlab3e15ead2014-10-15 14:21:34 -04002023 the ids. By obtaining the list of device ids on the fly,
2024 you can iterate through the list to get mastership, etc.
kelvin8ec71442015-01-15 16:57:00 -08002025 """
andrewonlab7e4d2d32014-10-15 13:23:21 -04002026 try:
kelvin8ec71442015-01-15 16:57:00 -08002027 # Call devices and store result string
kelvin-onlabd3b64892015-01-20 13:26:24 -08002028 devicesStr = self.devices( jsonFormat=False )
2029 idList = []
kelvin8ec71442015-01-15 16:57:00 -08002030
kelvin-onlabd3b64892015-01-20 13:26:24 -08002031 if not devicesStr:
kelvin8ec71442015-01-15 16:57:00 -08002032 main.log.info( "There are no devices to get id from" )
kelvin-onlabd3b64892015-01-20 13:26:24 -08002033 return idList
kelvin8ec71442015-01-15 16:57:00 -08002034
2035 # Split the string into list by comma
kelvin-onlabd3b64892015-01-20 13:26:24 -08002036 deviceList = devicesStr.split( "," )
kelvin8ec71442015-01-15 16:57:00 -08002037 # Get temporary list of all arguments with string 'id='
kelvin-onlabd3b64892015-01-20 13:26:24 -08002038 tempList = [ dev for dev in deviceList if "id=" in dev ]
kelvin8ec71442015-01-15 16:57:00 -08002039 # Split list further into arguments before and after string
2040 # 'id='. Get the latter portion ( the actual device id ) and
kelvin-onlabd3b64892015-01-20 13:26:24 -08002041 # append to idList
2042 for arg in tempList:
2043 idList.append( arg.split( "id=" )[ 1 ] )
2044 return idList
andrewonlab7e4d2d32014-10-15 13:23:21 -04002045
pingping-lin763ee042015-05-20 17:45:30 -07002046 except TypeError:
2047 main.log.exception( self.name + ": Object not as expected" )
2048 return None
andrewonlab7e4d2d32014-10-15 13:23:21 -04002049 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08002050 main.log.error( self.name + ": EOF exception found" )
2051 main.log.error( self.name + ": " + self.handle.before )
andrewonlab7e4d2d32014-10-15 13:23:21 -04002052 main.cleanup()
2053 main.exit()
pingping-lin763ee042015-05-20 17:45:30 -07002054 except Exception:
2055 main.log.exception( self.name + ": Uncaught exception!" )
andrewonlab7e4d2d32014-10-15 13:23:21 -04002056 main.cleanup()
2057 main.exit()
2058
kelvin-onlabd3b64892015-01-20 13:26:24 -08002059 def getAllNodesId( self ):
kelvin8ec71442015-01-15 16:57:00 -08002060 """
andrewonlab7c211572014-10-15 16:45:20 -04002061 Uses 'nodes' function to obtain list of all nodes
2062 and parse the result of nodes to obtain just the
kelvin8ec71442015-01-15 16:57:00 -08002063 node id's.
andrewonlab7c211572014-10-15 16:45:20 -04002064 Returns:
2065 list of node id's
kelvin8ec71442015-01-15 16:57:00 -08002066 """
andrewonlab7c211572014-10-15 16:45:20 -04002067 try:
pingping-lin763ee042015-05-20 17:45:30 -07002068 nodesStr = self.nodes( jsonFormat=True )
kelvin-onlabd3b64892015-01-20 13:26:24 -08002069 idList = []
pingping-lin763ee042015-05-20 17:45:30 -07002070 # Sample nodesStr output
2071 # id=local, address=127.0.0.1:9876, state=ACTIVE *
kelvin-onlabd3b64892015-01-20 13:26:24 -08002072 if not nodesStr:
kelvin8ec71442015-01-15 16:57:00 -08002073 main.log.info( "There are no nodes to get id from" )
kelvin-onlabd3b64892015-01-20 13:26:24 -08002074 return idList
pingping-lin763ee042015-05-20 17:45:30 -07002075 nodesJson = json.loads( nodesStr )
2076 idList = [ node.get('id') for node in nodesJson ]
kelvin-onlabd3b64892015-01-20 13:26:24 -08002077 return idList
kelvin8ec71442015-01-15 16:57:00 -08002078
pingping-lin763ee042015-05-20 17:45:30 -07002079 except TypeError:
2080 main.log.exception( self.name + ": Object not as expected" )
2081 return None
andrewonlab7c211572014-10-15 16:45:20 -04002082 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08002083 main.log.error( self.name + ": EOF exception found" )
2084 main.log.error( self.name + ": " + self.handle.before )
andrewonlab7c211572014-10-15 16:45:20 -04002085 main.cleanup()
2086 main.exit()
pingping-lin763ee042015-05-20 17:45:30 -07002087 except Exception:
2088 main.log.exception( self.name + ": Uncaught exception!" )
andrewonlab7c211572014-10-15 16:45:20 -04002089 main.cleanup()
2090 main.exit()
andrewonlab7e4d2d32014-10-15 13:23:21 -04002091
kelvin-onlabd3b64892015-01-20 13:26:24 -08002092 def getDevice( self, dpid=None ):
kelvin8ec71442015-01-15 16:57:00 -08002093 """
Jon Halla91c4dc2014-10-22 12:57:04 -04002094 Return the first device from the devices api whose 'id' contains 'dpid'
2095 Return None if there is no match
kelvin8ec71442015-01-15 16:57:00 -08002096 """
Jon Halla91c4dc2014-10-22 12:57:04 -04002097 try:
kelvin8ec71442015-01-15 16:57:00 -08002098 if dpid is None:
Jon Halla91c4dc2014-10-22 12:57:04 -04002099 return None
2100 else:
kelvin8ec71442015-01-15 16:57:00 -08002101 dpid = dpid.replace( ':', '' )
kelvin-onlabd3b64892015-01-20 13:26:24 -08002102 rawDevices = self.devices()
2103 devicesJson = json.loads( rawDevices )
kelvin8ec71442015-01-15 16:57:00 -08002104 # search json for the device with dpid then return the device
kelvin-onlabd3b64892015-01-20 13:26:24 -08002105 for device in devicesJson:
kelvin8ec71442015-01-15 16:57:00 -08002106 # print "%s in %s?" % ( dpid, device[ 'id' ] )
2107 if dpid in device[ 'id' ]:
Jon Halla91c4dc2014-10-22 12:57:04 -04002108 return device
2109 return None
pingping-lin763ee042015-05-20 17:45:30 -07002110 except TypeError:
2111 main.log.exception( self.name + ": Object not as expected" )
2112 return None
Jon Halla91c4dc2014-10-22 12:57:04 -04002113 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08002114 main.log.error( self.name + ": EOF exception found" )
2115 main.log.error( self.name + ": " + self.handle.before )
Jon Halla91c4dc2014-10-22 12:57:04 -04002116 main.cleanup()
2117 main.exit()
pingping-lin763ee042015-05-20 17:45:30 -07002118 except Exception:
2119 main.log.exception( self.name + ": Uncaught exception!" )
Jon Halla91c4dc2014-10-22 12:57:04 -04002120 main.cleanup()
2121 main.exit()
2122
kelvin-onlabd3b64892015-01-20 13:26:24 -08002123 def checkStatus( self, ip, numoswitch, numolink, logLevel="info" ):
kelvin8ec71442015-01-15 16:57:00 -08002124 """
pingping-lin763ee042015-05-20 17:45:30 -07002125 Checks the number of switches & links that ONOS sees against the
kelvin8ec71442015-01-15 16:57:00 -08002126 supplied values. By default this will report to main.log, but the
pingping-lin763ee042015-05-20 17:45:30 -07002127 log level can be specified.
kelvin8ec71442015-01-15 16:57:00 -08002128
Jon Hall42db6dc2014-10-24 19:03:48 -04002129 Params: ip = ip used for the onos cli
2130 numoswitch = expected number of switches
pingping-lin763ee042015-05-20 17:45:30 -07002131 numolink = expected number of links
kelvin-onlabd3b64892015-01-20 13:26:24 -08002132 logLevel = level to log to. Currently accepts
2133 'info', 'warn' and 'report'
Jon Hall42db6dc2014-10-24 19:03:48 -04002134
2135
kelvin-onlabd3b64892015-01-20 13:26:24 -08002136 logLevel can
Jon Hall42db6dc2014-10-24 19:03:48 -04002137
pingping-lin763ee042015-05-20 17:45:30 -07002138 Returns: main.TRUE if the number of switches and links are correct,
2139 main.FALSE if the number of switches and links is incorrect,
Jon Hall42db6dc2014-10-24 19:03:48 -04002140 and main.ERROR otherwise
kelvin8ec71442015-01-15 16:57:00 -08002141 """
Jon Hall42db6dc2014-10-24 19:03:48 -04002142 try:
kelvin-onlabd3b64892015-01-20 13:26:24 -08002143 topology = self.getTopology( ip )
Jon Hall42db6dc2014-10-24 19:03:48 -04002144 if topology == {}:
2145 return main.ERROR
2146 output = ""
kelvin8ec71442015-01-15 16:57:00 -08002147 # Is the number of switches is what we expected
2148 devices = topology.get( 'devices', False )
2149 links = topology.get( 'links', False )
pingping-lin763ee042015-05-20 17:45:30 -07002150 if devices is False or links is False:
Jon Hall42db6dc2014-10-24 19:03:48 -04002151 return main.ERROR
kelvin-onlabd3b64892015-01-20 13:26:24 -08002152 switchCheck = ( int( devices ) == int( numoswitch ) )
kelvin8ec71442015-01-15 16:57:00 -08002153 # Is the number of links is what we expected
kelvin-onlabd3b64892015-01-20 13:26:24 -08002154 linkCheck = ( int( links ) == int( numolink ) )
2155 if ( switchCheck and linkCheck ):
kelvin8ec71442015-01-15 16:57:00 -08002156 # We expected the correct numbers
pingping-lin763ee042015-05-20 17:45:30 -07002157 output += "The number of links and switches match " +\
2158 "what was expected"
Jon Hall42db6dc2014-10-24 19:03:48 -04002159 result = main.TRUE
2160 else:
pingping-lin763ee042015-05-20 17:45:30 -07002161 output += "The number of links and switches does not match " +\
2162 "what was expected"
Jon Hall42db6dc2014-10-24 19:03:48 -04002163 result = main.FALSE
kelvin-onlabd3b64892015-01-20 13:26:24 -08002164 output = output + "\n ONOS sees %i devices (%i expected) \
2165 and %i links (%i expected)" % (
2166 int( devices ), int( numoswitch ), int( links ),
2167 int( numolink ) )
2168 if logLevel == "report":
kelvin8ec71442015-01-15 16:57:00 -08002169 main.log.report( output )
kelvin-onlabd3b64892015-01-20 13:26:24 -08002170 elif logLevel == "warn":
kelvin8ec71442015-01-15 16:57:00 -08002171 main.log.warn( output )
Jon Hall42db6dc2014-10-24 19:03:48 -04002172 else:
pingping-lin763ee042015-05-20 17:45:30 -07002173 main.log.info( self.name + ": " + output )
kelvin8ec71442015-01-15 16:57:00 -08002174 return result
pingping-lin763ee042015-05-20 17:45:30 -07002175 except TypeError:
2176 main.log.exception( self.name + ": Object not as expected" )
2177 return None
Jon Hall42db6dc2014-10-24 19:03:48 -04002178 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08002179 main.log.error( self.name + ": EOF exception found" )
2180 main.log.error( self.name + ": " + self.handle.before )
Jon Hall42db6dc2014-10-24 19:03:48 -04002181 main.cleanup()
2182 main.exit()
pingping-lin763ee042015-05-20 17:45:30 -07002183 except Exception:
2184 main.log.exception( self.name + ": Uncaught exception!" )
Jon Hall42db6dc2014-10-24 19:03:48 -04002185 main.cleanup()
2186 main.exit()
Jon Hall1c9e8732014-10-27 19:29:27 -04002187
kelvin-onlabd3b64892015-01-20 13:26:24 -08002188 def deviceRole( self, deviceId, onosNode, role="master" ):
kelvin8ec71442015-01-15 16:57:00 -08002189 """
Jon Hall1c9e8732014-10-27 19:29:27 -04002190 Calls the device-role cli command.
kelvin-onlabd3b64892015-01-20 13:26:24 -08002191 deviceId must be the id of a device as seen in the onos devices command
2192 onosNode is the ip of one of the onos nodes in the cluster
Jon Hall1c9e8732014-10-27 19:29:27 -04002193 role must be either master, standby, or none
2194
Jon Halle3f39ff2015-01-13 11:50:53 -08002195 Returns:
2196 main.TRUE or main.FALSE based on argument verification and
2197 main.ERROR if command returns and error
kelvin-onlab898a6c62015-01-16 14:13:53 -08002198 """
Jon Hall1c9e8732014-10-27 19:29:27 -04002199 try:
Jon Halle3f39ff2015-01-13 11:50:53 -08002200 if role.lower() == "master" or role.lower() == "standby" or\
Jon Hall1c9e8732014-10-27 19:29:27 -04002201 role.lower() == "none":
kelvin-onlabd3b64892015-01-20 13:26:24 -08002202 cmdStr = "device-role " +\
2203 str( deviceId ) + " " +\
2204 str( onosNode ) + " " +\
kelvin-onlab898a6c62015-01-16 14:13:53 -08002205 str( role )
kelvin-onlabd3b64892015-01-20 13:26:24 -08002206 handle = self.sendline( cmdStr )
kelvin-onlab898a6c62015-01-16 14:13:53 -08002207 if re.search( "Error", handle ):
2208 # end color output to escape any colours
2209 # from the cli
kelvin8ec71442015-01-15 16:57:00 -08002210 main.log.error( self.name + ": " +
kelvin-onlab898a6c62015-01-16 14:13:53 -08002211 handle + '\033[0m' )
kelvin8ec71442015-01-15 16:57:00 -08002212 return main.ERROR
kelvin8ec71442015-01-15 16:57:00 -08002213 return main.TRUE
Jon Hall1c9e8732014-10-27 19:29:27 -04002214 else:
kelvin-onlab898a6c62015-01-16 14:13:53 -08002215 main.log.error( "Invalid 'role' given to device_role(). " +
2216 "Value was '" + str(role) + "'." )
Jon Hall1c9e8732014-10-27 19:29:27 -04002217 return main.FALSE
pingping-lin763ee042015-05-20 17:45:30 -07002218 except TypeError:
2219 main.log.exception( self.name + ": Object not as expected" )
2220 return None
Jon Hall1c9e8732014-10-27 19:29:27 -04002221 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08002222 main.log.error( self.name + ": EOF exception found" )
2223 main.log.error( self.name + ": " + self.handle.before )
Jon Hall1c9e8732014-10-27 19:29:27 -04002224 main.cleanup()
2225 main.exit()
pingping-lin763ee042015-05-20 17:45:30 -07002226 except Exception:
2227 main.log.exception( self.name + ": Uncaught exception!" )
Jon Hall1c9e8732014-10-27 19:29:27 -04002228 main.cleanup()
2229 main.exit()
2230
kelvin-onlabd3b64892015-01-20 13:26:24 -08002231 def clusters( self, jsonFormat=True ):
kelvin8ec71442015-01-15 16:57:00 -08002232 """
Jon Hall73cf9cc2014-11-20 22:28:38 -08002233 Lists all clusters
Jon Hallffb386d2014-11-21 13:43:38 -08002234 Optional argument:
kelvin-onlabd3b64892015-01-20 13:26:24 -08002235 * jsonFormat - boolean indicating if you want output in json
kelvin8ec71442015-01-15 16:57:00 -08002236 """
Jon Hall73cf9cc2014-11-20 22:28:38 -08002237 try:
pingping-lin763ee042015-05-20 17:45:30 -07002238 cmdStr = "clusters"
kelvin-onlabd3b64892015-01-20 13:26:24 -08002239 if jsonFormat:
pingping-lin763ee042015-05-20 17:45:30 -07002240 cmdStr += " -j"
2241 handle = self.sendline( cmdStr )
2242 return handle
2243 except TypeError:
2244 main.log.exception( self.name + ": Object not as expected" )
2245 return None
Jon Hall73cf9cc2014-11-20 22:28:38 -08002246 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08002247 main.log.error( self.name + ": EOF exception found" )
2248 main.log.error( self.name + ": " + self.handle.before )
Jon Hall73cf9cc2014-11-20 22:28:38 -08002249 main.cleanup()
2250 main.exit()
pingping-lin763ee042015-05-20 17:45:30 -07002251 except Exception:
2252 main.log.exception( self.name + ": Uncaught exception!" )
Jon Hall73cf9cc2014-11-20 22:28:38 -08002253 main.cleanup()
2254 main.exit()
2255
kelvin-onlabd3b64892015-01-20 13:26:24 -08002256 def electionTestLeader( self ):
kelvin-onlab898a6c62015-01-16 14:13:53 -08002257 """
Jon Halle3f39ff2015-01-13 11:50:53 -08002258 CLI command to get the current leader for the Election test application
2259 NOTE: Requires installation of the onos-app-election feature
2260 Returns: Node IP of the leader if one exists
2261 None if none exists
2262 Main.FALSE on error
kelvin-onlab898a6c62015-01-16 14:13:53 -08002263 """
Jon Hall94fd0472014-12-08 11:52:42 -08002264 try:
kelvin-onlabd3b64892015-01-20 13:26:24 -08002265 cmdStr = "election-test-leader"
2266 response = self.sendline( cmdStr )
Jon Halle3f39ff2015-01-13 11:50:53 -08002267 # Leader
2268 leaderPattern = "The\scurrent\sleader\sfor\sthe\sElection\s" +\
kelvin-onlab898a6c62015-01-16 14:13:53 -08002269 "app\sis\s(?P<node>.+)\."
kelvin-onlabd3b64892015-01-20 13:26:24 -08002270 nodeSearch = re.search( leaderPattern, response )
2271 if nodeSearch:
2272 node = nodeSearch.group( 'node' )
Jon Halle3f39ff2015-01-13 11:50:53 -08002273 main.log.info( "Election-test-leader on " + str( self.name ) +
kelvin-onlab898a6c62015-01-16 14:13:53 -08002274 " found " + node + " as the leader" )
Jon Hall94fd0472014-12-08 11:52:42 -08002275 return node
Jon Halle3f39ff2015-01-13 11:50:53 -08002276 # no leader
2277 nullPattern = "There\sis\scurrently\sno\sleader\selected\sfor\s" +\
kelvin-onlab898a6c62015-01-16 14:13:53 -08002278 "the\sElection\sapp"
kelvin-onlabd3b64892015-01-20 13:26:24 -08002279 nullSearch = re.search( nullPattern, response )
2280 if nullSearch:
Jon Halle3f39ff2015-01-13 11:50:53 -08002281 main.log.info( "Election-test-leader found no leader on " +
kelvin-onlab898a6c62015-01-16 14:13:53 -08002282 self.name )
Jon Hall94fd0472014-12-08 11:52:42 -08002283 return None
kelvin-onlab898a6c62015-01-16 14:13:53 -08002284 # error
Jon Halle3f39ff2015-01-13 11:50:53 -08002285 errorPattern = "Command\snot\sfound"
kelvin-onlab898a6c62015-01-16 14:13:53 -08002286 if re.search( errorPattern, response ):
2287 main.log.error( "Election app is not loaded on " + self.name )
Jon Halle3f39ff2015-01-13 11:50:53 -08002288 # TODO: Should this be main.ERROR?
Jon Hall669173b2014-12-17 11:36:30 -08002289 return main.FALSE
2290 else:
pingping-lin763ee042015-05-20 17:45:30 -07002291 main.log.error( "Error in electionTestLeader on " + self.name +
2292 ": " + "unexpected response" )
kelvin8ec71442015-01-15 16:57:00 -08002293 main.log.error( repr( response ) )
Jon Hall669173b2014-12-17 11:36:30 -08002294 return main.FALSE
pingping-lin763ee042015-05-20 17:45:30 -07002295 except TypeError:
2296 main.log.exception( self.name + ": Object not as expected" )
2297 return main.FALSE
Jon Hall94fd0472014-12-08 11:52:42 -08002298 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08002299 main.log.error( self.name + ": EOF exception found" )
2300 main.log.error( self.name + ": " + self.handle.before )
Jon Hall94fd0472014-12-08 11:52:42 -08002301 main.cleanup()
2302 main.exit()
pingping-lin763ee042015-05-20 17:45:30 -07002303 except Exception:
2304 main.log.exception( self.name + ": Uncaught exception!" )
Jon Hall94fd0472014-12-08 11:52:42 -08002305 main.cleanup()
2306 main.exit()
2307
kelvin-onlabd3b64892015-01-20 13:26:24 -08002308 def electionTestRun( self ):
kelvin-onlab898a6c62015-01-16 14:13:53 -08002309 """
Jon Halle3f39ff2015-01-13 11:50:53 -08002310 CLI command to run for leadership of the Election test application.
2311 NOTE: Requires installation of the onos-app-election feature
2312 Returns: Main.TRUE on success
2313 Main.FALSE on error
kelvin-onlab898a6c62015-01-16 14:13:53 -08002314 """
Jon Hall94fd0472014-12-08 11:52:42 -08002315 try:
kelvin-onlabd3b64892015-01-20 13:26:24 -08002316 cmdStr = "election-test-run"
2317 response = self.sendline( cmdStr )
kelvin-onlab898a6c62015-01-16 14:13:53 -08002318 # success
Jon Halle3f39ff2015-01-13 11:50:53 -08002319 successPattern = "Entering\sleadership\selections\sfor\sthe\s" +\
kelvin-onlab898a6c62015-01-16 14:13:53 -08002320 "Election\sapp."
Jon Halle3f39ff2015-01-13 11:50:53 -08002321 search = re.search( successPattern, response )
Jon Hall94fd0472014-12-08 11:52:42 -08002322 if search:
Jon Halle3f39ff2015-01-13 11:50:53 -08002323 main.log.info( self.name + " entering leadership elections " +
kelvin-onlab898a6c62015-01-16 14:13:53 -08002324 "for the Election app." )
Jon Hall94fd0472014-12-08 11:52:42 -08002325 return main.TRUE
kelvin-onlab898a6c62015-01-16 14:13:53 -08002326 # error
Jon Halle3f39ff2015-01-13 11:50:53 -08002327 errorPattern = "Command\snot\sfound"
2328 if re.search( errorPattern, response ):
2329 main.log.error( "Election app is not loaded on " + self.name )
Jon Hall669173b2014-12-17 11:36:30 -08002330 return main.FALSE
2331 else:
pingping-lin763ee042015-05-20 17:45:30 -07002332 main.log.error( "Error in electionTestRun on " + self.name +
2333 ": " + "unexpected response" )
Jon Halle3f39ff2015-01-13 11:50:53 -08002334 main.log.error( repr( response ) )
Jon Hall669173b2014-12-17 11:36:30 -08002335 return main.FALSE
pingping-lin763ee042015-05-20 17:45:30 -07002336 except TypeError:
2337 main.log.exception( self.name + ": Object not as expected" )
2338 return main.FALSE
Jon Hall94fd0472014-12-08 11:52:42 -08002339 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08002340 main.log.error( self.name + ": EOF exception found" )
2341 main.log.error( self.name + ": " + self.handle.before )
Jon Hall94fd0472014-12-08 11:52:42 -08002342 main.cleanup()
2343 main.exit()
pingping-lin763ee042015-05-20 17:45:30 -07002344 except Exception:
2345 main.log.exception( self.name + ": Uncaught exception!" )
Jon Hall94fd0472014-12-08 11:52:42 -08002346 main.cleanup()
2347 main.exit()
2348
kelvin-onlabd3b64892015-01-20 13:26:24 -08002349 def electionTestWithdraw( self ):
kelvin8ec71442015-01-15 16:57:00 -08002350 """
Jon Hall94fd0472014-12-08 11:52:42 -08002351 * CLI command to withdraw the local node from leadership election for
2352 * the Election test application.
2353 #NOTE: Requires installation of the onos-app-election feature
2354 Returns: Main.TRUE on success
2355 Main.FALSE on error
kelvin8ec71442015-01-15 16:57:00 -08002356 """
Jon Hall94fd0472014-12-08 11:52:42 -08002357 try:
kelvin-onlabd3b64892015-01-20 13:26:24 -08002358 cmdStr = "election-test-withdraw"
2359 response = self.sendline( cmdStr )
kelvin-onlab898a6c62015-01-16 14:13:53 -08002360 # success
Jon Halle3f39ff2015-01-13 11:50:53 -08002361 successPattern = "Withdrawing\sfrom\sleadership\selections\sfor" +\
kelvin-onlab898a6c62015-01-16 14:13:53 -08002362 "\sthe\sElection\sapp."
Jon Halle3f39ff2015-01-13 11:50:53 -08002363 if re.search( successPattern, response ):
2364 main.log.info( self.name + " withdrawing from leadership " +
kelvin-onlab898a6c62015-01-16 14:13:53 -08002365 "elections for the Election app." )
Jon Hall94fd0472014-12-08 11:52:42 -08002366 return main.TRUE
kelvin-onlab898a6c62015-01-16 14:13:53 -08002367 # error
Jon Halle3f39ff2015-01-13 11:50:53 -08002368 errorPattern = "Command\snot\sfound"
2369 if re.search( errorPattern, response ):
2370 main.log.error( "Election app is not loaded on " + self.name )
Jon Hall669173b2014-12-17 11:36:30 -08002371 return main.FALSE
2372 else:
pingping-lin763ee042015-05-20 17:45:30 -07002373 main.log.error( "Error in electionTestWithdraw on " +
2374 self.name + ": " + "unexpected response" )
Jon Halle3f39ff2015-01-13 11:50:53 -08002375 main.log.error( repr( response ) )
Jon Hall669173b2014-12-17 11:36:30 -08002376 return main.FALSE
pingping-lin763ee042015-05-20 17:45:30 -07002377 except TypeError:
2378 main.log.exception( self.name + ": Object not as expected" )
2379 return main.FALSE
Jon Hall94fd0472014-12-08 11:52:42 -08002380 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08002381 main.log.error( self.name + ": EOF exception found" )
2382 main.log.error( self.name + ": " + self.handle.before )
Jon Hall94fd0472014-12-08 11:52:42 -08002383 main.cleanup()
2384 main.exit()
pingping-lin763ee042015-05-20 17:45:30 -07002385 except Exception:
2386 main.log.exception( self.name + ": Uncaught exception!" )
Jon Hall94fd0472014-12-08 11:52:42 -08002387 main.cleanup()
2388 main.exit()
Jon Hall1c9e8732014-10-27 19:29:27 -04002389
kelvin8ec71442015-01-15 16:57:00 -08002390 def getDevicePortsEnabledCount( self, dpid ):
2391 """
Hari Krishnaa43d4e92014-12-19 13:22:40 -08002392 Get the count of all enabled ports on a particular device/switch
kelvin8ec71442015-01-15 16:57:00 -08002393 """
Hari Krishnaa43d4e92014-12-19 13:22:40 -08002394 try:
Jon Halle3f39ff2015-01-13 11:50:53 -08002395 dpid = str( dpid )
kelvin-onlabd3b64892015-01-20 13:26:24 -08002396 cmdStr = "onos:ports -e " + dpid + " | wc -l"
2397 output = self.sendline( cmdStr )
Jon Halle3f39ff2015-01-13 11:50:53 -08002398 if re.search( "No such device", output ):
2399 main.log.error( "Error in getting ports" )
2400 return ( output, "Error" )
Hari Krishnaa43d4e92014-12-19 13:22:40 -08002401 else:
Jon Halle3f39ff2015-01-13 11:50:53 -08002402 return output
pingping-lin763ee042015-05-20 17:45:30 -07002403 except TypeError:
2404 main.log.exception( self.name + ": Object not as expected" )
2405 return ( output, "Error" )
Hari Krishnaa43d4e92014-12-19 13:22:40 -08002406 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08002407 main.log.error( self.name + ": EOF exception found" )
2408 main.log.error( self.name + ": " + self.handle.before )
Hari Krishnaa43d4e92014-12-19 13:22:40 -08002409 main.cleanup()
2410 main.exit()
pingping-lin763ee042015-05-20 17:45:30 -07002411 except Exception:
2412 main.log.exception( self.name + ": Uncaught exception!" )
Hari Krishnaa43d4e92014-12-19 13:22:40 -08002413 main.cleanup()
2414 main.exit()
2415
kelvin8ec71442015-01-15 16:57:00 -08002416 def getDeviceLinksActiveCount( self, dpid ):
2417 """
Hari Krishnaa43d4e92014-12-19 13:22:40 -08002418 Get the count of all enabled ports on a particular device/switch
kelvin8ec71442015-01-15 16:57:00 -08002419 """
Hari Krishnaa43d4e92014-12-19 13:22:40 -08002420 try:
kelvin-onlab898a6c62015-01-16 14:13:53 -08002421 dpid = str( dpid )
kelvin-onlabd3b64892015-01-20 13:26:24 -08002422 cmdStr = "onos:links " + dpid + " | grep ACTIVE | wc -l"
2423 output = self.sendline( cmdStr )
Jon Halle3f39ff2015-01-13 11:50:53 -08002424 if re.search( "No such device", output ):
kelvin-onlab898a6c62015-01-16 14:13:53 -08002425 main.log.error( "Error in getting ports " )
2426 return ( output, "Error " )
Hari Krishnaa43d4e92014-12-19 13:22:40 -08002427 else:
Jon Halle3f39ff2015-01-13 11:50:53 -08002428 return output
pingping-lin763ee042015-05-20 17:45:30 -07002429 except TypeError:
2430 main.log.exception( self.name + ": Object not as expected" )
2431 return ( output, "Error " )
Hari Krishnaa43d4e92014-12-19 13:22:40 -08002432 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08002433 main.log.error( self.name + ": EOF exception found" )
2434 main.log.error( self.name + ": " + self.handle.before )
Hari Krishnaa43d4e92014-12-19 13:22:40 -08002435 main.cleanup()
2436 main.exit()
pingping-lin763ee042015-05-20 17:45:30 -07002437 except Exception:
2438 main.log.exception( self.name + ": Uncaught exception!" )
Hari Krishnaa43d4e92014-12-19 13:22:40 -08002439 main.cleanup()
2440 main.exit()
2441
kelvin8ec71442015-01-15 16:57:00 -08002442 def getAllIntentIds( self ):
2443 """
Hari Krishnaa43d4e92014-12-19 13:22:40 -08002444 Return a list of all Intent IDs
kelvin8ec71442015-01-15 16:57:00 -08002445 """
Hari Krishnaa43d4e92014-12-19 13:22:40 -08002446 try:
kelvin-onlabd3b64892015-01-20 13:26:24 -08002447 cmdStr = "onos:intents | grep id="
2448 output = self.sendline( cmdStr )
Jon Halle3f39ff2015-01-13 11:50:53 -08002449 if re.search( "Error", output ):
2450 main.log.error( "Error in getting ports" )
2451 return ( output, "Error" )
Hari Krishnaa43d4e92014-12-19 13:22:40 -08002452 else:
Jon Halle3f39ff2015-01-13 11:50:53 -08002453 return output
pingping-lin763ee042015-05-20 17:45:30 -07002454 except TypeError:
2455 main.log.exception( self.name + ": Object not as expected" )
2456 return ( output, "Error" )
Hari Krishnaa43d4e92014-12-19 13:22:40 -08002457 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08002458 main.log.error( self.name + ": EOF exception found" )
2459 main.log.error( self.name + ": " + self.handle.before )
Hari Krishnaa43d4e92014-12-19 13:22:40 -08002460 main.cleanup()
2461 main.exit()
pingping-lin763ee042015-05-20 17:45:30 -07002462 except Exception:
2463 main.log.exception( self.name + ": Uncaught exception!" )
Hari Krishnaa43d4e92014-12-19 13:22:40 -08002464 main.cleanup()
2465 main.exit()
pingping-lin763ee042015-05-20 17:45:30 -07002466
2467 def intentSummary( self ):
2468 """
2469 Returns a dictionary containing the current intent states and the count
2470 """
2471 try:
2472 intents = self.intents( )
2473 states = []
2474 for intent in json.loads( intents ):
2475 states.append( intent.get( 'state', None ) )
2476 out = [ ( i, states.count( i ) ) for i in set( states ) ]
2477 main.log.info( dict( out ) )
2478 return dict( out )
2479 except TypeError:
2480 main.log.exception( self.name + ": Object not as expected" )
2481 return None
2482 except pexpect.EOF:
2483 main.log.error( self.name + ": EOF exception found" )
2484 main.log.error( self.name + ": " + self.handle.before )
2485 main.cleanup()
2486 main.exit()
2487 except Exception:
2488 main.log.exception( self.name + ": Uncaught exception!" )
2489 main.cleanup()
2490 main.exit()
2491
2492 def leaders( self, jsonFormat=True ):
2493 """
2494 Returns the output of the leaders command.
2495 Optional argument:
2496 * jsonFormat - boolean indicating if you want output in json
2497 """
2498 # FIXME: add json output
2499 # Sample JSON
2500 # {
2501 # "electedTime": "13m ago",
2502 # "epoch": 4,
2503 # "leader": "10.128.30.17",
2504 # "topic": "intent-partition-3"
2505 # },
2506 try:
2507 cmdStr = "onos:leaders"
2508 if jsonFormat:
2509 cmdStr += " -j"
2510 output = self.sendline( cmdStr )
2511 return output
2512 except TypeError:
2513 main.log.exception( self.name + ": Object not as expected" )
2514 return None
2515 except pexpect.EOF:
2516 main.log.error( self.name + ": EOF exception found" )
2517 main.log.error( self.name + ": " + self.handle.before )
2518 main.cleanup()
2519 main.exit()
2520 except Exception:
2521 main.log.exception( self.name + ": Uncaught exception!" )
2522 main.cleanup()
2523 main.exit()
2524
2525 def pendingMap( self, jsonFormat=True ):
2526 """
2527 Returns the output of the intent Pending map.
2528 """
2529 try:
2530 cmdStr = "onos:intents -p"
2531 if jsonFormat:
2532 cmdStr += " -j"
2533 output = self.sendline( cmdStr )
2534 return output
2535 except TypeError:
2536 main.log.exception( self.name + ": Object not as expected" )
2537 return None
2538 except pexpect.EOF:
2539 main.log.error( self.name + ": EOF exception found" )
2540 main.log.error( self.name + ": " + self.handle.before )
2541 main.cleanup()
2542 main.exit()
2543 except Exception:
2544 main.log.exception( self.name + ": Uncaught exception!" )
2545 main.cleanup()
2546 main.exit()
2547
2548 def partitions( self, jsonFormat=True ):
2549 """
2550 Returns the output of the raft partitions command for ONOS.
2551 """
2552 # Sample JSON
2553 # {
2554 # "leader": "tcp://10.128.30.11:7238",
2555 # "members": [
2556 # "tcp://10.128.30.11:7238",
2557 # "tcp://10.128.30.17:7238",
2558 # "tcp://10.128.30.13:7238",
2559 # ],
2560 # "name": "p1",
2561 # "term": 3
2562 # },
2563 try:
2564 cmdStr = "onos:partitions"
2565 if jsonFormat:
2566 cmdStr += " -j"
2567 output = self.sendline( cmdStr )
2568 return output
2569 except TypeError:
2570 main.log.exception( self.name + ": Object not as expected" )
2571 return None
2572 except pexpect.EOF:
2573 main.log.error( self.name + ": EOF exception found" )
2574 main.log.error( self.name + ": " + self.handle.before )
2575 main.cleanup()
2576 main.exit()
2577 except Exception:
2578 main.log.exception( self.name + ": Uncaught exception!" )
2579 main.cleanup()
2580 main.exit()
2581
2582 def apps( self, jsonFormat=True ):
2583 """
2584 Returns the output of the apps command for ONOS. This command lists
2585 information about installed ONOS applications
2586 """
2587 # Sample JSON object
2588 # [{"name":"org.onosproject.openflow","id":0,"version":"1.2.0",
2589 # "description":"ONOS OpenFlow protocol southbound providers",
2590 # "origin":"ON.Lab","permissions":"[]","featuresRepo":"",
2591 # "features":"[onos-openflow]","state":"ACTIVE"}]
2592 try:
2593 cmdStr = "onos:apps"
2594 if jsonFormat:
2595 cmdStr += " -j"
2596 output = self.sendline( cmdStr )
2597 assert "Error executing command" not in output
2598 return output
2599 # FIXME: look at specific exceptions/Errors
2600 except AssertionError:
2601 main.log.error( "Error in processing onos:app command: " +
2602 str( output ) )
2603 return None
2604 except TypeError:
2605 main.log.exception( self.name + ": Object not as expected" )
2606 return None
2607 except pexpect.EOF:
2608 main.log.error( self.name + ": EOF exception found" )
2609 main.log.error( self.name + ": " + self.handle.before )
2610 main.cleanup()
2611 main.exit()
2612 except Exception:
2613 main.log.exception( self.name + ": Uncaught exception!" )
2614 main.cleanup()
2615 main.exit()
2616
2617 def appStatus( self, appName ):
2618 """
2619 Uses the onos:apps cli command to return the status of an application.
2620 Returns:
2621 "ACTIVE" - If app is installed and activated
2622 "INSTALLED" - If app is installed and deactivated
2623 "UNINSTALLED" - If app is not installed
2624 None - on error
2625 """
2626 try:
2627 if not isinstance( appName, types.StringType ):
2628 main.log.error( self.name + ".appStatus(): appName must be" +
2629 " a string" )
2630 return None
2631 output = self.apps( jsonFormat=True )
2632 appsJson = json.loads( output )
2633 state = None
2634 for app in appsJson:
2635 if appName == app.get('name'):
2636 state = app.get('state')
2637 break
2638 if state == "ACTIVE" or state == "INSTALLED":
2639 return state
2640 elif state is None:
2641 return "UNINSTALLED"
2642 elif state:
2643 main.log.error( "Unexpected state from 'onos:apps': " +
2644 str( state ) )
2645 return state
2646 except TypeError:
2647 main.log.exception( self.name + ": Object not as expected" )
2648 return None
2649 except pexpect.EOF:
2650 main.log.error( self.name + ": EOF exception found" )
2651 main.log.error( self.name + ": " + self.handle.before )
2652 main.cleanup()
2653 main.exit()
2654 except Exception:
2655 main.log.exception( self.name + ": Uncaught exception!" )
2656 main.cleanup()
2657 main.exit()
2658
2659 def app( self, appName, option ):
2660 """
2661 Interacts with the app command for ONOS. This command manages
2662 application inventory.
2663 """
2664 try:
2665 # Validate argument types
2666 valid = True
2667 if not isinstance( appName, types.StringType ):
2668 main.log.error( self.name + ".app(): appName must be a " +
2669 "string" )
2670 valid = False
2671 if not isinstance( option, types.StringType ):
2672 main.log.error( self.name + ".app(): option must be a string" )
2673 valid = False
2674 if not valid:
2675 return main.FALSE
2676 # Validate Option
2677 option = option.lower()
2678 # NOTE: Install may become a valid option
2679 if option == "activate":
2680 pass
2681 elif option == "deactivate":
2682 pass
2683 elif option == "uninstall":
2684 pass
2685 else:
2686 # Invalid option
2687 main.log.error( "The ONOS app command argument only takes " +
2688 "the values: (activate|deactivate|uninstall)" +
2689 "; was given '" + option + "'")
2690 return main.FALSE
2691 cmdStr = "onos:app " + option + " " + appName
2692 output = self.sendline( cmdStr )
2693 if "Error executing command" in output:
2694 main.log.error( "Error in processing onos:app command: " +
2695 str( output ) )
2696 return main.FALSE
2697 elif "No such application" in output:
2698 main.log.error( "The application '" + appName +
2699 "' is not installed in ONOS" )
2700 return main.FALSE
2701 elif "Command not found:" in output:
2702 main.log.error( "Error in processing onos:app command: " +
2703 str( output ) )
2704 return main.FALSE
2705 elif "Unsupported command:" in output:
2706 main.log.error( "Incorrect command given to 'app': " +
2707 str( output ) )
2708 # NOTE: we may need to add more checks here
2709 # else: Command was successful
2710 # main.log.debug( "app response: " + repr( output ) )
2711 return main.TRUE
2712 except TypeError:
2713 main.log.exception( self.name + ": Object not as expected" )
2714 return main.ERROR
2715 except pexpect.EOF:
2716 main.log.error( self.name + ": EOF exception found" )
2717 main.log.error( self.name + ": " + self.handle.before )
2718 main.cleanup()
2719 main.exit()
2720 except Exception:
2721 main.log.exception( self.name + ": Uncaught exception!" )
2722 main.cleanup()
2723 main.exit()
2724
2725 def activateApp( self, appName, check=True ):
2726 """
2727 Activate an app that is already installed in ONOS
2728 appName is the hierarchical app name, not the feature name
2729 If check is True, method will check the status of the app after the
2730 command is issued
2731 Returns main.TRUE if the command was successfully sent
2732 main.FALSE if the cli responded with an error or given
2733 incorrect input
2734 """
2735 try:
2736 if not isinstance( appName, types.StringType ):
2737 main.log.error( self.name + ".activateApp(): appName must be" +
2738 " a string" )
2739 return main.FALSE
2740 status = self.appStatus( appName )
2741 if status == "INSTALLED":
2742 response = self.app( appName, "activate" )
2743 if check and response == main.TRUE:
2744 for i in range(10): # try 10 times then give up
2745 # TODO: Check with Thomas about this delay
2746 status = self.appStatus( appName )
2747 if status == "ACTIVE":
2748 return main.TRUE
2749 else:
2750 main.log.debug( "The state of application " +
2751 appName + " is " + status )
2752 time.sleep( 1 )
2753 return main.FALSE
2754 else: # not 'check' or command didn't succeed
2755 return response
2756 elif status == "ACTIVE":
2757 return main.TRUE
2758 elif status == "UNINSTALLED":
2759 main.log.error( self.name + ": Tried to activate the " +
2760 "application '" + appName + "' which is not " +
2761 "installed." )
2762 else:
2763 main.log.error( "Unexpected return value from appStatus: " +
2764 str( status ) )
2765 return main.ERROR
2766 except TypeError:
2767 main.log.exception( self.name + ": Object not as expected" )
2768 return main.ERROR
2769 except pexpect.EOF:
2770 main.log.error( self.name + ": EOF exception found" )
2771 main.log.error( self.name + ": " + self.handle.before )
2772 main.cleanup()
2773 main.exit()
2774 except Exception:
2775 main.log.exception( self.name + ": Uncaught exception!" )
2776 main.cleanup()
2777 main.exit()
2778
2779 def deactivateApp( self, appName, check=True ):
2780 """
2781 Deactivate an app that is already activated in ONOS
2782 appName is the hierarchical app name, not the feature name
2783 If check is True, method will check the status of the app after the
2784 command is issued
2785 Returns main.TRUE if the command was successfully sent
2786 main.FALSE if the cli responded with an error or given
2787 incorrect input
2788 """
2789 try:
2790 if not isinstance( appName, types.StringType ):
2791 main.log.error( self.name + ".deactivateApp(): appName must " +
2792 "be a string" )
2793 return main.FALSE
2794 status = self.appStatus( appName )
2795 if status == "INSTALLED":
2796 return main.TRUE
2797 elif status == "ACTIVE":
2798 response = self.app( appName, "deactivate" )
2799 if check and response == main.TRUE:
2800 for i in range(10): # try 10 times then give up
2801 status = self.appStatus( appName )
2802 if status == "INSTALLED":
2803 return main.TRUE
2804 else:
2805 time.sleep( 1 )
2806 return main.FALSE
2807 else: # not check or command didn't succeed
2808 return response
2809 elif status == "UNINSTALLED":
2810 main.log.warn( self.name + ": Tried to deactivate the " +
2811 "application '" + appName + "' which is not " +
2812 "installed." )
2813 return main.TRUE
2814 else:
2815 main.log.error( "Unexpected return value from appStatus: " +
2816 str( status ) )
2817 return main.ERROR
2818 except TypeError:
2819 main.log.exception( self.name + ": Object not as expected" )
2820 return main.ERROR
2821 except pexpect.EOF:
2822 main.log.error( self.name + ": EOF exception found" )
2823 main.log.error( self.name + ": " + self.handle.before )
2824 main.cleanup()
2825 main.exit()
2826 except Exception:
2827 main.log.exception( self.name + ": Uncaught exception!" )
2828 main.cleanup()
2829 main.exit()
2830
2831 def uninstallApp( self, appName, check=True ):
2832 """
2833 Uninstall an app that is already installed in ONOS
2834 appName is the hierarchical app name, not the feature name
2835 If check is True, method will check the status of the app after the
2836 command is issued
2837 Returns main.TRUE if the command was successfully sent
2838 main.FALSE if the cli responded with an error or given
2839 incorrect input
2840 """
2841 # TODO: check with Thomas about the state machine for apps
2842 try:
2843 if not isinstance( appName, types.StringType ):
2844 main.log.error( self.name + ".uninstallApp(): appName must " +
2845 "be a string" )
2846 return main.FALSE
2847 status = self.appStatus( appName )
2848 if status == "INSTALLED":
2849 response = self.app( appName, "uninstall" )
2850 if check and response == main.TRUE:
2851 for i in range(10): # try 10 times then give up
2852 status = self.appStatus( appName )
2853 if status == "UNINSTALLED":
2854 return main.TRUE
2855 else:
2856 time.sleep( 1 )
2857 return main.FALSE
2858 else: # not check or command didn't succeed
2859 return response
2860 elif status == "ACTIVE":
2861 main.log.warn( self.name + ": Tried to uninstall the " +
2862 "application '" + appName + "' which is " +
2863 "currently active." )
2864 response = self.app( appName, "uninstall" )
2865 if check and response == main.TRUE:
2866 for i in range(10): # try 10 times then give up
2867 status = self.appStatus( appName )
2868 if status == "UNINSTALLED":
2869 return main.TRUE
2870 else:
2871 time.sleep( 1 )
2872 return main.FALSE
2873 else: # not check or command didn't succeed
2874 return response
2875 elif status == "UNINSTALLED":
2876 return main.TRUE
2877 else:
2878 main.log.error( "Unexpected return value from appStatus: " +
2879 str( status ) )
2880 return main.ERROR
2881 except TypeError:
2882 main.log.exception( self.name + ": Object not as expected" )
2883 return main.ERROR
2884 except pexpect.EOF:
2885 main.log.error( self.name + ": EOF exception found" )
2886 main.log.error( self.name + ": " + self.handle.before )
2887 main.cleanup()
2888 main.exit()
2889 except Exception:
2890 main.log.exception( self.name + ": Uncaught exception!" )
2891 main.cleanup()
2892 main.exit()
2893
2894 def appIDs( self, jsonFormat=True ):
2895 """
2896 Show the mappings between app id and app names given by the 'app-ids'
2897 cli command
2898 """
2899 try:
2900 cmdStr = "app-ids"
2901 if jsonFormat:
2902 cmdStr += " -j"
2903 output = self.sendline( cmdStr )
2904 assert "Error executing command" not in output
2905 return output
2906 except AssertionError:
2907 main.log.error( "Error in processing onos:app-ids command: " +
2908 str( output ) )
2909 return None
2910 except TypeError:
2911 main.log.exception( self.name + ": Object not as expected" )
2912 return None
2913 except pexpect.EOF:
2914 main.log.error( self.name + ": EOF exception found" )
2915 main.log.error( self.name + ": " + self.handle.before )
2916 main.cleanup()
2917 main.exit()
2918 except Exception:
2919 main.log.exception( self.name + ": Uncaught exception!" )
2920 main.cleanup()
2921 main.exit()
2922
2923 def appToIDCheck( self ):
2924 """
2925 This method will check that each application's ID listed in 'apps' is
2926 the same as the ID listed in 'app-ids'. The check will also check that
2927 there are no duplicate IDs issued. Note that an app ID should be
2928 a globaly unique numerical identifier for app/app-like features. Once
2929 an ID is registered, the ID is never freed up so that if an app is
2930 reinstalled it will have the same ID.
2931
2932 Returns: main.TRUE if the check passes and
2933 main.FALSE if the check fails or
2934 main.ERROR if there is some error in processing the test
2935 """
2936 try:
2937 bail = False
2938 ids = self.appIDs( jsonFormat=True )
2939 if ids:
2940 ids = json.loads( ids )
2941 else:
2942 main.log.error( "app-ids returned nothing:" + repr( ids ) )
2943 bail = True
2944 apps = self.apps( jsonFormat=True )
2945 if apps:
2946 apps = json.loads( apps )
2947 else:
2948 main.log.error( "apps returned nothing:" + repr( apps ) )
2949 bail = True
2950 if bail:
2951 return main.FALSE
2952 result = main.TRUE
2953 for app in apps:
2954 appID = app.get( 'id' )
2955 if appID is None:
2956 main.log.error( "Error parsing app: " + str( app ) )
2957 result = main.FALSE
2958 appName = app.get( 'name' )
2959 if appName is None:
2960 main.log.error( "Error parsing app: " + str( app ) )
2961 result = main.FALSE
2962 # get the entry in ids that has the same appID
2963 current = filter( lambda item: item[ 'id' ] == appID, ids )
2964 # main.log.debug( "Comparing " + str( app ) + " to " +
2965 # str( current ) )
2966 if not current: # if ids doesn't have this id
2967 result = main.FALSE
2968 main.log.error( "'app-ids' does not have the ID for " +
2969 str( appName ) + " that apps does." )
2970 elif len( current ) > 1:
2971 # there is more than one app with this ID
2972 result = main.FALSE
2973 # We will log this later in the method
2974 elif not current[0][ 'name' ] == appName:
2975 currentName = current[0][ 'name' ]
2976 result = main.FALSE
2977 main.log.error( "'app-ids' has " + str( currentName ) +
2978 " registered under id:" + str( appID ) +
2979 " but 'apps' has " + str( appName ) )
2980 else:
2981 pass # id and name match!
2982 # now make sure that app-ids has no duplicates
2983 idsList = []
2984 namesList = []
2985 for item in ids:
2986 idsList.append( item[ 'id' ] )
2987 namesList.append( item[ 'name' ] )
2988 if len( idsList ) != len( set( idsList ) ) or\
2989 len( namesList ) != len( set( namesList ) ):
2990 main.log.error( "'app-ids' has some duplicate entries: \n"
2991 + json.dumps( ids,
2992 sort_keys=True,
2993 indent=4,
2994 separators=( ',', ': ' ) ) )
2995 result = main.FALSE
2996 return result
2997 except ( ValueError, TypeError ):
2998 main.log.exception( self.name + ": Object not as expected" )
2999 return main.ERROR
3000 except pexpect.EOF:
3001 main.log.error( self.name + ": EOF exception found" )
3002 main.log.error( self.name + ": " + self.handle.before )
3003 main.cleanup()
3004 main.exit()
3005 except Exception:
3006 main.log.exception( self.name + ": Uncaught exception!" )
3007 main.cleanup()
3008 main.exit()
3009
3010 def getCfg( self, component=None, propName=None, short=False,
3011 jsonFormat=True ):
3012 """
3013 Get configuration settings from onos cli
3014 Optional arguments:
3015 component - Optionally only list configurations for a specific
3016 component. If None, all components with configurations
3017 are displayed. Case Sensitive string.
3018 propName - If component is specified, propName option will show
3019 only this specific configuration from that component.
3020 Case Sensitive string.
3021 jsonFormat - Returns output as json. Note that this will override
3022 the short option
3023 short - Short, less verbose, version of configurations.
3024 This is overridden by the json option
3025 returns:
3026 Output from cli as a string or None on error
3027 """
3028 try:
3029 baseStr = "cfg"
3030 cmdStr = " get"
3031 componentStr = ""
3032 if component:
3033 componentStr += " " + component
3034 if propName:
3035 componentStr += " " + propName
3036 if jsonFormat:
3037 baseStr += " -j"
3038 elif short:
3039 baseStr += " -s"
3040 output = self.sendline( baseStr + cmdStr + componentStr )
3041 assert "Error executing command" not in output
3042 return output
3043 except AssertionError:
3044 main.log.error( "Error in processing 'cfg get' command: " +
3045 str( output ) )
3046 return None
3047 except TypeError:
3048 main.log.exception( self.name + ": Object not as expected" )
3049 return None
3050 except pexpect.EOF:
3051 main.log.error( self.name + ": EOF exception found" )
3052 main.log.error( self.name + ": " + self.handle.before )
3053 main.cleanup()
3054 main.exit()
3055 except Exception:
3056 main.log.exception( self.name + ": Uncaught exception!" )
3057 main.cleanup()
3058 main.exit()
3059
3060 def setCfg( self, component, propName, value=None, check=True ):
3061 """
3062 Set/Unset configuration settings from ONOS cli
3063 Required arguments:
3064 component - The case sensitive name of the component whose
3065 property is to be set
3066 propName - The case sensitive name of the property to be set/unset
3067 Optional arguments:
3068 value - The value to set the property to. If None, will unset the
3069 property and revert it to it's default value(if applicable)
3070 check - Boolean, Check whether the option was successfully set this
3071 only applies when a value is given.
3072 returns:
3073 main.TRUE on success or main.FALSE on failure. If check is False,
3074 will return main.TRUE unless there is an error
3075 """
3076 try:
3077 baseStr = "cfg"
3078 cmdStr = " set " + str( component ) + " " + str( propName )
3079 if value is not None:
3080 cmdStr += " " + str( value )
3081 output = self.sendline( baseStr + cmdStr )
3082 assert "Error executing command" not in output
3083 if value and check:
3084 results = self.getCfg( component=str( component ),
3085 propName=str( propName ),
3086 jsonFormat=True )
3087 # Check if current value is what we just set
3088 try:
3089 jsonOutput = json.loads( results )
3090 current = jsonOutput[ 'value' ]
3091 except ( ValueError, TypeError ):
3092 main.log.exception( "Error parsing cfg output" )
3093 main.log.error( "output:" + repr( results ) )
3094 return main.FALSE
3095 if current == str( value ):
3096 return main.TRUE
3097 return main.FALSE
3098 return main.TRUE
3099 except AssertionError:
3100 main.log.error( "Error in processing 'cfg set' command: " +
3101 str( output ) )
3102 return main.FALSE
3103 except TypeError:
3104 main.log.exception( self.name + ": Object not as expected" )
3105 return main.FALSE
3106 except pexpect.EOF:
3107 main.log.error( self.name + ": EOF exception found" )
3108 main.log.error( self.name + ": " + self.handle.before )
3109 main.cleanup()
3110 main.exit()
3111 except Exception:
3112 main.log.exception( self.name + ": Uncaught exception!" )
3113 main.cleanup()
3114 main.exit()
3115
3116 def setTestAdd( self, setName, values ):
3117 """
3118 CLI command to add elements to a distributed set.
3119 Arguments:
3120 setName - The name of the set to add to.
3121 values - The value(s) to add to the set, space seperated.
3122 Example usages:
3123 setTestAdd( "set1", "a b c" )
3124 setTestAdd( "set2", "1" )
3125 returns:
3126 main.TRUE on success OR
3127 main.FALSE if elements were already in the set OR
3128 main.ERROR on error
3129 """
3130 try:
3131 cmdStr = "set-test-add " + str( setName ) + " " + str( values )
3132 output = self.sendline( cmdStr )
3133 try:
3134 # TODO: Maybe make this less hardcoded
3135 # ConsistentMap Exceptions
3136 assert "org.onosproject.store.service" not in output
3137 # Node not leader
3138 assert "java.lang.IllegalStateException" not in output
3139 except AssertionError:
3140 main.log.error( "Error in processing 'set-test-add' " +
3141 "command: " + str( output ) )
3142 retryTime = 30 # Conservative time, given by Madan
3143 main.log.info( "Waiting " + str( retryTime ) +
3144 "seconds before retrying." )
3145 time.sleep( retryTime ) # Due to change in mastership
3146 output = self.sendline( cmdStr )
3147 assert "Error executing command" not in output
3148 positiveMatch = "\[(.*)\] was added to the set " + str( setName )
3149 negativeMatch = "\[(.*)\] was already in set " + str( setName )
3150 main.log.info( self.name + ": " + output )
3151 if re.search( positiveMatch, output):
3152 return main.TRUE
3153 elif re.search( negativeMatch, output):
3154 return main.FALSE
3155 else:
3156 main.log.error( self.name + ": setTestAdd did not" +
3157 " match expected output" )
3158 main.log.debug( self.name + " expected: " + pattern )
3159 main.log.debug( self.name + " actual: " + repr( output ) )
3160 return main.ERROR
3161 except AssertionError:
3162 main.log.error( "Error in processing 'set-test-add' command: " +
3163 str( output ) )
3164 return main.ERROR
3165 except TypeError:
3166 main.log.exception( self.name + ": Object not as expected" )
3167 return main.ERROR
3168 except pexpect.EOF:
3169 main.log.error( self.name + ": EOF exception found" )
3170 main.log.error( self.name + ": " + self.handle.before )
3171 main.cleanup()
3172 main.exit()
3173 except Exception:
3174 main.log.exception( self.name + ": Uncaught exception!" )
3175 main.cleanup()
3176 main.exit()
3177
3178 def setTestRemove( self, setName, values, clear=False, retain=False ):
3179 """
3180 CLI command to remove elements from a distributed set.
3181 Required arguments:
3182 setName - The name of the set to remove from.
3183 values - The value(s) to remove from the set, space seperated.
3184 Optional arguments:
3185 clear - Clear all elements from the set
3186 retain - Retain only the given values. (intersection of the
3187 original set and the given set)
3188 returns:
3189 main.TRUE on success OR
3190 main.FALSE if the set was not changed OR
3191 main.ERROR on error
3192 """
3193 try:
3194 cmdStr = "set-test-remove "
3195 if clear:
3196 cmdStr += "-c " + str( setName )
3197 elif retain:
3198 cmdStr += "-r " + str( setName ) + " " + str( values )
3199 else:
3200 cmdStr += str( setName ) + " " + str( values )
3201 output = self.sendline( cmdStr )
3202 try:
3203 # TODO: Maybe make this less hardcoded
3204 # ConsistentMap Exceptions
3205 assert "org.onosproject.store.service" not in output
3206 # Node not leader
3207 assert "java.lang.IllegalStateException" not in output
3208 except AssertionError:
3209 main.log.error( "Error in processing 'set-test-add' " +
3210 "command: " + str( output ) )
3211 retryTime = 30 # Conservative time, given by Madan
3212 main.log.info( "Waiting " + str( retryTime ) +
3213 "seconds before retrying." )
3214 time.sleep( retryTime ) # Due to change in mastership
3215 output = self.sendline( cmdStr )
3216 assert "Error executing command" not in output
3217 main.log.info( self.name + ": " + output )
3218 if clear:
3219 pattern = "Set " + str( setName ) + " cleared"
3220 if re.search( pattern, output ):
3221 return main.TRUE
3222 elif retain:
3223 positivePattern = str( setName ) + " was pruned to contain " +\
3224 "only elements of set \[(.*)\]"
3225 negativePattern = str( setName ) + " was not changed by " +\
3226 "retaining only elements of the set " +\
3227 "\[(.*)\]"
3228 if re.search( positivePattern, output ):
3229 return main.TRUE
3230 elif re.search( negativePattern, output ):
3231 return main.FALSE
3232 else:
3233 positivePattern = "\[(.*)\] was removed from the set " +\
3234 str( setName )
3235 if ( len( values.split() ) == 1 ):
3236 negativePattern = "\[(.*)\] was not in set " +\
3237 str( setName )
3238 else:
3239 negativePattern = "No element of \[(.*)\] was in set " +\
3240 str( setName )
3241 if re.search( positivePattern, output ):
3242 return main.TRUE
3243 elif re.search( negativePattern, output ):
3244 return main.FALSE
3245 main.log.error( self.name + ": setTestRemove did not" +
3246 " match expected output" )
3247 main.log.debug( self.name + " expected: " + pattern )
3248 main.log.debug( self.name + " actual: " + repr( output ) )
3249 return main.ERROR
3250 except AssertionError:
3251 main.log.error( "Error in processing 'set-test-remove' command: " +
3252 str( output ) )
3253 return main.ERROR
3254 except TypeError:
3255 main.log.exception( self.name + ": Object not as expected" )
3256 return main.ERROR
3257 except pexpect.EOF:
3258 main.log.error( self.name + ": EOF exception found" )
3259 main.log.error( self.name + ": " + self.handle.before )
3260 main.cleanup()
3261 main.exit()
3262 except Exception:
3263 main.log.exception( self.name + ": Uncaught exception!" )
3264 main.cleanup()
3265 main.exit()
3266
3267 def setTestGet( self, setName, values="" ):
3268 """
3269 CLI command to get the elements in a distributed set.
3270 Required arguments:
3271 setName - The name of the set to remove from.
3272 Optional arguments:
3273 values - The value(s) to check if in the set, space seperated.
3274 returns:
3275 main.ERROR on error OR
3276 A list of elements in the set if no optional arguments are
3277 supplied OR
3278 A tuple containing the list then:
3279 main.FALSE if the given values are not in the set OR
3280 main.TRUE if the given values are in the set OR
3281 """
3282 try:
3283 values = str( values ).strip()
3284 setName = str( setName ).strip()
3285 length = len( values.split() )
3286 containsCheck = None
3287 # Patterns to match
3288 setPattern = "\[(.*)\]"
3289 pattern = "Items in set " + setName + ":\n" + setPattern
3290 containsTrue = "Set " + setName + " contains the value " + values
3291 containsFalse = "Set " + setName + " did not contain the value " +\
3292 values
3293 containsAllTrue = "Set " + setName + " contains the the subset " +\
3294 setPattern
3295 containsAllFalse = "Set " + setName + " did not contain the the" +\
3296 " subset " + setPattern
3297
3298 cmdStr = "set-test-get "
3299 cmdStr += setName + " " + values
3300 output = self.sendline( cmdStr )
3301 try:
3302 # TODO: Maybe make this less hardcoded
3303 # ConsistentMap Exceptions
3304 assert "org.onosproject.store.service" not in output
3305 # Node not leader
3306 assert "java.lang.IllegalStateException" not in output
3307 except AssertionError:
3308 main.log.error( "Error in processing 'set-test-add' " +
3309 "command: " + str( output ) )
3310 retryTime = 30 # Conservative time, given by Madan
3311 main.log.info( "Waiting " + str( retryTime ) +
3312 "seconds before retrying." )
3313 time.sleep( retryTime ) # Due to change in mastership
3314 output = self.sendline( cmdStr )
3315 assert "Error executing command" not in output
3316 main.log.info( self.name + ": " + output )
3317
3318 if length == 0:
3319 match = re.search( pattern, output )
3320 else: # if given values
3321 if length == 1: # Contains output
3322 patternTrue = pattern + "\n" + containsTrue
3323 patternFalse = pattern + "\n" + containsFalse
3324 else: # ContainsAll output
3325 patternTrue = pattern + "\n" + containsAllTrue
3326 patternFalse = pattern + "\n" + containsAllFalse
3327 matchTrue = re.search( patternTrue, output )
3328 matchFalse = re.search( patternFalse, output )
3329 if matchTrue:
3330 containsCheck = main.TRUE
3331 match = matchTrue
3332 elif matchFalse:
3333 containsCheck = main.FALSE
3334 match = matchFalse
3335 else:
3336 main.log.error( self.name + " setTestGet did not match " +\
3337 "expected output" )
3338 main.log.debug( self.name + " expected: " + pattern )
3339 main.log.debug( self.name + " actual: " + repr( output ) )
3340 match = None
3341 if match:
3342 setMatch = match.group( 1 )
3343 if setMatch == '':
3344 setList = []
3345 else:
3346 setList = setMatch.split( ", " )
3347 if length > 0:
3348 return ( setList, containsCheck )
3349 else:
3350 return setList
3351 else: # no match
3352 main.log.error( self.name + ": setTestGet did not" +
3353 " match expected output" )
3354 main.log.debug( self.name + " expected: " + pattern )
3355 main.log.debug( self.name + " actual: " + repr( output ) )
3356 return main.ERROR
3357 except AssertionError:
3358 main.log.error( "Error in processing 'set-test-get' command: " +
3359 str( output ) )
3360 return main.ERROR
3361 except TypeError:
3362 main.log.exception( self.name + ": Object not as expected" )
3363 return main.ERROR
3364 except pexpect.EOF:
3365 main.log.error( self.name + ": EOF exception found" )
3366 main.log.error( self.name + ": " + self.handle.before )
3367 main.cleanup()
3368 main.exit()
3369 except Exception:
3370 main.log.exception( self.name + ": Uncaught exception!" )
3371 main.cleanup()
3372 main.exit()
3373
3374 def setTestSize( self, setName ):
3375 """
3376 CLI command to get the elements in a distributed set.
3377 Required arguments:
3378 setName - The name of the set to remove from.
3379 returns:
3380 The integer value of the size returned or
3381 None on error
3382 """
3383 try:
3384 # TODO: Should this check against the number of elements returned
3385 # and then return true/false based on that?
3386 setName = str( setName ).strip()
3387 # Patterns to match
3388 setPattern = "\[(.*)\]"
3389 pattern = "There are (\d+) items in set " + setName + ":\n" +\
3390 setPattern
3391 cmdStr = "set-test-get -s "
3392 cmdStr += setName
3393 output = self.sendline( cmdStr )
3394 try:
3395 # TODO: Maybe make this less hardcoded
3396 # ConsistentMap Exceptions
3397 assert "org.onosproject.store.service" not in output
3398 # Node not leader
3399 assert "java.lang.IllegalStateException" not in output
3400 except AssertionError:
3401 main.log.error( "Error in processing 'set-test-add' " +
3402 "command: " + str( output ) )
3403 retryTime = 30 # Conservative time, given by Madan
3404 main.log.info( "Waiting " + str( retryTime ) +
3405 "seconds before retrying." )
3406 time.sleep( retryTime ) # Due to change in mastership
3407 output = self.sendline( cmdStr )
3408 assert "Error executing command" not in output
3409 main.log.info( self.name + ": " + output )
3410 match = re.search( pattern, output )
3411 if match:
3412 setSize = int( match.group( 1 ) )
3413 setMatch = match.group( 2 )
3414 if len( setMatch.split() ) == setSize:
3415 main.log.info( "The size returned by " + self.name +
3416 " matches the number of elements in " +
3417 "the returned set" )
3418 else:
3419 main.log.error( "The size returned by " + self.name +
3420 " does not match the number of " +
3421 "elements in the returned set." )
3422 return setSize
3423 else: # no match
3424 main.log.error( self.name + ": setTestGet did not" +
3425 " match expected output" )
3426 main.log.debug( self.name + " expected: " + pattern )
3427 main.log.debug( self.name + " actual: " + repr( output ) )
3428 return None
3429 except AssertionError:
3430 main.log.error( "Error in processing 'set-test-get' command: " +
3431 str( output ) )
3432 return None
3433 except TypeError:
3434 main.log.exception( self.name + ": Object not as expected" )
3435 return None
3436 except pexpect.EOF:
3437 main.log.error( self.name + ": EOF exception found" )
3438 main.log.error( self.name + ": " + self.handle.before )
3439 main.cleanup()
3440 main.exit()
3441 except Exception:
3442 main.log.exception( self.name + ": Uncaught exception!" )
3443 main.cleanup()
3444 main.exit()
3445
3446 def counters( self ):
3447 """
3448 Command to list the various counters in the system.
3449 returns:
3450 A dict containing the counters in the system with the counter
3451 names being the keys and the value of the counters being the
3452 values OR
3453 None on error
3454 """
3455 #FIXME: JSON FORMAT
3456 try:
3457 counters = {}
3458 cmdStr = "counters"
3459 output = self.sendline( cmdStr )
3460 assert "Error executing command" not in output
3461 main.log.info( self.name + ": " + output )
3462 for line in output.splitlines():
3463 match = re.search( "name=(\S+) value=(\d+)", line )
3464 if match:
3465 key = match.group( 1 )
3466 value = int( match.group( 2 ) )
3467 counters[key] = value
3468 else:
3469 main.log.error( self.name + ": counters did not match " +
3470 "expected output" )
3471 main.log.debug( self.name + " expected: " + pattern )
3472 main.log.debug( self.name + " actual: " + repr( output ) )
3473 return None
3474 return counters
3475 except AssertionError:
3476 main.log.error( "Error in processing 'counters' command: " +
3477 str( output ) )
3478 return main.ERROR
3479 except TypeError:
3480 main.log.exception( self.name + ": Object not as expected" )
3481 return main.ERROR
3482 except pexpect.EOF:
3483 main.log.error( self.name + ": EOF exception found" )
3484 main.log.error( self.name + ": " + self.handle.before )
3485 main.cleanup()
3486 main.exit()
3487 except Exception:
3488 main.log.exception( self.name + ": Uncaught exception!" )
3489 main.cleanup()
3490 main.exit()
3491
3492 def counterTestIncrement( self, counter, inMemory=False ):
3493 """
3494 CLI command to increment and get a distributed counter.
3495 Required arguments:
3496 counter - The name of the counter to increment.
3497 Optional arguments:
3498 inMemory - use in memory map for the counter
3499 returns:
3500 integer value of the counter or
3501 None on Error
3502 """
3503 try:
3504 counter = str( counter )
3505 cmdStr = "counter-test-increment "
3506 if inMemory:
3507 cmdStr += "-i "
3508 cmdStr += counter
3509 output = self.sendline( cmdStr )
3510 try:
3511 # TODO: Maybe make this less hardcoded
3512 # ConsistentMap Exceptions
3513 assert "org.onosproject.store.service" not in output
3514 # Node not leader
3515 assert "java.lang.IllegalStateException" not in output
3516 except AssertionError:
3517 main.log.error( "Error in processing 'set-test-add' " +
3518 "command: " + str( output ) )
3519 retryTime = 30 # Conservative time, given by Madan
3520 main.log.info( "Waiting " + str( retryTime ) +
3521 "seconds before retrying." )
3522 time.sleep( retryTime ) # Due to change in mastership
3523 output = self.sendline( cmdStr )
3524 assert "Error executing command" not in output
3525 main.log.info( self.name + ": " + output )
3526 pattern = counter + " was incremented to (\d+)"
3527 match = re.search( pattern, output )
3528 if match:
3529 return int( match.group( 1 ) )
3530 else:
3531 main.log.error( self.name + ": counterTestIncrement did not" +
3532 " match expected output." )
3533 main.log.debug( self.name + " expected: " + pattern )
3534 main.log.debug( self.name + " actual: " + repr( output ) )
3535 return None
3536 except AssertionError:
3537 main.log.error( "Error in processing 'counter-test-increment'" +
3538 " command: " + str( output ) )
3539 return None
3540 except TypeError:
3541 main.log.exception( self.name + ": Object not as expected" )
3542 return None
3543 except pexpect.EOF:
3544 main.log.error( self.name + ": EOF exception found" )
3545 main.log.error( self.name + ": " + self.handle.before )
3546 main.cleanup()
3547 main.exit()
3548 except Exception:
3549 main.log.exception( self.name + ": Uncaught exception!" )
3550 main.cleanup()
3551 main.exit()
3552