blob: 08f8a5b6b9547191be06687970e608a69a5ab205 [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
Jeremy Songsterae01bba2016-07-11 15:39:17 -070017Modified 2016 by ON.Lab
18
19Please refer questions to either the onos test mailing list at <onos-test@onosproject.org>,
20the System Testing Plans and Results wiki page at <https://wiki.onosproject.org/x/voMg>,
21or the System Testing Guide page at <https://wiki.onosproject.org/x/WYQg>
andrewonlab95ce8322014-10-13 14:12:04 -040022
kelvin8ec71442015-01-15 16:57:00 -080023"""
andrewonlab95ce8322014-10-13 14:12:04 -040024import pexpect
25import re
Jon Hall30b82fa2015-03-04 17:15:43 -080026import json
27import types
Jon Hallbd16b922015-03-26 17:53:15 -070028import time
kelvin-onlaba4074292015-07-09 15:19:49 -070029import os
andrewonlab95ce8322014-10-13 14:12:04 -040030from drivers.common.clidriver import CLI
You Wangdb8cd0a2016-05-26 15:19:45 -070031from core.graph import Graph
andrewonlab95ce8322014-10-13 14:12:04 -040032
andrewonlab95ce8322014-10-13 14:12:04 -040033
kelvin8ec71442015-01-15 16:57:00 -080034class OnosCliDriver( CLI ):
andrewonlab95ce8322014-10-13 14:12:04 -040035
kelvin8ec71442015-01-15 16:57:00 -080036 def __init__( self ):
37 """
38 Initialize client
39 """
Jon Hallefbd9792015-03-05 16:11:36 -080040 self.name = None
41 self.home = None
42 self.handle = None
You Wangdb8cd0a2016-05-26 15:19:45 -070043 self.graph = Graph()
kelvin8ec71442015-01-15 16:57:00 -080044 super( CLI, self ).__init__()
45
46 def connect( self, **connectargs ):
47 """
andrewonlab95ce8322014-10-13 14:12:04 -040048 Creates ssh handle for ONOS cli.
kelvin8ec71442015-01-15 16:57:00 -080049 """
andrewonlab95ce8322014-10-13 14:12:04 -040050 try:
51 for key in connectargs:
kelvin8ec71442015-01-15 16:57:00 -080052 vars( self )[ key ] = connectargs[ key ]
andrew@onlab.us658ec012015-03-11 15:13:09 -070053 self.home = "~/onos"
andrewonlab95ce8322014-10-13 14:12:04 -040054 for key in self.options:
55 if key == "home":
kelvin8ec71442015-01-15 16:57:00 -080056 self.home = self.options[ 'home' ]
andrewonlab95ce8322014-10-13 14:12:04 -040057 break
kelvin-onlabfb521662015-02-27 09:52:40 -080058 if self.home is None or self.home == "":
Jon Halle94919c2015-03-23 11:42:57 -070059 self.home = "~/onos"
andrewonlab95ce8322014-10-13 14:12:04 -040060
kelvin-onlaba4074292015-07-09 15:19:49 -070061 for key in self.options:
62 if key == 'onosIp':
63 self.onosIp = self.options[ 'onosIp' ]
64 break
65
kelvin8ec71442015-01-15 16:57:00 -080066 self.name = self.options[ 'name' ]
kelvin-onlaba4074292015-07-09 15:19:49 -070067
68 try:
Jon Hallc6793552016-01-19 14:18:37 -080069 if os.getenv( str( self.ip_address ) ) is not None:
kelvin-onlaba4074292015-07-09 15:19:49 -070070 self.ip_address = os.getenv( str( self.ip_address ) )
71 else:
72 main.log.info( self.name +
73 ": Trying to connect to " +
74 self.ip_address )
75
76 except KeyError:
77 main.log.info( "Invalid host name," +
78 " connecting to local host instead" )
79 self.ip_address = 'localhost'
80 except Exception as inst:
81 main.log.error( "Uncaught exception: " + str( inst ) )
82
kelvin8ec71442015-01-15 16:57:00 -080083 self.handle = super( OnosCliDriver, self ).connect(
kelvin-onlab08679eb2015-01-21 16:11:48 -080084 user_name=self.user_name,
85 ip_address=self.ip_address,
kelvin-onlab898a6c62015-01-16 14:13:53 -080086 port=self.port,
87 pwd=self.pwd,
88 home=self.home )
andrewonlab95ce8322014-10-13 14:12:04 -040089
kelvin8ec71442015-01-15 16:57:00 -080090 self.handle.sendline( "cd " + self.home )
91 self.handle.expect( "\$" )
andrewonlab95ce8322014-10-13 14:12:04 -040092 if self.handle:
93 return self.handle
kelvin8ec71442015-01-15 16:57:00 -080094 else:
95 main.log.info( "NO ONOS HANDLE" )
andrewonlab95ce8322014-10-13 14:12:04 -040096 return main.FALSE
Jon Halld4d4b372015-01-28 16:02:41 -080097 except TypeError:
98 main.log.exception( self.name + ": Object not as expected" )
99 return None
andrewonlab95ce8322014-10-13 14:12:04 -0400100 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -0800101 main.log.error( self.name + ": EOF exception found" )
102 main.log.error( self.name + ": " + self.handle.before )
andrewonlab95ce8322014-10-13 14:12:04 -0400103 main.cleanup()
104 main.exit()
Jon Hallfebb1c72015-03-05 13:30:09 -0800105 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -0800106 main.log.exception( self.name + ": Uncaught exception!" )
andrewonlab95ce8322014-10-13 14:12:04 -0400107 main.cleanup()
108 main.exit()
109
kelvin8ec71442015-01-15 16:57:00 -0800110 def disconnect( self ):
111 """
andrewonlab95ce8322014-10-13 14:12:04 -0400112 Called when Test is complete to disconnect the ONOS handle.
kelvin8ec71442015-01-15 16:57:00 -0800113 """
Jon Halld61331b2015-02-17 16:35:47 -0800114 response = main.TRUE
andrewonlab95ce8322014-10-13 14:12:04 -0400115 try:
Jon Hall61282e32015-03-19 11:34:11 -0700116 if self.handle:
117 i = self.logout()
118 if i == main.TRUE:
119 self.handle.sendline( "" )
120 self.handle.expect( "\$" )
121 self.handle.sendline( "exit" )
122 self.handle.expect( "closed" )
Jon Halld4d4b372015-01-28 16:02:41 -0800123 except TypeError:
124 main.log.exception( self.name + ": Object not as expected" )
Jon Halld61331b2015-02-17 16:35:47 -0800125 response = main.FALSE
andrewonlab95ce8322014-10-13 14:12:04 -0400126 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -0800127 main.log.error( self.name + ": EOF exception found" )
128 main.log.error( self.name + ": " + self.handle.before )
Jon Hall61282e32015-03-19 11:34:11 -0700129 except ValueError:
Jon Hall1a77a1e2015-04-06 10:41:13 -0700130 main.log.exception( "Exception in disconnect of " + self.name )
Jon Hall61282e32015-03-19 11:34:11 -0700131 response = main.TRUE
Jon Hallfebb1c72015-03-05 13:30:09 -0800132 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -0800133 main.log.exception( self.name + ": Connection failed to the host" )
andrewonlab95ce8322014-10-13 14:12:04 -0400134 response = main.FALSE
135 return response
136
kelvin8ec71442015-01-15 16:57:00 -0800137 def logout( self ):
138 """
andrewonlab38d2b4a2014-11-13 16:28:47 -0500139 Sends 'logout' command to ONOS cli
Jon Hall61282e32015-03-19 11:34:11 -0700140 Returns main.TRUE if exited CLI and
141 main.FALSE on timeout (not guranteed you are disconnected)
142 None on TypeError
143 Exits test on unknown error or pexpect exits unexpectedly
kelvin8ec71442015-01-15 16:57:00 -0800144 """
andrewonlab38d2b4a2014-11-13 16:28:47 -0500145 try:
Jon Hall61282e32015-03-19 11:34:11 -0700146 if self.handle:
147 self.handle.sendline( "" )
148 i = self.handle.expect( [ "onos>", "\$", pexpect.TIMEOUT ],
149 timeout=10 )
150 if i == 0: # In ONOS CLI
151 self.handle.sendline( "logout" )
Jon Hallbfe00002016-04-05 10:23:54 -0700152 j = self.handle.expect( [ "\$",
153 "Command not found:",
154 pexpect.TIMEOUT ] )
155 if j == 0: # Successfully logged out
156 return main.TRUE
157 elif j == 1 or j == 2:
158 # ONOS didn't fully load, and logout command isn't working
159 # or the command timed out
160 self.handle.send( "\x04" ) # send ctrl-d
Jon Hall64ab3bd2016-05-13 11:29:44 -0700161 try:
162 self.handle.expect( "\$" )
163 except pexpect.TIMEOUT:
164 main.log.error( "ONOS did not respond to 'logout' or CTRL-d" )
Jon Hallbfe00002016-04-05 10:23:54 -0700165 return main.TRUE
166 else: # some other output
167 main.log.warn( "Unknown repsonse to logout command: '{}'",
168 repr( self.handle.before ) )
169 return main.FALSE
Jon Hall61282e32015-03-19 11:34:11 -0700170 elif i == 1: # not in CLI
171 return main.TRUE
172 elif i == 3: # Timeout
173 return main.FALSE
174 else:
andrewonlab9627f432014-11-14 12:45:10 -0500175 return main.TRUE
Jon Halld4d4b372015-01-28 16:02:41 -0800176 except TypeError:
177 main.log.exception( self.name + ": Object not as expected" )
178 return None
andrewonlab38d2b4a2014-11-13 16:28:47 -0500179 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -0800180 main.log.error( self.name + ": eof exception found" )
Jon Hall61282e32015-03-19 11:34:11 -0700181 main.log.error( self.name + ": " + self.handle.before )
andrewonlab38d2b4a2014-11-13 16:28:47 -0500182 main.cleanup()
183 main.exit()
Jon Hall61282e32015-03-19 11:34:11 -0700184 except ValueError:
Jon Hall5aa168b2015-03-23 14:23:09 -0700185 main.log.error( self.name +
186 "ValueError exception in logout method" )
Jon Hallfebb1c72015-03-05 13:30:09 -0800187 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -0800188 main.log.exception( self.name + ": Uncaught exception!" )
andrewonlab38d2b4a2014-11-13 16:28:47 -0500189 main.cleanup()
190 main.exit()
191
kelvin-onlabd3b64892015-01-20 13:26:24 -0800192 def setCell( self, cellname ):
kelvin8ec71442015-01-15 16:57:00 -0800193 """
andrewonlab95ce8322014-10-13 14:12:04 -0400194 Calls 'cell <name>' to set the environment variables on ONOSbench
kelvin8ec71442015-01-15 16:57:00 -0800195
andrewonlab95ce8322014-10-13 14:12:04 -0400196 Before issuing any cli commands, set the environment variable first.
kelvin8ec71442015-01-15 16:57:00 -0800197 """
andrewonlab95ce8322014-10-13 14:12:04 -0400198 try:
199 if not cellname:
kelvin8ec71442015-01-15 16:57:00 -0800200 main.log.error( "Must define cellname" )
andrewonlab95ce8322014-10-13 14:12:04 -0400201 main.cleanup()
202 main.exit()
203 else:
kelvin8ec71442015-01-15 16:57:00 -0800204 self.handle.sendline( "cell " + str( cellname ) )
kelvin-onlabd3b64892015-01-20 13:26:24 -0800205 # Expect the cellname in the ONOSCELL variable.
kelvin8ec71442015-01-15 16:57:00 -0800206 # Note that this variable name is subject to change
andrewonlab95ce8322014-10-13 14:12:04 -0400207 # and that this driver will have to change accordingly
Cameron Franke9c94fb02015-01-21 10:20:20 -0800208 self.handle.expect(str(cellname))
andrew@onlab.usc400b112015-01-21 15:33:19 -0800209 handleBefore = self.handle.before
210 handleAfter = self.handle.after
kelvin8ec71442015-01-15 16:57:00 -0800211 # Get the rest of the handle
Cameron Franke9c94fb02015-01-21 10:20:20 -0800212 self.handle.sendline("")
213 self.handle.expect("\$")
andrew@onlab.usc400b112015-01-21 15:33:19 -0800214 handleMore = self.handle.before
andrewonlab95ce8322014-10-13 14:12:04 -0400215
kelvin-onlabd3b64892015-01-20 13:26:24 -0800216 main.log.info( "Cell call returned: " + handleBefore +
217 handleAfter + handleMore )
andrewonlab95ce8322014-10-13 14:12:04 -0400218
219 return main.TRUE
220
Jon Halld4d4b372015-01-28 16:02:41 -0800221 except TypeError:
222 main.log.exception( self.name + ": Object not as expected" )
223 return None
andrewonlab95ce8322014-10-13 14:12:04 -0400224 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -0800225 main.log.error( self.name + ": eof exception found" )
226 main.log.error( self.name + ": " + self.handle.before )
andrewonlab95ce8322014-10-13 14:12:04 -0400227 main.cleanup()
228 main.exit()
Jon Hallfebb1c72015-03-05 13:30:09 -0800229 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -0800230 main.log.exception( self.name + ": Uncaught exception!" )
andrewonlab95ce8322014-10-13 14:12:04 -0400231 main.cleanup()
232 main.exit()
kelvin8ec71442015-01-15 16:57:00 -0800233
pingping-lin57a56ce2015-05-20 16:43:48 -0700234 def startOnosCli( self, ONOSIp, karafTimeout="",
Chiyu Chengef109502016-11-21 15:51:38 -0800235 commandlineTimeout=10, onosStartTimeout=60, waitForStart=False ):
kelvin8ec71442015-01-15 16:57:00 -0800236 """
Jon Hallefbd9792015-03-05 16:11:36 -0800237 karafTimeout is an optional argument. karafTimeout value passed
kelvin-onlabd3b64892015-01-20 13:26:24 -0800238 by user would be used to set the current karaf shell idle timeout.
239 Note that when ever this property is modified the shell will exit and
Hari Krishnad7b9c202015-01-05 10:38:14 -0800240 the subsequent login would reflect new idle timeout.
kelvin-onlabd3b64892015-01-20 13:26:24 -0800241 Below is an example to start a session with 60 seconds idle timeout
242 ( input value is in milliseconds ):
kelvin8ec71442015-01-15 16:57:00 -0800243
Hari Krishna25d42f72015-01-05 15:08:28 -0800244 tValue = "60000"
kelvin-onlabd3b64892015-01-20 13:26:24 -0800245 main.ONOScli1.startOnosCli( ONOSIp, karafTimeout=tValue )
kelvin8ec71442015-01-15 16:57:00 -0800246
kelvin-onlabd3b64892015-01-20 13:26:24 -0800247 Note: karafTimeout is left as str so that this could be read
248 and passed to startOnosCli from PARAMS file as str.
kelvin8ec71442015-01-15 16:57:00 -0800249 """
You Wangf69ab392016-01-26 16:34:38 -0800250 self.onosIp = ONOSIp
andrewonlab95ce8322014-10-13 14:12:04 -0400251 try:
Jon Hall67253832016-12-05 09:47:13 -0800252 # Check if we are already in the cli
kelvin8ec71442015-01-15 16:57:00 -0800253 self.handle.sendline( "" )
254 x = self.handle.expect( [
pingping-lin57a56ce2015-05-20 16:43:48 -0700255 "\$", "onos>" ], commandlineTimeout)
andrewonlab48829f62014-11-17 13:49:01 -0500256 if x == 1:
kelvin8ec71442015-01-15 16:57:00 -0800257 main.log.info( "ONOS cli is already running" )
andrewonlab48829f62014-11-17 13:49:01 -0500258 return main.TRUE
andrewonlab95ce8322014-10-13 14:12:04 -0400259
Jon Hall67253832016-12-05 09:47:13 -0800260 # Not in CLI so login
Chiyu Chengef109502016-11-21 15:51:38 -0800261 if waitForStart:
262 # Wait for onos start ( -w ) and enter onos cli
263 startCliCommand = "onos -w "
264 else:
265 startCliCommand = "onos "
266 self.handle.sendline( startCliCommand + str( ONOSIp ) )
kelvin8ec71442015-01-15 16:57:00 -0800267 i = self.handle.expect( [
268 "onos>",
pingping-lin57a56ce2015-05-20 16:43:48 -0700269 pexpect.TIMEOUT ], onosStartTimeout )
andrewonlab2a7ea9b2014-10-24 12:21:05 -0400270
271 if i == 0:
kelvin-onlabd3b64892015-01-20 13:26:24 -0800272 main.log.info( str( ONOSIp ) + " CLI Started successfully" )
Hari Krishnae36ef212015-01-04 14:09:13 -0800273 if karafTimeout:
kelvin8ec71442015-01-15 16:57:00 -0800274 self.handle.sendline(
Hari Krishnaac4e1782015-01-26 12:09:12 -0800275 "config:property-set -p org.apache.karaf.shell\
276 sshIdleTimeout " +
kelvin8ec71442015-01-15 16:57:00 -0800277 karafTimeout )
278 self.handle.expect( "\$" )
Chiyu Chengef109502016-11-21 15:51:38 -0800279 self.handle.sendline( startCliCommand + str( ONOSIp ) )
kelvin8ec71442015-01-15 16:57:00 -0800280 self.handle.expect( "onos>" )
andrewonlab2a7ea9b2014-10-24 12:21:05 -0400281 return main.TRUE
282 else:
kelvin8ec71442015-01-15 16:57:00 -0800283 # If failed, send ctrl+c to process and try again
284 main.log.info( "Starting CLI failed. Retrying..." )
285 self.handle.send( "\x03" )
Chiyu Chengef109502016-11-21 15:51:38 -0800286 self.handle.sendline( startCliCommand + str( ONOSIp ) )
kelvin8ec71442015-01-15 16:57:00 -0800287 i = self.handle.expect( [ "onos>", pexpect.TIMEOUT ],
288 timeout=30 )
andrewonlab3a7c3c72014-10-24 17:21:03 -0400289 if i == 0:
kelvin-onlabd3b64892015-01-20 13:26:24 -0800290 main.log.info( str( ONOSIp ) + " CLI Started " +
kelvin8ec71442015-01-15 16:57:00 -0800291 "successfully after retry attempt" )
Hari Krishnae36ef212015-01-04 14:09:13 -0800292 if karafTimeout:
kelvin8ec71442015-01-15 16:57:00 -0800293 self.handle.sendline(
kelvin-onlabd3b64892015-01-20 13:26:24 -0800294 "config:property-set -p org.apache.karaf.shell\
295 sshIdleTimeout " +
kelvin8ec71442015-01-15 16:57:00 -0800296 karafTimeout )
297 self.handle.expect( "\$" )
Chiyu Chengef109502016-11-21 15:51:38 -0800298 self.handle.sendline( startCliCommand + str( ONOSIp ) )
kelvin8ec71442015-01-15 16:57:00 -0800299 self.handle.expect( "onos>" )
andrewonlab3a7c3c72014-10-24 17:21:03 -0400300 return main.TRUE
301 else:
kelvin8ec71442015-01-15 16:57:00 -0800302 main.log.error( "Connection to CLI " +
kelvin-onlabd3b64892015-01-20 13:26:24 -0800303 str( ONOSIp ) + " timeout" )
andrewonlab3a7c3c72014-10-24 17:21:03 -0400304 return main.FALSE
andrewonlab95ce8322014-10-13 14:12:04 -0400305
Jon Halld4d4b372015-01-28 16:02:41 -0800306 except TypeError:
307 main.log.exception( self.name + ": Object not as expected" )
308 return None
andrewonlab95ce8322014-10-13 14:12:04 -0400309 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -0800310 main.log.error( self.name + ": EOF exception found" )
311 main.log.error( self.name + ": " + self.handle.before )
andrewonlab95ce8322014-10-13 14:12:04 -0400312 main.cleanup()
313 main.exit()
Jon Hallfebb1c72015-03-05 13:30:09 -0800314 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -0800315 main.log.exception( self.name + ": Uncaught exception!" )
andrewonlab95ce8322014-10-13 14:12:04 -0400316 main.cleanup()
317 main.exit()
318
suibin zhang116647a2016-05-06 16:30:09 -0700319 def startCellCli( self, karafTimeout="",
320 commandlineTimeout=10, onosStartTimeout=60 ):
321 """
322 Start CLI on onos ecll handle.
323
324 karafTimeout is an optional argument. karafTimeout value passed
325 by user would be used to set the current karaf shell idle timeout.
326 Note that when ever this property is modified the shell will exit and
327 the subsequent login would reflect new idle timeout.
328 Below is an example to start a session with 60 seconds idle timeout
329 ( input value is in milliseconds ):
330
331 tValue = "60000"
332
333 Note: karafTimeout is left as str so that this could be read
334 and passed to startOnosCli from PARAMS file as str.
335 """
336
337 try:
338 self.handle.sendline( "" )
339 x = self.handle.expect( [
340 "\$", "onos>" ], commandlineTimeout)
341
342 if x == 1:
343 main.log.info( "ONOS cli is already running" )
344 return main.TRUE
345
346 # Wait for onos start ( -w ) and enter onos cli
347 self.handle.sendline( "/opt/onos/bin/onos" )
348 i = self.handle.expect( [
349 "onos>",
350 pexpect.TIMEOUT ], onosStartTimeout )
351
352 if i == 0:
353 main.log.info( self.name + " CLI Started successfully" )
354 if karafTimeout:
355 self.handle.sendline(
356 "config:property-set -p org.apache.karaf.shell\
357 sshIdleTimeout " +
358 karafTimeout )
359 self.handle.expect( "\$" )
360 self.handle.sendline( "/opt/onos/bin/onos" )
361 self.handle.expect( "onos>" )
362 return main.TRUE
363 else:
364 # If failed, send ctrl+c to process and try again
365 main.log.info( "Starting CLI failed. Retrying..." )
366 self.handle.send( "\x03" )
367 self.handle.sendline( "/opt/onos/bin/onos" )
368 i = self.handle.expect( [ "onos>", pexpect.TIMEOUT ],
369 timeout=30 )
370 if i == 0:
371 main.log.info( self.name + " CLI Started " +
372 "successfully after retry attempt" )
373 if karafTimeout:
374 self.handle.sendline(
375 "config:property-set -p org.apache.karaf.shell\
376 sshIdleTimeout " +
377 karafTimeout )
378 self.handle.expect( "\$" )
379 self.handle.sendline( "/opt/onos/bin/onos" )
380 self.handle.expect( "onos>" )
381 return main.TRUE
382 else:
383 main.log.error( "Connection to CLI " +
384 self.name + " timeout" )
385 return main.FALSE
386
387 except TypeError:
388 main.log.exception( self.name + ": Object not as expected" )
389 return None
390 except pexpect.EOF:
391 main.log.error( self.name + ": EOF exception found" )
392 main.log.error( self.name + ": " + self.handle.before )
393 main.cleanup()
394 main.exit()
395 except Exception:
396 main.log.exception( self.name + ": Uncaught exception!" )
397 main.cleanup()
398 main.exit()
399
YPZhangebf9eb52016-05-12 15:20:24 -0700400 def log( self, cmdStr, level="",noExit=False):
kelvin-onlab9f541032015-02-04 16:19:53 -0800401 """
402 log the commands in the onos CLI.
kelvin-onlab338f5512015-02-06 10:53:16 -0800403 returns main.TRUE on success
Jon Hallefbd9792015-03-05 16:11:36 -0800404 returns main.FALSE if Error occurred
YPZhangebf9eb52016-05-12 15:20:24 -0700405 if noExit is True, TestON will not exit, but clean up
kelvin-onlab338f5512015-02-06 10:53:16 -0800406 Available level: DEBUG, TRACE, INFO, WARN, ERROR
407 Level defaults to INFO
kelvin-onlab9f541032015-02-04 16:19:53 -0800408 """
409 try:
kelvin-onlab338f5512015-02-06 10:53:16 -0800410 lvlStr = ""
411 if level:
412 lvlStr = "--level=" + level
413
kelvin-onlab338f5512015-02-06 10:53:16 -0800414 self.handle.sendline( "log:log " + lvlStr + " " + cmdStr )
Jon Hall390696c2015-05-05 17:13:41 -0700415 self.handle.expect( "log:log" )
kelvin-onlab9f541032015-02-04 16:19:53 -0800416 self.handle.expect( "onos>" )
kelvin-onlabfb521662015-02-27 09:52:40 -0800417
kelvin-onlab9f541032015-02-04 16:19:53 -0800418 response = self.handle.before
419 if re.search( "Error", response ):
420 return main.FALSE
421 return main.TRUE
Jon Hall80daded2015-05-27 16:07:00 -0700422 except pexpect.TIMEOUT:
423 main.log.exception( self.name + ": TIMEOUT exception found" )
YPZhangebf9eb52016-05-12 15:20:24 -0700424 if noExit:
425 main.cleanup()
426 return None
427 else:
428 main.cleanup()
429 main.exit()
kelvin-onlab9f541032015-02-04 16:19:53 -0800430 except pexpect.EOF:
431 main.log.error( self.name + ": EOF exception found" )
432 main.log.error( self.name + ": " + self.handle.before )
YPZhangebf9eb52016-05-12 15:20:24 -0700433 if noExit:
434 main.cleanup()
435 return None
436 else:
437 main.cleanup()
438 main.exit()
Jon Hallfebb1c72015-03-05 13:30:09 -0800439 except Exception:
kelvin-onlabfb521662015-02-27 09:52:40 -0800440 main.log.exception( self.name + ": Uncaught exception!" )
YPZhangebf9eb52016-05-12 15:20:24 -0700441 if noExit:
442 main.cleanup()
443 return None
444 else:
445 main.cleanup()
446 main.exit()
andrewonlab95ce8322014-10-13 14:12:04 -0400447
YPZhangebf9eb52016-05-12 15:20:24 -0700448 def sendline( self, cmdStr, showResponse=False, debug=False, timeout=10, noExit=False ):
kelvin8ec71442015-01-15 16:57:00 -0800449 """
Jon Halle3f39ff2015-01-13 11:50:53 -0800450 Send a completely user specified string to
451 the onos> prompt. Use this function if you have
andrewonlaba18f6bf2014-10-13 19:31:54 -0400452 a very specific command to send.
Jon Halle3f39ff2015-01-13 11:50:53 -0800453
YPZhang14a4aa92016-07-15 13:37:15 -0700454 if noExit is True, TestON will not exit, and return None
YPZhangebf9eb52016-05-12 15:20:24 -0700455
andrewonlaba18f6bf2014-10-13 19:31:54 -0400456 Warning: There are no sanity checking to commands
457 sent using this method.
GlennRCed771242016-01-13 17:02:47 -0800458
kelvin8ec71442015-01-15 16:57:00 -0800459 """
andrewonlaba18f6bf2014-10-13 19:31:54 -0400460 try:
Jon Halla495f562016-05-16 18:03:26 -0700461 # Try to reconnect if disconnected from cli
462 self.handle.sendline( "" )
463 i = self.handle.expect( [ "onos>", "\$", pexpect.TIMEOUT ] )
464 if i == 1:
465 main.log.error( self.name + ": onos cli session closed. ")
466 if self.onosIp:
467 main.log.warn( "Trying to reconnect " + self.onosIp )
468 reconnectResult = self.startOnosCli( self.onosIp )
469 if reconnectResult:
470 main.log.info( self.name + ": onos cli session reconnected." )
471 else:
472 main.log.error( self.name + ": reconnection failed." )
YPZhang14a4aa92016-07-15 13:37:15 -0700473 if noExit:
474 return None
475 else:
476 main.cleanup()
477 main.exit()
Jon Halla495f562016-05-16 18:03:26 -0700478 else:
479 main.cleanup()
480 main.exit()
481 if i == 2:
482 self.handle.sendline( "" )
483 self.handle.expect( "onos>" )
484
Jon Hall14a03b52016-05-11 12:07:30 -0700485 if debug:
486 # NOTE: This adds and average of .4 seconds per call
487 logStr = "\"Sending CLI command: '" + cmdStr + "'\""
YPZhangebf9eb52016-05-12 15:20:24 -0700488 self.log( logStr,noExit=noExit )
kelvin-onlabd3b64892015-01-20 13:26:24 -0800489 self.handle.sendline( cmdStr )
GlennRCed771242016-01-13 17:02:47 -0800490 i = self.handle.expect( ["onos>", "\$"], timeout )
Jon Hall63604932015-02-26 17:09:50 -0800491 response = self.handle.before
Jon Hall63604932015-02-26 17:09:50 -0800492 # TODO: do something with i
Jon Hallc6793552016-01-19 14:18:37 -0800493 main.log.info( "Command '" + str( cmdStr ) + "' sent to "
494 + self.name + "." )
Jon Hallc6358dd2015-04-10 12:44:28 -0700495 if debug:
Jon Hall390696c2015-05-05 17:13:41 -0700496 main.log.debug( self.name + ": Raw output" )
497 main.log.debug( self.name + ": " + repr( response ) )
Jon Hallc6358dd2015-04-10 12:44:28 -0700498
499 # Remove ANSI color control strings from output
kelvin-onlabd3b64892015-01-20 13:26:24 -0800500 ansiEscape = re.compile( r'\x1b[^m]*m' )
Jon Hall63604932015-02-26 17:09:50 -0800501 response = ansiEscape.sub( '', response )
Jon Hallc6358dd2015-04-10 12:44:28 -0700502 if debug:
Jon Hall390696c2015-05-05 17:13:41 -0700503 main.log.debug( self.name + ": ansiEscape output" )
504 main.log.debug( self.name + ": " + repr( response ) )
Jon Hallc6358dd2015-04-10 12:44:28 -0700505
kelvin-onlabfb521662015-02-27 09:52:40 -0800506 # Remove extra return chars that get added
Jon Hall63604932015-02-26 17:09:50 -0800507 response = re.sub( r"\s\r", "", response )
Jon Hallc6358dd2015-04-10 12:44:28 -0700508 if debug:
Jon Hall390696c2015-05-05 17:13:41 -0700509 main.log.debug( self.name + ": Removed extra returns " +
510 "from output" )
511 main.log.debug( self.name + ": " + repr( response ) )
Jon Hallc6358dd2015-04-10 12:44:28 -0700512
513 # Strip excess whitespace
Jon Hall63604932015-02-26 17:09:50 -0800514 response = response.strip()
Jon Hallc6358dd2015-04-10 12:44:28 -0700515 if debug:
Jon Hall390696c2015-05-05 17:13:41 -0700516 main.log.debug( self.name + ": parsed and stripped output" )
517 main.log.debug( self.name + ": " + repr( response ) )
Jon Hallc6358dd2015-04-10 12:44:28 -0700518
Jon Hall63604932015-02-26 17:09:50 -0800519 # parse for just the output, remove the cmd from response
Jon Hallc6358dd2015-04-10 12:44:28 -0700520 output = response.split( cmdStr.strip(), 1 )
521 if debug:
Jon Hall390696c2015-05-05 17:13:41 -0700522 main.log.debug( self.name + ": split output" )
Jon Hallc6358dd2015-04-10 12:44:28 -0700523 for r in output:
Jon Hall390696c2015-05-05 17:13:41 -0700524 main.log.debug( self.name + ": " + repr( r ) )
GlennRC85870432015-11-23 11:45:51 -0800525 output = output[1].strip()
526 if showResponse:
GlennRCed771242016-01-13 17:02:47 -0800527 main.log.info( "Response from ONOS: {}".format( output ) )
GlennRC85870432015-11-23 11:45:51 -0800528 return output
GlennRCed771242016-01-13 17:02:47 -0800529 except pexpect.TIMEOUT:
530 main.log.error( self.name + ":ONOS timeout" )
531 if debug:
532 main.log.debug( self.handle.before )
533 return None
Jon Hallc6358dd2015-04-10 12:44:28 -0700534 except IndexError:
535 main.log.exception( self.name + ": Object not as expected" )
Jon Halla495f562016-05-16 18:03:26 -0700536 main.log.debug( "response: {}".format( repr( response ) ) )
Jon Hallc6358dd2015-04-10 12:44:28 -0700537 return None
Jon Halld4d4b372015-01-28 16:02:41 -0800538 except TypeError:
539 main.log.exception( self.name + ": Object not as expected" )
540 return None
andrewonlaba18f6bf2014-10-13 19:31:54 -0400541 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -0800542 main.log.error( self.name + ": EOF exception found" )
543 main.log.error( self.name + ": " + self.handle.before )
YPZhangebf9eb52016-05-12 15:20:24 -0700544 if noExit:
YPZhangebf9eb52016-05-12 15:20:24 -0700545 return None
546 else:
547 main.cleanup()
548 main.exit()
Jon Hallfebb1c72015-03-05 13:30:09 -0800549 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -0800550 main.log.exception( self.name + ": Uncaught exception!" )
YPZhangebf9eb52016-05-12 15:20:24 -0700551 if noExit:
YPZhangebf9eb52016-05-12 15:20:24 -0700552 return None
553 else:
554 main.cleanup()
555 main.exit()
andrewonlaba18f6bf2014-10-13 19:31:54 -0400556
kelvin8ec71442015-01-15 16:57:00 -0800557 # IMPORTANT NOTE:
558 # For all cli commands, naming convention should match
kelvin-onlabd3b64892015-01-20 13:26:24 -0800559 # the cli command changing 'a:b' with 'aB'.
560 # Ex ) onos:topology > onosTopology
561 # onos:links > onosLinks
562 # feature:list > featureList
Jon Halle3f39ff2015-01-13 11:50:53 -0800563
kelvin-onlabd3b64892015-01-20 13:26:24 -0800564 def addNode( self, nodeId, ONOSIp, tcpPort="" ):
kelvin8ec71442015-01-15 16:57:00 -0800565 """
andrewonlabc2d05aa2014-10-13 16:51:10 -0400566 Adds a new cluster node by ID and address information.
567 Required:
kelvin-onlabd3b64892015-01-20 13:26:24 -0800568 * nodeId
569 * ONOSIp
andrewonlabc2d05aa2014-10-13 16:51:10 -0400570 Optional:
kelvin-onlabd3b64892015-01-20 13:26:24 -0800571 * tcpPort
kelvin8ec71442015-01-15 16:57:00 -0800572 """
andrewonlabc2d05aa2014-10-13 16:51:10 -0400573 try:
kelvin-onlabd3b64892015-01-20 13:26:24 -0800574 cmdStr = "add-node " + str( nodeId ) + " " +\
575 str( ONOSIp ) + " " + str( tcpPort )
576 handle = self.sendline( cmdStr )
Jon Halla495f562016-05-16 18:03:26 -0700577 assert handle is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -0800578 assert "Command not found:" not in handle, handle
kelvin-onlab898a6c62015-01-16 14:13:53 -0800579 if re.search( "Error", handle ):
kelvin8ec71442015-01-15 16:57:00 -0800580 main.log.error( "Error in adding node" )
581 main.log.error( handle )
Jon Halle3f39ff2015-01-13 11:50:53 -0800582 return main.FALSE
andrewonlabc2d05aa2014-10-13 16:51:10 -0400583 else:
kelvin-onlabd3b64892015-01-20 13:26:24 -0800584 main.log.info( "Node " + str( ONOSIp ) + " added" )
andrewonlabc2d05aa2014-10-13 16:51:10 -0400585 return main.TRUE
Jon Hallc6793552016-01-19 14:18:37 -0800586 except AssertionError:
587 main.log.exception( "" )
588 return None
Jon Halld4d4b372015-01-28 16:02:41 -0800589 except TypeError:
590 main.log.exception( self.name + ": Object not as expected" )
591 return None
andrewonlabc2d05aa2014-10-13 16:51:10 -0400592 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -0800593 main.log.error( self.name + ": EOF exception found" )
594 main.log.error( self.name + ": " + self.handle.before )
andrewonlabc2d05aa2014-10-13 16:51:10 -0400595 main.cleanup()
596 main.exit()
Jon Hallfebb1c72015-03-05 13:30:09 -0800597 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -0800598 main.log.exception( self.name + ": Uncaught exception!" )
andrewonlabc2d05aa2014-10-13 16:51:10 -0400599 main.cleanup()
600 main.exit()
601
kelvin-onlabd3b64892015-01-20 13:26:24 -0800602 def removeNode( self, nodeId ):
kelvin8ec71442015-01-15 16:57:00 -0800603 """
andrewonlab86dc3082014-10-13 18:18:38 -0400604 Removes a cluster by ID
605 Issues command: 'remove-node [<node-id>]'
606 Required:
kelvin-onlabd3b64892015-01-20 13:26:24 -0800607 * nodeId
kelvin8ec71442015-01-15 16:57:00 -0800608 """
andrewonlab86dc3082014-10-13 18:18:38 -0400609 try:
andrewonlab86dc3082014-10-13 18:18:38 -0400610
kelvin-onlabd3b64892015-01-20 13:26:24 -0800611 cmdStr = "remove-node " + str( nodeId )
Jon Hall08f61bc2015-04-13 16:00:30 -0700612 handle = self.sendline( cmdStr )
Jon Halla495f562016-05-16 18:03:26 -0700613 assert handle is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -0800614 assert "Command not found:" not in handle, handle
Jon Hallc6358dd2015-04-10 12:44:28 -0700615 if re.search( "Error", handle ):
616 main.log.error( "Error in removing node" )
617 main.log.error( handle )
618 return main.FALSE
619 else:
620 return main.TRUE
Jon Hallc6793552016-01-19 14:18:37 -0800621 except AssertionError:
622 main.log.exception( "" )
623 return None
Jon Halld4d4b372015-01-28 16:02:41 -0800624 except TypeError:
625 main.log.exception( self.name + ": Object not as expected" )
626 return None
andrewonlab86dc3082014-10-13 18:18:38 -0400627 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -0800628 main.log.error( self.name + ": EOF exception found" )
629 main.log.error( self.name + ": " + self.handle.before )
andrewonlab86dc3082014-10-13 18:18:38 -0400630 main.cleanup()
631 main.exit()
Jon Hallfebb1c72015-03-05 13:30:09 -0800632 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -0800633 main.log.exception( self.name + ": Uncaught exception!" )
andrewonlab86dc3082014-10-13 18:18:38 -0400634 main.cleanup()
635 main.exit()
andrewonlabc2d05aa2014-10-13 16:51:10 -0400636
Jon Hall61282e32015-03-19 11:34:11 -0700637 def nodes( self, jsonFormat=True):
kelvin8ec71442015-01-15 16:57:00 -0800638 """
andrewonlab7c211572014-10-15 16:45:20 -0400639 List the nodes currently visible
640 Issues command: 'nodes'
Jon Hall61282e32015-03-19 11:34:11 -0700641 Optional argument:
642 * jsonFormat - boolean indicating if you want output in json
kelvin8ec71442015-01-15 16:57:00 -0800643 """
andrewonlab7c211572014-10-15 16:45:20 -0400644 try:
Jon Hallc6358dd2015-04-10 12:44:28 -0700645 cmdStr = "nodes"
Jon Hall61282e32015-03-19 11:34:11 -0700646 if jsonFormat:
Jon Hallc6358dd2015-04-10 12:44:28 -0700647 cmdStr += " -j"
648 output = self.sendline( cmdStr )
Jon Halla495f562016-05-16 18:03:26 -0700649 assert output is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -0800650 assert "Command not found:" not in output, output
Jon Hallc6358dd2015-04-10 12:44:28 -0700651 return output
Jon Hallc6793552016-01-19 14:18:37 -0800652 except AssertionError:
653 main.log.exception( "" )
654 return None
Jon Halld4d4b372015-01-28 16:02:41 -0800655 except TypeError:
656 main.log.exception( self.name + ": Object not as expected" )
657 return None
andrewonlab7c211572014-10-15 16:45:20 -0400658 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -0800659 main.log.error( self.name + ": EOF exception found" )
660 main.log.error( self.name + ": " + self.handle.before )
andrewonlab7c211572014-10-15 16:45:20 -0400661 main.cleanup()
662 main.exit()
Jon Hallfebb1c72015-03-05 13:30:09 -0800663 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -0800664 main.log.exception( self.name + ": Uncaught exception!" )
andrewonlab7c211572014-10-15 16:45:20 -0400665 main.cleanup()
666 main.exit()
667
kelvin8ec71442015-01-15 16:57:00 -0800668 def topology( self ):
669 """
Hari Krishnaef1bd4e2015-03-12 16:55:30 -0700670 Definition:
Jon Hall390696c2015-05-05 17:13:41 -0700671 Returns the output of topology command.
Hari Krishnaef1bd4e2015-03-12 16:55:30 -0700672 Return:
673 topology = current ONOS topology
kelvin8ec71442015-01-15 16:57:00 -0800674 """
andrewonlab95ce8322014-10-13 14:12:04 -0400675 try:
Hari Krishnaef1bd4e2015-03-12 16:55:30 -0700676 cmdStr = "topology -j"
kelvin-onlabd3b64892015-01-20 13:26:24 -0800677 handle = self.sendline( cmdStr )
Jon Hallc6793552016-01-19 14:18:37 -0800678 assert "Command not found:" not in handle, handle
Jon Hallc6358dd2015-04-10 12:44:28 -0700679 main.log.info( cmdStr + " returned: " + str( handle ) )
andrewonlab95ce8322014-10-13 14:12:04 -0400680 return handle
Jon Hallc6793552016-01-19 14:18:37 -0800681 except AssertionError:
682 main.log.exception( "" )
Jon Halld4d4b372015-01-28 16:02:41 -0800683 return None
Jon Halld4d4b372015-01-28 16:02:41 -0800684 except TypeError:
685 main.log.exception( self.name + ": Object not as expected" )
686 return None
andrewonlabc2d05aa2014-10-13 16:51:10 -0400687 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -0800688 main.log.error( self.name + ": EOF exception found" )
689 main.log.error( self.name + ": " + self.handle.before )
andrewonlabc2d05aa2014-10-13 16:51:10 -0400690 main.cleanup()
691 main.exit()
Jon Hallfebb1c72015-03-05 13:30:09 -0800692 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -0800693 main.log.exception( self.name + ": Uncaught exception!" )
andrewonlabc2d05aa2014-10-13 16:51:10 -0400694 main.cleanup()
695 main.exit()
Jon Hallffb386d2014-11-21 13:43:38 -0800696
jenkins7ead5a82015-03-13 10:28:21 -0700697 def deviceRemove( self, deviceId ):
698 """
699 Removes particular device from storage
700
701 TODO: refactor this function
702 """
703 try:
Jon Hallc6358dd2015-04-10 12:44:28 -0700704 cmdStr = "device-remove " + str( deviceId )
705 handle = self.sendline( cmdStr )
Jon Hallc6793552016-01-19 14:18:37 -0800706 assert "Command not found:" not in handle, handle
Jon Hallc6358dd2015-04-10 12:44:28 -0700707 if re.search( "Error", handle ):
708 main.log.error( "Error in removing device" )
709 main.log.error( handle )
710 return main.FALSE
711 else:
712 return main.TRUE
Jon Hallc6793552016-01-19 14:18:37 -0800713 except AssertionError:
714 main.log.exception( "" )
715 return None
jenkins7ead5a82015-03-13 10:28:21 -0700716 except TypeError:
717 main.log.exception( self.name + ": Object not as expected" )
718 return None
719 except pexpect.EOF:
720 main.log.error( self.name + ": EOF exception found" )
721 main.log.error( self.name + ": " + self.handle.before )
722 main.cleanup()
723 main.exit()
724 except Exception:
725 main.log.exception( self.name + ": Uncaught exception!" )
726 main.cleanup()
727 main.exit()
jenkins7ead5a82015-03-13 10:28:21 -0700728
kelvin-onlabd3b64892015-01-20 13:26:24 -0800729 def devices( self, jsonFormat=True ):
kelvin8ec71442015-01-15 16:57:00 -0800730 """
Jon Hall7b02d952014-10-17 20:14:54 -0400731 Lists all infrastructure devices or switches
andrewonlab86dc3082014-10-13 18:18:38 -0400732 Optional argument:
kelvin-onlabd3b64892015-01-20 13:26:24 -0800733 * jsonFormat - boolean indicating if you want output in json
kelvin8ec71442015-01-15 16:57:00 -0800734 """
andrewonlab86dc3082014-10-13 18:18:38 -0400735 try:
Jon Hallc6358dd2015-04-10 12:44:28 -0700736 cmdStr = "devices"
kelvin-onlabd3b64892015-01-20 13:26:24 -0800737 if jsonFormat:
Jon Hallc6358dd2015-04-10 12:44:28 -0700738 cmdStr += " -j"
739 handle = self.sendline( cmdStr )
Jon Hallc6793552016-01-19 14:18:37 -0800740 assert "Command not found:" not in handle, handle
Jon Hallc6358dd2015-04-10 12:44:28 -0700741 return handle
Jon Hallc6793552016-01-19 14:18:37 -0800742 except AssertionError:
743 main.log.exception( "" )
744 return None
Jon Halld4d4b372015-01-28 16:02:41 -0800745 except TypeError:
746 main.log.exception( self.name + ": Object not as expected" )
747 return None
andrewonlab7c211572014-10-15 16:45:20 -0400748 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -0800749 main.log.error( self.name + ": EOF exception found" )
750 main.log.error( self.name + ": " + self.handle.before )
andrewonlab7c211572014-10-15 16:45:20 -0400751 main.cleanup()
752 main.exit()
Jon Hallfebb1c72015-03-05 13:30:09 -0800753 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -0800754 main.log.exception( self.name + ": Uncaught exception!" )
andrewonlab7c211572014-10-15 16:45:20 -0400755 main.cleanup()
756 main.exit()
757
kelvin-onlabd3b64892015-01-20 13:26:24 -0800758 def balanceMasters( self ):
kelvin8ec71442015-01-15 16:57:00 -0800759 """
Hari Krishnaa43d4e92014-12-19 13:22:40 -0800760 This balances the devices across all controllers
761 by issuing command: 'onos> onos:balance-masters'
762 If required this could be extended to return devices balanced output.
kelvin8ec71442015-01-15 16:57:00 -0800763 """
Hari Krishnaa43d4e92014-12-19 13:22:40 -0800764 try:
kelvin-onlabd3b64892015-01-20 13:26:24 -0800765 cmdStr = "onos:balance-masters"
Jon Hallc6358dd2015-04-10 12:44:28 -0700766 handle = self.sendline( cmdStr )
Jon Hallc6793552016-01-19 14:18:37 -0800767 assert "Command not found:" not in handle, handle
Jon Hallc6358dd2015-04-10 12:44:28 -0700768 if re.search( "Error", handle ):
769 main.log.error( "Error in balancing masters" )
770 main.log.error( handle )
771 return main.FALSE
772 else:
773 return main.TRUE
Jon Hallc6793552016-01-19 14:18:37 -0800774 except AssertionError:
775 main.log.exception( "" )
776 return None
Jon Halld4d4b372015-01-28 16:02:41 -0800777 except TypeError:
778 main.log.exception( self.name + ": Object not as expected" )
779 return None
Hari Krishnaa43d4e92014-12-19 13:22:40 -0800780 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -0800781 main.log.error( self.name + ": EOF exception found" )
782 main.log.error( self.name + ": " + self.handle.before )
Hari Krishnaa43d4e92014-12-19 13:22:40 -0800783 main.cleanup()
784 main.exit()
Jon Hallfebb1c72015-03-05 13:30:09 -0800785 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -0800786 main.log.exception( self.name + ": Uncaught exception!" )
Hari Krishnaa43d4e92014-12-19 13:22:40 -0800787 main.cleanup()
788 main.exit()
789
Jon Hallc6793552016-01-19 14:18:37 -0800790 def checkMasters( self, jsonFormat=True ):
acsmars24950022015-07-30 18:00:43 -0700791 """
792 Returns the output of the masters command.
793 Optional argument:
794 * jsonFormat - boolean indicating if you want output in json
795 """
796 try:
797 cmdStr = "onos:masters"
798 if jsonFormat:
799 cmdStr += " -j"
800 output = self.sendline( cmdStr )
Jon Halla495f562016-05-16 18:03:26 -0700801 assert output is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -0800802 assert "Command not found:" not in output, output
acsmars24950022015-07-30 18:00:43 -0700803 return output
Jon Hallc6793552016-01-19 14:18:37 -0800804 except AssertionError:
805 main.log.exception( "" )
806 return None
acsmars24950022015-07-30 18:00:43 -0700807 except TypeError:
808 main.log.exception( self.name + ": Object not as expected" )
809 return None
810 except pexpect.EOF:
811 main.log.error( self.name + ": EOF exception found" )
812 main.log.error( self.name + ": " + self.handle.before )
813 main.cleanup()
814 main.exit()
815 except Exception:
816 main.log.exception( self.name + ": Uncaught exception!" )
817 main.cleanup()
818 main.exit()
819
Jon Hallc6793552016-01-19 14:18:37 -0800820 def checkBalanceMasters( self, jsonFormat=True ):
acsmars24950022015-07-30 18:00:43 -0700821 """
822 Uses the master command to check that the devices' leadership
823 is evenly divided
824
825 Dependencies: checkMasters() and summary()
826
Jon Hall6509dbf2016-06-21 17:01:17 -0700827 Returns main.TRUE if the devices are balanced
828 Returns main.FALSE if the devices are unbalanced
acsmars24950022015-07-30 18:00:43 -0700829 Exits on Exception
830 Returns None on TypeError
831 """
832 try:
Jon Hallc6793552016-01-19 14:18:37 -0800833 summaryOutput = self.summary()
834 totalDevices = json.loads( summaryOutput )[ "devices" ]
835 except ( TypeError, ValueError ):
836 main.log.exception( "{}: Object not as expected: {!r}".format( self.name, summaryOutput ) )
837 return None
838 try:
acsmars24950022015-07-30 18:00:43 -0700839 totalOwnedDevices = 0
Jon Hallc6793552016-01-19 14:18:37 -0800840 mastersOutput = self.checkMasters()
841 masters = json.loads( mastersOutput )
acsmars24950022015-07-30 18:00:43 -0700842 first = masters[ 0 ][ "size" ]
843 for master in masters:
844 totalOwnedDevices += master[ "size" ]
845 if master[ "size" ] > first + 1 or master[ "size" ] < first - 1:
846 main.log.error( "Mastership not balanced" )
847 main.log.info( "\n" + self.checkMasters( False ) )
848 return main.FALSE
849 main.log.info( "Mastership balanced between " \
850 + str( len(masters) ) + " masters" )
851 return main.TRUE
Jon Hallc6793552016-01-19 14:18:37 -0800852 except ( TypeError, ValueError ):
853 main.log.exception( "{}: Object not as expected: {!r}".format( self.name, mastersOutput ) )
acsmars24950022015-07-30 18:00:43 -0700854 return None
855 except pexpect.EOF:
856 main.log.error( self.name + ": EOF exception found" )
857 main.log.error( self.name + ": " + self.handle.before )
858 main.cleanup()
859 main.exit()
860 except Exception:
861 main.log.exception( self.name + ": Uncaught exception!" )
862 main.cleanup()
863 main.exit()
864
YPZhangfebf7302016-05-24 16:45:56 -0700865 def links( self, jsonFormat=True, timeout=30 ):
kelvin8ec71442015-01-15 16:57:00 -0800866 """
Jon Halle8217482014-10-17 13:49:14 -0400867 Lists all core links
868 Optional argument:
kelvin-onlabd3b64892015-01-20 13:26:24 -0800869 * jsonFormat - boolean indicating if you want output in json
kelvin8ec71442015-01-15 16:57:00 -0800870 """
Jon Halle8217482014-10-17 13:49:14 -0400871 try:
Jon Hallc6358dd2015-04-10 12:44:28 -0700872 cmdStr = "links"
kelvin-onlabd3b64892015-01-20 13:26:24 -0800873 if jsonFormat:
Jon Hallc6358dd2015-04-10 12:44:28 -0700874 cmdStr += " -j"
YPZhangfebf7302016-05-24 16:45:56 -0700875 handle = self.sendline( cmdStr, timeout=timeout )
Jon Hallc6793552016-01-19 14:18:37 -0800876 assert "Command not found:" not in handle, handle
Jon Hallc6358dd2015-04-10 12:44:28 -0700877 return handle
Jon Hallc6793552016-01-19 14:18:37 -0800878 except AssertionError:
879 main.log.exception( "" )
880 return None
Jon Halld4d4b372015-01-28 16:02:41 -0800881 except TypeError:
882 main.log.exception( self.name + ": Object not as expected" )
883 return None
Jon Halle8217482014-10-17 13:49:14 -0400884 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -0800885 main.log.error( self.name + ": EOF exception found" )
886 main.log.error( self.name + ": " + self.handle.before )
Jon Halle8217482014-10-17 13:49:14 -0400887 main.cleanup()
888 main.exit()
Jon Hallfebb1c72015-03-05 13:30:09 -0800889 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -0800890 main.log.exception( self.name + ": Uncaught exception!" )
Jon Halle8217482014-10-17 13:49:14 -0400891 main.cleanup()
892 main.exit()
893
kelvin-onlabd3b64892015-01-20 13:26:24 -0800894 def ports( self, jsonFormat=True ):
kelvin8ec71442015-01-15 16:57:00 -0800895 """
Jon Halle8217482014-10-17 13:49:14 -0400896 Lists all ports
897 Optional argument:
kelvin-onlabd3b64892015-01-20 13:26:24 -0800898 * jsonFormat - boolean indicating if you want output in json
kelvin8ec71442015-01-15 16:57:00 -0800899 """
Jon Halle8217482014-10-17 13:49:14 -0400900 try:
Jon Hallc6358dd2015-04-10 12:44:28 -0700901 cmdStr = "ports"
kelvin-onlabd3b64892015-01-20 13:26:24 -0800902 if jsonFormat:
Jon Hallc6358dd2015-04-10 12:44:28 -0700903 cmdStr += " -j"
904 handle = self.sendline( cmdStr )
Jon Hallc6793552016-01-19 14:18:37 -0800905 assert "Command not found:" not in handle, handle
Jon Hallc6358dd2015-04-10 12:44:28 -0700906 return handle
Jon Hallc6793552016-01-19 14:18:37 -0800907 except AssertionError:
908 main.log.exception( "" )
909 return None
Jon Halld4d4b372015-01-28 16:02:41 -0800910 except TypeError:
911 main.log.exception( self.name + ": Object not as expected" )
912 return None
Jon Halle8217482014-10-17 13:49: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 )
Jon Halle8217482014-10-17 13:49:14 -0400916 main.cleanup()
917 main.exit()
Jon Hallfebb1c72015-03-05 13:30:09 -0800918 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -0800919 main.log.exception( self.name + ": Uncaught exception!" )
Jon Halle8217482014-10-17 13:49:14 -0400920 main.cleanup()
921 main.exit()
922
kelvin-onlabd3b64892015-01-20 13:26:24 -0800923 def roles( self, jsonFormat=True ):
kelvin8ec71442015-01-15 16:57:00 -0800924 """
Jon Hall983a1702014-10-28 18:44:22 -0400925 Lists all devices and the controllers with roles assigned to them
926 Optional argument:
kelvin-onlabd3b64892015-01-20 13:26:24 -0800927 * jsonFormat - boolean indicating if you want output in json
kelvin8ec71442015-01-15 16:57:00 -0800928 """
andrewonlab7c211572014-10-15 16:45:20 -0400929 try:
Jon Hallc6358dd2015-04-10 12:44:28 -0700930 cmdStr = "roles"
kelvin-onlabd3b64892015-01-20 13:26:24 -0800931 if jsonFormat:
Jon Hallc6358dd2015-04-10 12:44:28 -0700932 cmdStr += " -j"
933 handle = self.sendline( cmdStr )
Jon Hallc6793552016-01-19 14:18:37 -0800934 assert "Command not found:" not in handle, handle
Jon Hallc6358dd2015-04-10 12:44:28 -0700935 return handle
Jon Hallc6793552016-01-19 14:18:37 -0800936 except AssertionError:
937 main.log.exception( "" )
938 return None
Jon Halld4d4b372015-01-28 16:02:41 -0800939 except TypeError:
940 main.log.exception( self.name + ": Object not as expected" )
941 return None
Jon Hall983a1702014-10-28 18:44:22 -0400942 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -0800943 main.log.error( self.name + ": EOF exception found" )
944 main.log.error( self.name + ": " + self.handle.before )
Jon Hall983a1702014-10-28 18:44:22 -0400945 main.cleanup()
946 main.exit()
Jon Hallfebb1c72015-03-05 13:30:09 -0800947 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -0800948 main.log.exception( self.name + ": Uncaught exception!" )
Jon Hall983a1702014-10-28 18:44:22 -0400949 main.cleanup()
950 main.exit()
951
kelvin-onlabd3b64892015-01-20 13:26:24 -0800952 def getRole( self, deviceId ):
kelvin-onlab898a6c62015-01-16 14:13:53 -0800953 """
Jon Halle3f39ff2015-01-13 11:50:53 -0800954 Given the a string containing the json representation of the "roles"
955 cli command and a partial or whole device id, returns a json object
956 containing the roles output for the first device whose id contains
957 "device_id"
Jon Hall983a1702014-10-28 18:44:22 -0400958
959 Returns:
Jon Halle3f39ff2015-01-13 11:50:53 -0800960 A dict of the role assignments for the given device or
961 None if no match
kelvin8ec71442015-01-15 16:57:00 -0800962 """
Jon Hall983a1702014-10-28 18:44:22 -0400963 try:
kelvin-onlabd3b64892015-01-20 13:26:24 -0800964 if deviceId is None:
Jon Hall983a1702014-10-28 18:44:22 -0400965 return None
966 else:
kelvin-onlabd3b64892015-01-20 13:26:24 -0800967 rawRoles = self.roles()
968 rolesJson = json.loads( rawRoles )
kelvin8ec71442015-01-15 16:57:00 -0800969 # search json for the device with id then return the device
kelvin-onlabd3b64892015-01-20 13:26:24 -0800970 for device in rolesJson:
kelvin8ec71442015-01-15 16:57:00 -0800971 # print device
kelvin-onlabd3b64892015-01-20 13:26:24 -0800972 if str( deviceId ) in device[ 'id' ]:
Jon Hall983a1702014-10-28 18:44:22 -0400973 return device
974 return None
Jon Hallc6793552016-01-19 14:18:37 -0800975 except ( TypeError, ValueError ):
976 main.log.exception( "{}: Object not as expected: {!r}".format( self.name, rawRoles ) )
Jon Halld4d4b372015-01-28 16:02:41 -0800977 return None
andrewonlab86dc3082014-10-13 18:18:38 -0400978 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -0800979 main.log.error( self.name + ": EOF exception found" )
980 main.log.error( self.name + ": " + self.handle.before )
andrewonlab86dc3082014-10-13 18:18:38 -0400981 main.cleanup()
982 main.exit()
Jon Hallfebb1c72015-03-05 13:30:09 -0800983 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -0800984 main.log.exception( self.name + ": Uncaught exception!" )
andrewonlab86dc3082014-10-13 18:18:38 -0400985 main.cleanup()
986 main.exit()
Jon Hall94fd0472014-12-08 11:52:42 -0800987
kelvin-onlabd3b64892015-01-20 13:26:24 -0800988 def rolesNotNull( self ):
kelvin8ec71442015-01-15 16:57:00 -0800989 """
Jon Hall94fd0472014-12-08 11:52:42 -0800990 Iterates through each device and checks if there is a master assigned
991 Returns: main.TRUE if each device has a master
992 main.FALSE any device has no master
kelvin8ec71442015-01-15 16:57:00 -0800993 """
Jon Hall94fd0472014-12-08 11:52:42 -0800994 try:
kelvin-onlabd3b64892015-01-20 13:26:24 -0800995 rawRoles = self.roles()
996 rolesJson = json.loads( rawRoles )
kelvin8ec71442015-01-15 16:57:00 -0800997 # search json for the device with id then return the device
kelvin-onlabd3b64892015-01-20 13:26:24 -0800998 for device in rolesJson:
kelvin8ec71442015-01-15 16:57:00 -0800999 # print device
1000 if device[ 'master' ] == "none":
1001 main.log.warn( "Device has no master: " + str( device ) )
Jon Hall94fd0472014-12-08 11:52:42 -08001002 return main.FALSE
1003 return main.TRUE
Jon Hallc6793552016-01-19 14:18:37 -08001004 except ( TypeError, ValueError ):
1005 main.log.exception( "{}: Object not as expected: {!r}".format( self.name, rawRoles ) )
Jon Halld4d4b372015-01-28 16:02:41 -08001006 return None
Jon Hall94fd0472014-12-08 11:52:42 -08001007 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08001008 main.log.error( self.name + ": EOF exception found" )
1009 main.log.error( self.name + ": " + self.handle.before )
Jon Hall94fd0472014-12-08 11:52:42 -08001010 main.cleanup()
1011 main.exit()
Jon Hallfebb1c72015-03-05 13:30:09 -08001012 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -08001013 main.log.exception( self.name + ": Uncaught exception!" )
Jon Hall94fd0472014-12-08 11:52:42 -08001014 main.cleanup()
1015 main.exit()
1016
kelvin-onlabd3b64892015-01-20 13:26:24 -08001017 def paths( self, srcId, dstId ):
kelvin8ec71442015-01-15 16:57:00 -08001018 """
andrewonlab3e15ead2014-10-15 14:21:34 -04001019 Returns string of paths, and the cost.
1020 Issues command: onos:paths <src> <dst>
kelvin8ec71442015-01-15 16:57:00 -08001021 """
andrewonlab3e15ead2014-10-15 14:21:34 -04001022 try:
kelvin-onlabd3b64892015-01-20 13:26:24 -08001023 cmdStr = "onos:paths " + str( srcId ) + " " + str( dstId )
1024 handle = self.sendline( cmdStr )
Jon Hallc6793552016-01-19 14:18:37 -08001025 assert "Command not found:" not in handle, handle
Jon Halle3f39ff2015-01-13 11:50:53 -08001026 if re.search( "Error", handle ):
kelvin8ec71442015-01-15 16:57:00 -08001027 main.log.error( "Error in getting paths" )
1028 return ( handle, "Error" )
andrewonlab3e15ead2014-10-15 14:21:34 -04001029 else:
kelvin8ec71442015-01-15 16:57:00 -08001030 path = handle.split( ";" )[ 0 ]
1031 cost = handle.split( ";" )[ 1 ]
1032 return ( path, cost )
Jon Hallc6793552016-01-19 14:18:37 -08001033 except AssertionError:
1034 main.log.exception( "" )
1035 return ( handle, "Error" )
Jon Halld4d4b372015-01-28 16:02:41 -08001036 except TypeError:
1037 main.log.exception( self.name + ": Object not as expected" )
1038 return ( handle, "Error" )
andrewonlab3e15ead2014-10-15 14:21:34 -04001039 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08001040 main.log.error( self.name + ": EOF exception found" )
1041 main.log.error( self.name + ": " + self.handle.before )
andrewonlab3e15ead2014-10-15 14:21:34 -04001042 main.cleanup()
1043 main.exit()
Jon Hallfebb1c72015-03-05 13:30:09 -08001044 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -08001045 main.log.exception( self.name + ": Uncaught exception!" )
andrewonlab3e15ead2014-10-15 14:21:34 -04001046 main.cleanup()
1047 main.exit()
Jon Hallffb386d2014-11-21 13:43:38 -08001048
kelvin-onlabd3b64892015-01-20 13:26:24 -08001049 def hosts( self, jsonFormat=True ):
kelvin8ec71442015-01-15 16:57:00 -08001050 """
Jon Hallffb386d2014-11-21 13:43:38 -08001051 Lists all discovered hosts
Jon Hall42db6dc2014-10-24 19:03:48 -04001052 Optional argument:
kelvin-onlabd3b64892015-01-20 13:26:24 -08001053 * jsonFormat - boolean indicating if you want output in json
kelvin8ec71442015-01-15 16:57:00 -08001054 """
Jon Hall42db6dc2014-10-24 19:03:48 -04001055 try:
Jon Hallc6358dd2015-04-10 12:44:28 -07001056 cmdStr = "hosts"
kelvin-onlabd3b64892015-01-20 13:26:24 -08001057 if jsonFormat:
Jon Hallc6358dd2015-04-10 12:44:28 -07001058 cmdStr += " -j"
1059 handle = self.sendline( cmdStr )
Jeremyd9e4eb12016-04-13 12:09:06 -07001060 if handle:
1061 assert "Command not found:" not in handle, handle
Jon Hallbaf53162015-12-17 17:04:34 -08001062 # TODO: Maybe make this less hardcoded
1063 # ConsistentMap Exceptions
1064 assert "org.onosproject.store.service" not in handle
1065 # Node not leader
1066 assert "java.lang.IllegalStateException" not in handle
Jon Hallc6358dd2015-04-10 12:44:28 -07001067 return handle
Jon Hallc6793552016-01-19 14:18:37 -08001068 except AssertionError:
Jeremyd9e4eb12016-04-13 12:09:06 -07001069 main.log.exception( "Error in processing '" + cmdStr + "' " +
Jeremy Songster6949cea2016-04-19 18:13:18 -07001070 "command: " + str( handle ) )
Jon Hallc6793552016-01-19 14:18:37 -08001071 return None
Jon Halld4d4b372015-01-28 16:02:41 -08001072 except TypeError:
1073 main.log.exception( self.name + ": Object not as expected" )
1074 return None
Jon Hall42db6dc2014-10-24 19:03:48 -04001075 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08001076 main.log.error( self.name + ": EOF exception found" )
1077 main.log.error( self.name + ": " + self.handle.before )
Jon Hall42db6dc2014-10-24 19:03:48 -04001078 main.cleanup()
1079 main.exit()
Jon Hallfebb1c72015-03-05 13:30:09 -08001080 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -08001081 main.log.exception( self.name + ": Uncaught exception!" )
Jon Hall42db6dc2014-10-24 19:03:48 -04001082 main.cleanup()
1083 main.exit()
1084
kelvin-onlabd3b64892015-01-20 13:26:24 -08001085 def getHost( self, mac ):
kelvin8ec71442015-01-15 16:57:00 -08001086 """
Jon Hall42db6dc2014-10-24 19:03:48 -04001087 Return the first host from the hosts api whose 'id' contains 'mac'
Jon Halle3f39ff2015-01-13 11:50:53 -08001088
Jon Hallefbd9792015-03-05 16:11:36 -08001089 Note: mac must be a colon separated mac address, but could be a
Jon Halle3f39ff2015-01-13 11:50:53 -08001090 partial mac address
1091
Jon Hall42db6dc2014-10-24 19:03:48 -04001092 Return None if there is no match
kelvin8ec71442015-01-15 16:57:00 -08001093 """
Jon Hall42db6dc2014-10-24 19:03:48 -04001094 try:
kelvin8ec71442015-01-15 16:57:00 -08001095 if mac is None:
Jon Hall42db6dc2014-10-24 19:03:48 -04001096 return None
1097 else:
1098 mac = mac
kelvin-onlabd3b64892015-01-20 13:26:24 -08001099 rawHosts = self.hosts()
1100 hostsJson = json.loads( rawHosts )
kelvin8ec71442015-01-15 16:57:00 -08001101 # search json for the host with mac then return the device
kelvin-onlabd3b64892015-01-20 13:26:24 -08001102 for host in hostsJson:
kelvin8ec71442015-01-15 16:57:00 -08001103 # print "%s in %s?" % ( mac, host[ 'id' ] )
Jon Halld4d4b372015-01-28 16:02:41 -08001104 if not host:
1105 pass
1106 elif mac in host[ 'id' ]:
Jon Hall42db6dc2014-10-24 19:03:48 -04001107 return host
1108 return None
Jon Hallc6793552016-01-19 14:18:37 -08001109 except ( TypeError, ValueError ):
1110 main.log.exception( "{}: Object not as expected: {!r}".format( self.name, rawHosts ) )
Jon Halld4d4b372015-01-28 16:02:41 -08001111 return None
Jon Hall42db6dc2014-10-24 19:03:48 -04001112 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08001113 main.log.error( self.name + ": EOF exception found" )
1114 main.log.error( self.name + ": " + self.handle.before )
Jon Hall42db6dc2014-10-24 19:03:48 -04001115 main.cleanup()
1116 main.exit()
Jon Hallfebb1c72015-03-05 13:30:09 -08001117 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -08001118 main.log.exception( self.name + ": Uncaught exception!" )
Jon Hall42db6dc2014-10-24 19:03:48 -04001119 main.cleanup()
1120 main.exit()
1121
kelvin-onlabd3b64892015-01-20 13:26:24 -08001122 def getHostsId( self, hostList ):
kelvin8ec71442015-01-15 16:57:00 -08001123 """
1124 Obtain list of hosts
andrewonlab3f0a4af2014-10-17 12:25:14 -04001125 Issues command: 'onos> hosts'
kelvin8ec71442015-01-15 16:57:00 -08001126
andrewonlab3f0a4af2014-10-17 12:25:14 -04001127 Required:
kelvin-onlabd3b64892015-01-20 13:26:24 -08001128 * hostList: List of hosts obtained by Mininet
andrewonlab3f0a4af2014-10-17 12:25:14 -04001129 IMPORTANT:
1130 This function assumes that you started your
kelvin8ec71442015-01-15 16:57:00 -08001131 topology with the option '--mac'.
andrewonlab3f0a4af2014-10-17 12:25:14 -04001132 Furthermore, it assumes that value of VLAN is '-1'
1133 Description:
kelvin8ec71442015-01-15 16:57:00 -08001134 Converts mininet hosts ( h1, h2, h3... ) into
1135 ONOS format ( 00:00:00:00:00:01/-1 , ... )
1136 """
andrewonlab3f0a4af2014-10-17 12:25:14 -04001137 try:
kelvin-onlabd3b64892015-01-20 13:26:24 -08001138 onosHostList = []
andrewonlab3f0a4af2014-10-17 12:25:14 -04001139
kelvin-onlabd3b64892015-01-20 13:26:24 -08001140 for host in hostList:
kelvin8ec71442015-01-15 16:57:00 -08001141 host = host.replace( "h", "" )
kelvin-onlabd3b64892015-01-20 13:26:24 -08001142 hostHex = hex( int( host ) ).zfill( 12 )
1143 hostHex = str( hostHex ).replace( 'x', '0' )
1144 i = iter( str( hostHex ) )
1145 hostHex = ":".join( a + b for a, b in zip( i, i ) )
1146 hostHex = hostHex + "/-1"
1147 onosHostList.append( hostHex )
andrewonlab3f0a4af2014-10-17 12:25:14 -04001148
kelvin-onlabd3b64892015-01-20 13:26:24 -08001149 return onosHostList
andrewonlab3f0a4af2014-10-17 12:25:14 -04001150
Jon Halld4d4b372015-01-28 16:02:41 -08001151 except TypeError:
1152 main.log.exception( self.name + ": Object not as expected" )
1153 return None
andrewonlab3f0a4af2014-10-17 12:25:14 -04001154 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08001155 main.log.error( self.name + ": EOF exception found" )
1156 main.log.error( self.name + ": " + self.handle.before )
andrewonlab3f0a4af2014-10-17 12:25:14 -04001157 main.cleanup()
1158 main.exit()
Jon Hallfebb1c72015-03-05 13:30:09 -08001159 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -08001160 main.log.exception( self.name + ": Uncaught exception!" )
andrewonlab3f0a4af2014-10-17 12:25:14 -04001161 main.cleanup()
1162 main.exit()
andrewonlab3e15ead2014-10-15 14:21:34 -04001163
Jeremy Songsterc032f162016-08-04 17:14:49 -07001164 def addHostIntent( self, hostIdOne, hostIdTwo, vlanId="", setVlan="", encap="" ):
kelvin8ec71442015-01-15 16:57:00 -08001165 """
andrewonlabe6745342014-10-17 14:29:13 -04001166 Required:
kelvin-onlabd3b64892015-01-20 13:26:24 -08001167 * hostIdOne: ONOS host id for host1
1168 * hostIdTwo: ONOS host id for host2
Jeremy Songster832f9e92016-05-05 14:30:49 -07001169 Optional:
1170 * vlanId: specify a VLAN id for the intent
Jeremy Songsterff553672016-05-12 17:06:23 -07001171 * setVlan: specify a VLAN id treatment
Jeremy Songsterc032f162016-08-04 17:14:49 -07001172 * encap: specify an encapsulation type
andrewonlabe6745342014-10-17 14:29:13 -04001173 Description:
Jon Hallefbd9792015-03-05 16:11:36 -08001174 Adds a host-to-host intent ( bidirectional ) by
Jon Hallb1290e82014-11-18 16:17:48 -05001175 specifying the two hosts.
kelvin-onlabfb521662015-02-27 09:52:40 -08001176 Returns:
1177 A string of the intent id or None on Error
kelvin8ec71442015-01-15 16:57:00 -08001178 """
andrewonlabe6745342014-10-17 14:29:13 -04001179 try:
Jeremy Songster832f9e92016-05-05 14:30:49 -07001180 cmdStr = "add-host-intent "
1181 if vlanId:
1182 cmdStr += "-v " + str( vlanId ) + " "
Jeremy Songsterff553672016-05-12 17:06:23 -07001183 if setVlan:
1184 cmdStr += "--setVlan " + str( vlanId ) + " "
Jeremy Songsterc032f162016-08-04 17:14:49 -07001185 if encap:
1186 cmdStr += "--encapsulation " + str( encap ) + " "
Jeremy Songster832f9e92016-05-05 14:30:49 -07001187 cmdStr += str( hostIdOne ) + " " + str( hostIdTwo )
kelvin-onlabd3b64892015-01-20 13:26:24 -08001188 handle = self.sendline( cmdStr )
Jon Hallc6793552016-01-19 14:18:37 -08001189 assert "Command not found:" not in handle, handle
Hari Krishnaac4e1782015-01-26 12:09:12 -08001190 if re.search( "Error", handle ):
1191 main.log.error( "Error in adding Host intent" )
Jon Hall61282e32015-03-19 11:34:11 -07001192 main.log.debug( "Response from ONOS was: " + repr( handle ) )
kelvin-onlabfb521662015-02-27 09:52:40 -08001193 return None
Hari Krishnaac4e1782015-01-26 12:09:12 -08001194 else:
1195 main.log.info( "Host intent installed between " +
kelvin-onlabfb521662015-02-27 09:52:40 -08001196 str( hostIdOne ) + " and " + str( hostIdTwo ) )
1197 match = re.search('id=0x([\da-f]+),', handle)
1198 if match:
1199 return match.group()[3:-1]
1200 else:
1201 main.log.error( "Error, intent ID not found" )
Jon Hall61282e32015-03-19 11:34:11 -07001202 main.log.debug( "Response from ONOS was: " +
1203 repr( handle ) )
kelvin-onlabfb521662015-02-27 09:52:40 -08001204 return None
Jon Hallc6793552016-01-19 14:18:37 -08001205 except AssertionError:
1206 main.log.exception( "" )
1207 return None
Jon Halld4d4b372015-01-28 16:02:41 -08001208 except TypeError:
1209 main.log.exception( self.name + ": Object not as expected" )
1210 return None
andrewonlabe6745342014-10-17 14:29:13 -04001211 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08001212 main.log.error( self.name + ": EOF exception found" )
1213 main.log.error( self.name + ": " + self.handle.before )
andrewonlabe6745342014-10-17 14:29:13 -04001214 main.cleanup()
1215 main.exit()
Jon Hallfebb1c72015-03-05 13:30:09 -08001216 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -08001217 main.log.exception( self.name + ": Uncaught exception!" )
andrewonlabe6745342014-10-17 14:29:13 -04001218 main.cleanup()
1219 main.exit()
1220
kelvin-onlabd3b64892015-01-20 13:26:24 -08001221 def addOpticalIntent( self, ingressDevice, egressDevice ):
kelvin8ec71442015-01-15 16:57:00 -08001222 """
andrewonlab7b31d232014-10-24 13:31:47 -04001223 Required:
kelvin-onlabd3b64892015-01-20 13:26:24 -08001224 * ingressDevice: device id of ingress device
1225 * egressDevice: device id of egress device
andrewonlab7b31d232014-10-24 13:31:47 -04001226 Optional:
1227 TODO: Still needs to be implemented via dev side
kelvin-onlabfb521662015-02-27 09:52:40 -08001228 Description:
1229 Adds an optical intent by specifying an ingress and egress device
1230 Returns:
1231 A string of the intent id or None on error
kelvin-onlab898a6c62015-01-16 14:13:53 -08001232 """
andrewonlab7b31d232014-10-24 13:31:47 -04001233 try:
kelvin-onlabd3b64892015-01-20 13:26:24 -08001234 cmdStr = "add-optical-intent " + str( ingressDevice ) +\
1235 " " + str( egressDevice )
1236 handle = self.sendline( cmdStr )
Jon Hallc6793552016-01-19 14:18:37 -08001237 assert "Command not found:" not in handle, handle
kelvin-onlab898a6c62015-01-16 14:13:53 -08001238 # If error, return error message
Jon Halle3f39ff2015-01-13 11:50:53 -08001239 if re.search( "Error", handle ):
kelvin-onlabfb521662015-02-27 09:52:40 -08001240 main.log.error( "Error in adding Optical intent" )
1241 return None
andrewonlab7b31d232014-10-24 13:31:47 -04001242 else:
kelvin-onlabfb521662015-02-27 09:52:40 -08001243 main.log.info( "Optical intent installed between " +
1244 str( ingressDevice ) + " and " +
1245 str( egressDevice ) )
1246 match = re.search('id=0x([\da-f]+),', handle)
1247 if match:
1248 return match.group()[3:-1]
1249 else:
1250 main.log.error( "Error, intent ID not found" )
1251 return None
Jon Hallc6793552016-01-19 14:18:37 -08001252 except AssertionError:
1253 main.log.exception( "" )
1254 return None
Jon Halld4d4b372015-01-28 16:02:41 -08001255 except TypeError:
1256 main.log.exception( self.name + ": Object not as expected" )
1257 return None
andrewonlab7b31d232014-10-24 13:31:47 -04001258 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08001259 main.log.error( self.name + ": EOF exception found" )
1260 main.log.error( self.name + ": " + self.handle.before )
andrewonlab7b31d232014-10-24 13:31:47 -04001261 main.cleanup()
1262 main.exit()
Jon Hallfebb1c72015-03-05 13:30:09 -08001263 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -08001264 main.log.exception( self.name + ": Uncaught exception!" )
andrewonlab7b31d232014-10-24 13:31:47 -04001265 main.cleanup()
1266 main.exit()
1267
kelvin-onlabd3b64892015-01-20 13:26:24 -08001268 def addPointIntent(
kelvin-onlab898a6c62015-01-16 14:13:53 -08001269 self,
kelvin-onlabd3b64892015-01-20 13:26:24 -08001270 ingressDevice,
1271 egressDevice,
1272 portIngress="",
1273 portEgress="",
kelvin-onlab898a6c62015-01-16 14:13:53 -08001274 ethType="",
1275 ethSrc="",
1276 ethDst="",
1277 bandwidth="",
kelvin-onlabd3b64892015-01-20 13:26:24 -08001278 lambdaAlloc=False,
kelvin-onlab898a6c62015-01-16 14:13:53 -08001279 ipProto="",
1280 ipSrc="",
1281 ipDst="",
1282 tcpSrc="",
Jeremy Songster832f9e92016-05-05 14:30:49 -07001283 tcpDst="",
Jeremy Songsterff553672016-05-12 17:06:23 -07001284 vlanId="",
Jeremy Songsterc032f162016-08-04 17:14:49 -07001285 setVlan="",
1286 encap="" ):
kelvin8ec71442015-01-15 16:57:00 -08001287 """
andrewonlab4dbb4d82014-10-17 18:22:31 -04001288 Required:
kelvin-onlabd3b64892015-01-20 13:26:24 -08001289 * ingressDevice: device id of ingress device
1290 * egressDevice: device id of egress device
andrewonlab289e4b72014-10-21 21:24:18 -04001291 Optional:
1292 * ethType: specify ethType
kelvin8ec71442015-01-15 16:57:00 -08001293 * ethSrc: specify ethSrc ( i.e. src mac addr )
1294 * ethDst: specify ethDst ( i.e. dst mac addr )
andrewonlab0dbb6ec2014-11-06 13:46:55 -05001295 * bandwidth: specify bandwidth capacity of link
kelvin-onlabd3b64892015-01-20 13:26:24 -08001296 * lambdaAlloc: if True, intent will allocate lambda
andrewonlab40ccd8b2014-11-06 16:23:34 -05001297 for the specified intent
Jon Halle3f39ff2015-01-13 11:50:53 -08001298 * ipProto: specify ip protocol
andrewonlabf77e0cb2014-11-11 17:17:59 -05001299 * ipSrc: specify ip source address
1300 * ipDst: specify ip destination address
1301 * tcpSrc: specify tcp source port
1302 * tcpDst: specify tcp destination port
Jeremy Songster832f9e92016-05-05 14:30:49 -07001303 * vlanId: specify vlan ID
Jeremy Songsterff553672016-05-12 17:06:23 -07001304 * setVlan: specify a VLAN id treatment
Jeremy Songsterc032f162016-08-04 17:14:49 -07001305 * encap: specify an Encapsulation type to use
andrewonlab4dbb4d82014-10-17 18:22:31 -04001306 Description:
kelvin8ec71442015-01-15 16:57:00 -08001307 Adds a point-to-point intent ( uni-directional ) by
andrewonlab289e4b72014-10-21 21:24:18 -04001308 specifying device id's and optional fields
kelvin-onlabfb521662015-02-27 09:52:40 -08001309 Returns:
1310 A string of the intent id or None on error
andrewonlab289e4b72014-10-21 21:24:18 -04001311
Jon Halle3f39ff2015-01-13 11:50:53 -08001312 NOTE: This function may change depending on the
andrewonlab4dbb4d82014-10-17 18:22:31 -04001313 options developers provide for point-to-point
1314 intent via cli
kelvin8ec71442015-01-15 16:57:00 -08001315 """
andrewonlab4dbb4d82014-10-17 18:22:31 -04001316 try:
Jeremy Songsterff553672016-05-12 17:06:23 -07001317 cmd = "add-point-intent"
andrewonlab36af3822014-11-18 17:48:18 -05001318
Jeremy Songsterff553672016-05-12 17:06:23 -07001319 if ethType:
1320 cmd += " --ethType " + str( ethType )
1321 if ethSrc:
1322 cmd += " --ethSrc " + str( ethSrc )
1323 if ethDst:
1324 cmd += " --ethDst " + str( ethDst )
1325 if bandwidth:
1326 cmd += " --bandwidth " + str( bandwidth )
1327 if lambdaAlloc:
1328 cmd += " --lambda "
1329 if ipProto:
1330 cmd += " --ipProto " + str( ipProto )
1331 if ipSrc:
1332 cmd += " --ipSrc " + str( ipSrc )
1333 if ipDst:
1334 cmd += " --ipDst " + str( ipDst )
1335 if tcpSrc:
1336 cmd += " --tcpSrc " + str( tcpSrc )
1337 if tcpDst:
1338 cmd += " --tcpDst " + str( tcpDst )
1339 if vlanId:
1340 cmd += " -v " + str( vlanId )
1341 if setVlan:
1342 cmd += " --setVlan " + str( setVlan )
Jeremy Songsterc032f162016-08-04 17:14:49 -07001343 if encap:
1344 cmd += " --encapsulation " + str( encap )
andrewonlab289e4b72014-10-21 21:24:18 -04001345
kelvin8ec71442015-01-15 16:57:00 -08001346 # Check whether the user appended the port
1347 # or provided it as an input
kelvin-onlabd3b64892015-01-20 13:26:24 -08001348 if "/" in ingressDevice:
1349 cmd += " " + str( ingressDevice )
andrewonlab36af3822014-11-18 17:48:18 -05001350 else:
kelvin-onlabd3b64892015-01-20 13:26:24 -08001351 if not portIngress:
kelvin-onlabfb521662015-02-27 09:52:40 -08001352 main.log.error( "You must specify the ingress port" )
kelvin8ec71442015-01-15 16:57:00 -08001353 # TODO: perhaps more meaningful return
kelvin-onlabfb521662015-02-27 09:52:40 -08001354 # Would it make sense to throw an exception and exit
1355 # the test?
1356 return None
andrewonlab36af3822014-11-18 17:48:18 -05001357
kelvin8ec71442015-01-15 16:57:00 -08001358 cmd += " " + \
kelvin-onlabd3b64892015-01-20 13:26:24 -08001359 str( ingressDevice ) + "/" +\
1360 str( portIngress ) + " "
andrewonlab36af3822014-11-18 17:48:18 -05001361
kelvin-onlabd3b64892015-01-20 13:26:24 -08001362 if "/" in egressDevice:
1363 cmd += " " + str( egressDevice )
andrewonlab36af3822014-11-18 17:48:18 -05001364 else:
kelvin-onlabd3b64892015-01-20 13:26:24 -08001365 if not portEgress:
kelvin-onlabfb521662015-02-27 09:52:40 -08001366 main.log.error( "You must specify the egress port" )
1367 return None
Jon Halle3f39ff2015-01-13 11:50:53 -08001368
kelvin8ec71442015-01-15 16:57:00 -08001369 cmd += " " +\
kelvin-onlabd3b64892015-01-20 13:26:24 -08001370 str( egressDevice ) + "/" +\
1371 str( portEgress )
kelvin8ec71442015-01-15 16:57:00 -08001372
kelvin-onlab898a6c62015-01-16 14:13:53 -08001373 handle = self.sendline( cmd )
Jon Hallc6793552016-01-19 14:18:37 -08001374 assert "Command not found:" not in handle, handle
kelvin-onlabfb521662015-02-27 09:52:40 -08001375 # If error, return error message
kelvin-onlab898a6c62015-01-16 14:13:53 -08001376 if re.search( "Error", handle ):
kelvin8ec71442015-01-15 16:57:00 -08001377 main.log.error( "Error in adding point-to-point intent" )
kelvin-onlabfb521662015-02-27 09:52:40 -08001378 return None
andrewonlab4dbb4d82014-10-17 18:22:31 -04001379 else:
kelvin-onlabfb521662015-02-27 09:52:40 -08001380 # TODO: print out all the options in this message?
1381 main.log.info( "Point-to-point intent installed between " +
1382 str( ingressDevice ) + " and " +
1383 str( egressDevice ) )
1384 match = re.search('id=0x([\da-f]+),', handle)
1385 if match:
1386 return match.group()[3:-1]
1387 else:
1388 main.log.error( "Error, intent ID not found" )
1389 return None
Jon Hallc6793552016-01-19 14:18:37 -08001390 except AssertionError:
1391 main.log.exception( "" )
1392 return None
Jon Halld4d4b372015-01-28 16:02:41 -08001393 except TypeError:
1394 main.log.exception( self.name + ": Object not as expected" )
1395 return None
andrewonlab4dbb4d82014-10-17 18:22:31 -04001396 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08001397 main.log.error( self.name + ": EOF exception found" )
1398 main.log.error( self.name + ": " + self.handle.before )
andrewonlab4dbb4d82014-10-17 18:22:31 -04001399 main.cleanup()
1400 main.exit()
Jon Hallfebb1c72015-03-05 13:30:09 -08001401 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -08001402 main.log.exception( self.name + ": Uncaught exception!" )
andrewonlab4dbb4d82014-10-17 18:22:31 -04001403 main.cleanup()
1404 main.exit()
1405
kelvin-onlabd3b64892015-01-20 13:26:24 -08001406 def addMultipointToSinglepointIntent(
kelvin-onlab898a6c62015-01-16 14:13:53 -08001407 self,
shahshreyac2f97072015-03-19 17:04:29 -07001408 ingressDeviceList,
kelvin-onlabd3b64892015-01-20 13:26:24 -08001409 egressDevice,
shahshreyac2f97072015-03-19 17:04:29 -07001410 portIngressList=None,
kelvin-onlabd3b64892015-01-20 13:26:24 -08001411 portEgress="",
kelvin-onlab898a6c62015-01-16 14:13:53 -08001412 ethType="",
1413 ethSrc="",
1414 ethDst="",
1415 bandwidth="",
kelvin-onlabd3b64892015-01-20 13:26:24 -08001416 lambdaAlloc=False,
kelvin-onlab898a6c62015-01-16 14:13:53 -08001417 ipProto="",
1418 ipSrc="",
1419 ipDst="",
1420 tcpSrc="",
1421 tcpDst="",
1422 setEthSrc="",
Jeremy Songster832f9e92016-05-05 14:30:49 -07001423 setEthDst="",
Jeremy Songsterff553672016-05-12 17:06:23 -07001424 vlanId="",
Jeremy Songster9385d412016-06-02 17:57:36 -07001425 setVlan="",
Jeremy Songsterc032f162016-08-04 17:14:49 -07001426 partial=False,
1427 encap="" ):
kelvin8ec71442015-01-15 16:57:00 -08001428 """
shahshreyad0c80432014-12-04 16:56:05 -08001429 Note:
shahshreya70622b12015-03-19 17:19:00 -07001430 This function assumes the format of all ingress devices
Jon Hallbe379602015-03-24 13:39:32 -07001431 is same. That is, all ingress devices include port numbers
1432 with a "/" or all ingress devices could specify device
1433 ids and port numbers seperately.
shahshreyad0c80432014-12-04 16:56:05 -08001434 Required:
Jon Hallbe379602015-03-24 13:39:32 -07001435 * ingressDeviceList: List of device ids of ingress device
shahshreyac2f97072015-03-19 17:04:29 -07001436 ( Atleast 2 ingress devices required in the list )
kelvin-onlabd3b64892015-01-20 13:26:24 -08001437 * egressDevice: device id of egress device
shahshreyad0c80432014-12-04 16:56:05 -08001438 Optional:
1439 * ethType: specify ethType
kelvin8ec71442015-01-15 16:57:00 -08001440 * ethSrc: specify ethSrc ( i.e. src mac addr )
1441 * ethDst: specify ethDst ( i.e. dst mac addr )
shahshreyad0c80432014-12-04 16:56:05 -08001442 * bandwidth: specify bandwidth capacity of link
kelvin-onlabd3b64892015-01-20 13:26:24 -08001443 * lambdaAlloc: if True, intent will allocate lambda
shahshreyad0c80432014-12-04 16:56:05 -08001444 for the specified intent
Jon Halle3f39ff2015-01-13 11:50:53 -08001445 * ipProto: specify ip protocol
shahshreyad0c80432014-12-04 16:56:05 -08001446 * ipSrc: specify ip source address
1447 * ipDst: specify ip destination address
1448 * tcpSrc: specify tcp source port
1449 * tcpDst: specify tcp destination port
1450 * setEthSrc: action to Rewrite Source MAC Address
1451 * setEthDst: action to Rewrite Destination MAC Address
Jeremy Songster832f9e92016-05-05 14:30:49 -07001452 * vlanId: specify vlan Id
Jeremy Songsterff553672016-05-12 17:06:23 -07001453 * setVlan: specify VLAN Id treatment
Jeremy Songsterc032f162016-08-04 17:14:49 -07001454 * encap: specify a type of encapsulation
shahshreyad0c80432014-12-04 16:56:05 -08001455 Description:
kelvin8ec71442015-01-15 16:57:00 -08001456 Adds a multipoint-to-singlepoint intent ( uni-directional ) by
shahshreyad0c80432014-12-04 16:56:05 -08001457 specifying device id's and optional fields
kelvin-onlabfb521662015-02-27 09:52:40 -08001458 Returns:
1459 A string of the intent id or None on error
shahshreyad0c80432014-12-04 16:56:05 -08001460
Jon Halle3f39ff2015-01-13 11:50:53 -08001461 NOTE: This function may change depending on the
Jon Hallefbd9792015-03-05 16:11:36 -08001462 options developers provide for multipoint-to-singlepoint
shahshreyad0c80432014-12-04 16:56:05 -08001463 intent via cli
kelvin8ec71442015-01-15 16:57:00 -08001464 """
shahshreyad0c80432014-12-04 16:56:05 -08001465 try:
Jeremy Songsterff553672016-05-12 17:06:23 -07001466 cmd = "add-multi-to-single-intent"
shahshreyad0c80432014-12-04 16:56:05 -08001467
Jeremy Songsterff553672016-05-12 17:06:23 -07001468 if ethType:
1469 cmd += " --ethType " + str( ethType )
1470 if ethSrc:
1471 cmd += " --ethSrc " + str( ethSrc )
1472 if ethDst:
1473 cmd += " --ethDst " + str( ethDst )
1474 if bandwidth:
1475 cmd += " --bandwidth " + str( bandwidth )
1476 if lambdaAlloc:
1477 cmd += " --lambda "
1478 if ipProto:
1479 cmd += " --ipProto " + str( ipProto )
1480 if ipSrc:
1481 cmd += " --ipSrc " + str( ipSrc )
1482 if ipDst:
1483 cmd += " --ipDst " + str( ipDst )
1484 if tcpSrc:
1485 cmd += " --tcpSrc " + str( tcpSrc )
1486 if tcpDst:
1487 cmd += " --tcpDst " + str( tcpDst )
1488 if setEthSrc:
1489 cmd += " --setEthSrc " + str( setEthSrc )
1490 if setEthDst:
1491 cmd += " --setEthDst " + str( setEthDst )
1492 if vlanId:
1493 cmd += " -v " + str( vlanId )
1494 if setVlan:
1495 cmd += " --setVlan " + str( setVlan )
Jeremy Songster9385d412016-06-02 17:57:36 -07001496 if partial:
1497 cmd += " --partial"
Jeremy Songsterc032f162016-08-04 17:14:49 -07001498 if encap:
1499 cmd += " --encapsulation " + str( encap )
shahshreyad0c80432014-12-04 16:56:05 -08001500
kelvin8ec71442015-01-15 16:57:00 -08001501 # Check whether the user appended the port
1502 # or provided it as an input
shahshreyac2f97072015-03-19 17:04:29 -07001503
1504 if portIngressList is None:
1505 for ingressDevice in ingressDeviceList:
1506 if "/" in ingressDevice:
1507 cmd += " " + str( ingressDevice )
1508 else:
1509 main.log.error( "You must specify " +
Jon Hallbe379602015-03-24 13:39:32 -07001510 "the ingress port" )
shahshreyac2f97072015-03-19 17:04:29 -07001511 # TODO: perhaps more meaningful return
1512 return main.FALSE
shahshreyad0c80432014-12-04 16:56:05 -08001513 else:
Jon Hall71ce4e72015-03-23 14:05:58 -07001514 if len( ingressDeviceList ) == len( portIngressList ):
Jon Hall08f61bc2015-04-13 16:00:30 -07001515 for ingressDevice, portIngress in zip( ingressDeviceList,
1516 portIngressList ):
shahshreya70622b12015-03-19 17:19:00 -07001517 cmd += " " + \
1518 str( ingressDevice ) + "/" +\
1519 str( portIngress ) + " "
kelvin-onlab38143812015-04-01 15:03:01 -07001520 else:
Jon Hall08f61bc2015-04-13 16:00:30 -07001521 main.log.error( "Device list and port list does not " +
1522 "have the same length" )
kelvin-onlab38143812015-04-01 15:03:01 -07001523 return main.FALSE
kelvin-onlabd3b64892015-01-20 13:26:24 -08001524 if "/" in egressDevice:
1525 cmd += " " + str( egressDevice )
shahshreyad0c80432014-12-04 16:56:05 -08001526 else:
kelvin-onlabd3b64892015-01-20 13:26:24 -08001527 if not portEgress:
kelvin8ec71442015-01-15 16:57:00 -08001528 main.log.error( "You must specify " +
1529 "the egress port" )
shahshreyad0c80432014-12-04 16:56:05 -08001530 return main.FALSE
Jon Halle3f39ff2015-01-13 11:50:53 -08001531
kelvin8ec71442015-01-15 16:57:00 -08001532 cmd += " " +\
kelvin-onlabd3b64892015-01-20 13:26:24 -08001533 str( egressDevice ) + "/" +\
1534 str( portEgress )
kelvin-onlab898a6c62015-01-16 14:13:53 -08001535 handle = self.sendline( cmd )
Jon Hallc6793552016-01-19 14:18:37 -08001536 assert "Command not found:" not in handle, handle
kelvin-onlabfb521662015-02-27 09:52:40 -08001537 # If error, return error message
kelvin-onlab898a6c62015-01-16 14:13:53 -08001538 if re.search( "Error", handle ):
kelvin-onlabfb521662015-02-27 09:52:40 -08001539 main.log.error( "Error in adding multipoint-to-singlepoint " +
1540 "intent" )
1541 return None
shahshreyad0c80432014-12-04 16:56:05 -08001542 else:
kelvin-onlabb9408212015-04-01 13:34:04 -07001543 match = re.search('id=0x([\da-f]+),', handle)
1544 if match:
1545 return match.group()[3:-1]
1546 else:
1547 main.log.error( "Error, intent ID not found" )
1548 return None
Jon Hallc6793552016-01-19 14:18:37 -08001549 except AssertionError:
1550 main.log.exception( "" )
1551 return None
kelvin-onlabb9408212015-04-01 13:34:04 -07001552 except TypeError:
1553 main.log.exception( self.name + ": Object not as expected" )
1554 return None
1555 except pexpect.EOF:
1556 main.log.error( self.name + ": EOF exception found" )
1557 main.log.error( self.name + ": " + self.handle.before )
1558 main.cleanup()
1559 main.exit()
1560 except Exception:
1561 main.log.exception( self.name + ": Uncaught exception!" )
1562 main.cleanup()
1563 main.exit()
1564
1565 def addSinglepointToMultipointIntent(
1566 self,
1567 ingressDevice,
1568 egressDeviceList,
1569 portIngress="",
1570 portEgressList=None,
1571 ethType="",
1572 ethSrc="",
1573 ethDst="",
1574 bandwidth="",
1575 lambdaAlloc=False,
1576 ipProto="",
1577 ipSrc="",
1578 ipDst="",
1579 tcpSrc="",
1580 tcpDst="",
1581 setEthSrc="",
Jeremy Songster832f9e92016-05-05 14:30:49 -07001582 setEthDst="",
Jeremy Songsterff553672016-05-12 17:06:23 -07001583 vlanId="",
Jeremy Songster9385d412016-06-02 17:57:36 -07001584 setVlan="",
Jeremy Songsterc032f162016-08-04 17:14:49 -07001585 partial=False,
1586 encap="" ):
kelvin-onlabb9408212015-04-01 13:34:04 -07001587 """
1588 Note:
1589 This function assumes the format of all egress devices
1590 is same. That is, all egress devices include port numbers
1591 with a "/" or all egress devices could specify device
1592 ids and port numbers seperately.
1593 Required:
1594 * EgressDeviceList: List of device ids of egress device
1595 ( Atleast 2 eress devices required in the list )
1596 * ingressDevice: device id of ingress device
1597 Optional:
1598 * ethType: specify ethType
1599 * ethSrc: specify ethSrc ( i.e. src mac addr )
1600 * ethDst: specify ethDst ( i.e. dst mac addr )
1601 * bandwidth: specify bandwidth capacity of link
1602 * lambdaAlloc: if True, intent will allocate lambda
1603 for the specified intent
1604 * ipProto: specify ip protocol
1605 * ipSrc: specify ip source address
1606 * ipDst: specify ip destination address
1607 * tcpSrc: specify tcp source port
1608 * tcpDst: specify tcp destination port
1609 * setEthSrc: action to Rewrite Source MAC Address
1610 * setEthDst: action to Rewrite Destination MAC Address
Jeremy Songster832f9e92016-05-05 14:30:49 -07001611 * vlanId: specify vlan Id
Jeremy Songsterff553672016-05-12 17:06:23 -07001612 * setVlan: specify VLAN ID treatment
Jeremy Songsterc032f162016-08-04 17:14:49 -07001613 * encap: specify an encapsulation type
kelvin-onlabb9408212015-04-01 13:34:04 -07001614 Description:
1615 Adds a singlepoint-to-multipoint intent ( uni-directional ) by
1616 specifying device id's and optional fields
1617 Returns:
1618 A string of the intent id or None on error
1619
1620 NOTE: This function may change depending on the
1621 options developers provide for singlepoint-to-multipoint
1622 intent via cli
1623 """
1624 try:
Jeremy Songsterff553672016-05-12 17:06:23 -07001625 cmd = "add-single-to-multi-intent"
kelvin-onlabb9408212015-04-01 13:34:04 -07001626
Jeremy Songsterff553672016-05-12 17:06:23 -07001627 if ethType:
1628 cmd += " --ethType " + str( ethType )
1629 if ethSrc:
1630 cmd += " --ethSrc " + str( ethSrc )
1631 if ethDst:
1632 cmd += " --ethDst " + str( ethDst )
1633 if bandwidth:
1634 cmd += " --bandwidth " + str( bandwidth )
1635 if lambdaAlloc:
1636 cmd += " --lambda "
1637 if ipProto:
1638 cmd += " --ipProto " + str( ipProto )
1639 if ipSrc:
1640 cmd += " --ipSrc " + str( ipSrc )
1641 if ipDst:
1642 cmd += " --ipDst " + str( ipDst )
1643 if tcpSrc:
1644 cmd += " --tcpSrc " + str( tcpSrc )
1645 if tcpDst:
1646 cmd += " --tcpDst " + str( tcpDst )
1647 if setEthSrc:
1648 cmd += " --setEthSrc " + str( setEthSrc )
1649 if setEthDst:
1650 cmd += " --setEthDst " + str( setEthDst )
1651 if vlanId:
1652 cmd += " -v " + str( vlanId )
1653 if setVlan:
1654 cmd += " --setVlan " + str( setVlan )
Jeremy Songster9385d412016-06-02 17:57:36 -07001655 if partial:
1656 cmd += " --partial"
Jeremy Songsterc032f162016-08-04 17:14:49 -07001657 if encap:
1658 cmd += " --encapsulation " + str( encap )
kelvin-onlabb9408212015-04-01 13:34:04 -07001659
1660 # Check whether the user appended the port
1661 # or provided it as an input
Jon Hall08f61bc2015-04-13 16:00:30 -07001662
kelvin-onlabb9408212015-04-01 13:34:04 -07001663 if "/" in ingressDevice:
1664 cmd += " " + str( ingressDevice )
1665 else:
1666 if not portIngress:
1667 main.log.error( "You must specify " +
1668 "the Ingress port" )
1669 return main.FALSE
1670
1671 cmd += " " +\
1672 str( ingressDevice ) + "/" +\
1673 str( portIngress )
1674
1675 if portEgressList is None:
1676 for egressDevice in egressDeviceList:
1677 if "/" in egressDevice:
1678 cmd += " " + str( egressDevice )
1679 else:
1680 main.log.error( "You must specify " +
1681 "the egress port" )
1682 # TODO: perhaps more meaningful return
1683 return main.FALSE
1684 else:
1685 if len( egressDeviceList ) == len( portEgressList ):
Jon Hall08f61bc2015-04-13 16:00:30 -07001686 for egressDevice, portEgress in zip( egressDeviceList,
1687 portEgressList ):
kelvin-onlabb9408212015-04-01 13:34:04 -07001688 cmd += " " + \
1689 str( egressDevice ) + "/" +\
1690 str( portEgress )
kelvin-onlab38143812015-04-01 15:03:01 -07001691 else:
Jon Hall08f61bc2015-04-13 16:00:30 -07001692 main.log.error( "Device list and port list does not " +
1693 "have the same length" )
kelvin-onlab38143812015-04-01 15:03:01 -07001694 return main.FALSE
kelvin-onlabb9408212015-04-01 13:34:04 -07001695 handle = self.sendline( cmd )
Jon Hallc6793552016-01-19 14:18:37 -08001696 assert "Command not found:" not in handle, handle
kelvin-onlabb9408212015-04-01 13:34:04 -07001697 # If error, return error message
1698 if re.search( "Error", handle ):
1699 main.log.error( "Error in adding singlepoint-to-multipoint " +
1700 "intent" )
shahshreyac2f97072015-03-19 17:04:29 -07001701 return None
kelvin-onlabb9408212015-04-01 13:34:04 -07001702 else:
1703 match = re.search('id=0x([\da-f]+),', handle)
1704 if match:
1705 return match.group()[3:-1]
1706 else:
1707 main.log.error( "Error, intent ID not found" )
1708 return None
Jon Hallc6793552016-01-19 14:18:37 -08001709 except AssertionError:
1710 main.log.exception( "" )
1711 return None
Jon Halld4d4b372015-01-28 16:02:41 -08001712 except TypeError:
1713 main.log.exception( self.name + ": Object not as expected" )
1714 return None
shahshreyad0c80432014-12-04 16:56:05 -08001715 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08001716 main.log.error( self.name + ": EOF exception found" )
1717 main.log.error( self.name + ": " + self.handle.before )
shahshreyad0c80432014-12-04 16:56:05 -08001718 main.cleanup()
1719 main.exit()
Jon Hallfebb1c72015-03-05 13:30:09 -08001720 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -08001721 main.log.exception( self.name + ": Uncaught exception!" )
shahshreyad0c80432014-12-04 16:56:05 -08001722 main.cleanup()
1723 main.exit()
1724
Hari Krishna9e232602015-04-13 17:29:08 -07001725 def addMplsIntent(
1726 self,
1727 ingressDevice,
1728 egressDevice,
Hari Krishna87a17f12015-04-13 17:42:23 -07001729 ingressPort="",
1730 egressPort="",
Hari Krishna9e232602015-04-13 17:29:08 -07001731 ethType="",
1732 ethSrc="",
1733 ethDst="",
1734 bandwidth="",
1735 lambdaAlloc=False,
1736 ipProto="",
1737 ipSrc="",
1738 ipDst="",
1739 tcpSrc="",
1740 tcpDst="",
Hari Krishna87a17f12015-04-13 17:42:23 -07001741 ingressLabel="",
Hari Krishnadfff6672015-04-13 17:53:27 -07001742 egressLabel="",
Hari Krishna9e232602015-04-13 17:29:08 -07001743 priority=""):
1744 """
1745 Required:
1746 * ingressDevice: device id of ingress device
1747 * egressDevice: device id of egress device
1748 Optional:
1749 * ethType: specify ethType
1750 * ethSrc: specify ethSrc ( i.e. src mac addr )
1751 * ethDst: specify ethDst ( i.e. dst mac addr )
1752 * bandwidth: specify bandwidth capacity of link
1753 * lambdaAlloc: if True, intent will allocate lambda
1754 for the specified intent
1755 * ipProto: specify ip protocol
1756 * ipSrc: specify ip source address
1757 * ipDst: specify ip destination address
1758 * tcpSrc: specify tcp source port
1759 * tcpDst: specify tcp destination port
1760 * ingressLabel: Ingress MPLS label
1761 * egressLabel: Egress MPLS label
1762 Description:
1763 Adds MPLS intent by
1764 specifying device id's and optional fields
1765 Returns:
1766 A string of the intent id or None on error
1767
1768 NOTE: This function may change depending on the
1769 options developers provide for MPLS
1770 intent via cli
1771 """
1772 try:
Jeremy Songsterff553672016-05-12 17:06:23 -07001773 cmd = "add-mpls-intent"
Hari Krishna9e232602015-04-13 17:29:08 -07001774
Jeremy Songsterff553672016-05-12 17:06:23 -07001775 if ethType:
1776 cmd += " --ethType " + str( ethType )
1777 if ethSrc:
1778 cmd += " --ethSrc " + str( ethSrc )
1779 if ethDst:
1780 cmd += " --ethDst " + str( ethDst )
1781 if bandwidth:
1782 cmd += " --bandwidth " + str( bandwidth )
1783 if lambdaAlloc:
1784 cmd += " --lambda "
1785 if ipProto:
1786 cmd += " --ipProto " + str( ipProto )
1787 if ipSrc:
1788 cmd += " --ipSrc " + str( ipSrc )
1789 if ipDst:
1790 cmd += " --ipDst " + str( ipDst )
1791 if tcpSrc:
1792 cmd += " --tcpSrc " + str( tcpSrc )
1793 if tcpDst:
1794 cmd += " --tcpDst " + str( tcpDst )
1795 if ingressLabel:
1796 cmd += " --ingressLabel " + str( ingressLabel )
1797 if egressLabel:
1798 cmd += " --egressLabel " + str( egressLabel )
1799 if priority:
1800 cmd += " --priority " + str( priority )
Hari Krishna9e232602015-04-13 17:29:08 -07001801
1802 # Check whether the user appended the port
1803 # or provided it as an input
1804 if "/" in ingressDevice:
1805 cmd += " " + str( ingressDevice )
1806 else:
Hari Krishna87a17f12015-04-13 17:42:23 -07001807 if not ingressPort:
Hari Krishna9e232602015-04-13 17:29:08 -07001808 main.log.error( "You must specify the ingress port" )
1809 return None
1810
1811 cmd += " " + \
1812 str( ingressDevice ) + "/" +\
Hari Krishna87a17f12015-04-13 17:42:23 -07001813 str( ingressPort ) + " "
Hari Krishna9e232602015-04-13 17:29:08 -07001814
1815 if "/" in egressDevice:
1816 cmd += " " + str( egressDevice )
1817 else:
Hari Krishna87a17f12015-04-13 17:42:23 -07001818 if not egressPort:
Hari Krishna9e232602015-04-13 17:29:08 -07001819 main.log.error( "You must specify the egress port" )
1820 return None
1821
1822 cmd += " " +\
1823 str( egressDevice ) + "/" +\
Hari Krishna87a17f12015-04-13 17:42:23 -07001824 str( egressPort )
Hari Krishna9e232602015-04-13 17:29:08 -07001825
1826 handle = self.sendline( cmd )
Jon Hallc6793552016-01-19 14:18:37 -08001827 assert "Command not found:" not in handle, handle
Hari Krishna9e232602015-04-13 17:29:08 -07001828 # If error, return error message
1829 if re.search( "Error", handle ):
1830 main.log.error( "Error in adding mpls intent" )
1831 return None
1832 else:
1833 # TODO: print out all the options in this message?
1834 main.log.info( "MPLS intent installed between " +
1835 str( ingressDevice ) + " and " +
1836 str( egressDevice ) )
1837 match = re.search('id=0x([\da-f]+),', handle)
1838 if match:
1839 return match.group()[3:-1]
1840 else:
1841 main.log.error( "Error, intent ID not found" )
1842 return None
Jon Hallc6793552016-01-19 14:18:37 -08001843 except AssertionError:
1844 main.log.exception( "" )
1845 return None
Hari Krishna9e232602015-04-13 17:29:08 -07001846 except TypeError:
1847 main.log.exception( self.name + ": Object not as expected" )
1848 return None
1849 except pexpect.EOF:
1850 main.log.error( self.name + ": EOF exception found" )
1851 main.log.error( self.name + ": " + self.handle.before )
1852 main.cleanup()
1853 main.exit()
1854 except Exception:
1855 main.log.exception( self.name + ": Uncaught exception!" )
1856 main.cleanup()
1857 main.exit()
1858
Jon Hallefbd9792015-03-05 16:11:36 -08001859 def removeIntent( self, intentId, app='org.onosproject.cli',
1860 purge=False, sync=False ):
kelvin-onlab898a6c62015-01-16 14:13:53 -08001861 """
shahshreya1c818fc2015-02-26 13:44:08 -08001862 Remove intent for specified application id and intent id
Jon Hall61282e32015-03-19 11:34:11 -07001863 Optional args:-
shahshreya1c818fc2015-02-26 13:44:08 -08001864 -s or --sync: Waits for the removal before returning
Jon Hall61282e32015-03-19 11:34:11 -07001865 -p or --purge: Purge the intent from the store after removal
1866
Jon Halle3f39ff2015-01-13 11:50:53 -08001867 Returns:
Jon Hall6509dbf2016-06-21 17:01:17 -07001868 main.FALSE on error and
Jon Halle3f39ff2015-01-13 11:50:53 -08001869 cli output otherwise
kelvin-onlab898a6c62015-01-16 14:13:53 -08001870 """
andrewonlab9a50dfe2014-10-17 17:22:31 -04001871 try:
Jon Hallc6358dd2015-04-10 12:44:28 -07001872 cmdStr = "remove-intent"
shahshreya1c818fc2015-02-26 13:44:08 -08001873 if purge:
1874 cmdStr += " -p"
1875 if sync:
1876 cmdStr += " -s"
1877
1878 cmdStr += " " + app + " " + str( intentId )
kelvin-onlabd3b64892015-01-20 13:26:24 -08001879 handle = self.sendline( cmdStr )
Jon Hallc6793552016-01-19 14:18:37 -08001880 assert "Command not found:" not in handle, handle
Jon Halle3f39ff2015-01-13 11:50:53 -08001881 if re.search( "Error", handle ):
kelvin-onlab898a6c62015-01-16 14:13:53 -08001882 main.log.error( "Error in removing intent" )
Jon Halle3f39ff2015-01-13 11:50:53 -08001883 return main.FALSE
andrewonlab9a50dfe2014-10-17 17:22:31 -04001884 else:
Jon Halle3f39ff2015-01-13 11:50:53 -08001885 # TODO: Should this be main.TRUE
1886 return handle
Jon Hallc6793552016-01-19 14:18:37 -08001887 except AssertionError:
1888 main.log.exception( "" )
1889 return None
Jon Halld4d4b372015-01-28 16:02:41 -08001890 except TypeError:
1891 main.log.exception( self.name + ": Object not as expected" )
1892 return None
andrewonlab9a50dfe2014-10-17 17:22:31 -04001893 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08001894 main.log.error( self.name + ": EOF exception found" )
1895 main.log.error( self.name + ": " + self.handle.before )
andrewonlab9a50dfe2014-10-17 17:22:31 -04001896 main.cleanup()
1897 main.exit()
Jon Hallfebb1c72015-03-05 13:30:09 -08001898 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -08001899 main.log.exception( self.name + ": Uncaught exception!" )
andrewonlab9a50dfe2014-10-17 17:22:31 -04001900 main.cleanup()
1901 main.exit()
1902
YPZhangfebf7302016-05-24 16:45:56 -07001903 def removeAllIntents( self, purge=False, sync=False, app='org.onosproject.cli', timeout=30 ):
Jeremy42df2e72016-02-23 16:37:46 -08001904 """
1905 Description:
1906 Remove all the intents
1907 Optional args:-
1908 -s or --sync: Waits for the removal before returning
1909 -p or --purge: Purge the intent from the store after removal
1910 Returns:
1911 Returns main.TRUE if all intents are removed, otherwise returns
1912 main.FALSE; Returns None for exception
1913 """
1914 try:
1915 cmdStr = "remove-intent"
1916 if purge:
1917 cmdStr += " -p"
1918 if sync:
1919 cmdStr += " -s"
1920
1921 cmdStr += " " + app
YPZhangfebf7302016-05-24 16:45:56 -07001922 handle = self.sendline( cmdStr, timeout=timeout )
Jeremy42df2e72016-02-23 16:37:46 -08001923 assert "Command not found:" not in handle, handle
1924 if re.search( "Error", handle ):
1925 main.log.error( "Error in removing intent" )
1926 return main.FALSE
1927 else:
1928 return main.TRUE
1929 except AssertionError:
1930 main.log.exception( "" )
1931 return None
1932 except TypeError:
1933 main.log.exception( self.name + ": Object not as expected" )
1934 return None
1935 except pexpect.EOF:
1936 main.log.error( self.name + ": EOF exception found" )
1937 main.log.error( self.name + ": " + self.handle.before )
1938 main.cleanup()
1939 main.exit()
1940 except Exception:
1941 main.log.exception( self.name + ": Uncaught exception!" )
1942 main.cleanup()
1943 main.exit()
1944
Hari Krishnaacabd5a2015-07-01 17:10:19 -07001945 def purgeWithdrawnIntents( self ):
Hari Krishna0ce0e152015-06-23 09:55:29 -07001946 """
1947 Purges all WITHDRAWN Intents
1948 """
1949 try:
1950 cmdStr = "purge-intents"
1951 handle = self.sendline( cmdStr )
Jon Hallc6793552016-01-19 14:18:37 -08001952 assert "Command not found:" not in handle, handle
Hari Krishna0ce0e152015-06-23 09:55:29 -07001953 if re.search( "Error", handle ):
1954 main.log.error( "Error in purging intents" )
1955 return main.FALSE
1956 else:
1957 return main.TRUE
Jon Hallc6793552016-01-19 14:18:37 -08001958 except AssertionError:
1959 main.log.exception( "" )
1960 return None
Hari Krishna0ce0e152015-06-23 09:55:29 -07001961 except TypeError:
1962 main.log.exception( self.name + ": Object not as expected" )
1963 return None
1964 except pexpect.EOF:
1965 main.log.error( self.name + ": EOF exception found" )
1966 main.log.error( self.name + ": " + self.handle.before )
1967 main.cleanup()
1968 main.exit()
1969 except Exception:
1970 main.log.exception( self.name + ": Uncaught exception!" )
1971 main.cleanup()
1972 main.exit()
1973
kelvin-onlabd3b64892015-01-20 13:26:24 -08001974 def routes( self, jsonFormat=False ):
kelvin8ec71442015-01-15 16:57:00 -08001975 """
kelvin-onlab898a6c62015-01-16 14:13:53 -08001976 NOTE: This method should be used after installing application:
1977 onos-app-sdnip
pingping-lin8b306ac2014-11-17 18:13:51 -08001978 Optional:
kelvin-onlabd3b64892015-01-20 13:26:24 -08001979 * jsonFormat: enable output formatting in json
pingping-lin8b306ac2014-11-17 18:13:51 -08001980 Description:
1981 Obtain all routes in the system
kelvin8ec71442015-01-15 16:57:00 -08001982 """
pingping-lin8b306ac2014-11-17 18:13:51 -08001983 try:
Jon Hallc6358dd2015-04-10 12:44:28 -07001984 cmdStr = "routes"
kelvin-onlabd3b64892015-01-20 13:26:24 -08001985 if jsonFormat:
Jon Hallc6358dd2015-04-10 12:44:28 -07001986 cmdStr += " -j"
1987 handle = self.sendline( cmdStr )
Jon Hallc6793552016-01-19 14:18:37 -08001988 assert "Command not found:" not in handle, handle
pingping-lin8b306ac2014-11-17 18:13:51 -08001989 return handle
Jon Hallc6793552016-01-19 14:18:37 -08001990 except AssertionError:
1991 main.log.exception( "" )
1992 return None
Jon Halld4d4b372015-01-28 16:02:41 -08001993 except TypeError:
1994 main.log.exception( self.name + ": Object not as expected" )
1995 return None
pingping-lin8b306ac2014-11-17 18:13:51 -08001996 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08001997 main.log.error( self.name + ": EOF exception found" )
1998 main.log.error( self.name + ": " + self.handle.before )
pingping-lin8b306ac2014-11-17 18:13:51 -08001999 main.cleanup()
2000 main.exit()
Jon Hallfebb1c72015-03-05 13:30:09 -08002001 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -08002002 main.log.exception( self.name + ": Uncaught exception!" )
pingping-lin8b306ac2014-11-17 18:13:51 -08002003 main.cleanup()
2004 main.exit()
2005
pingping-lin54b03372015-08-13 14:43:10 -07002006 def ipv4RouteNumber( self ):
2007 """
2008 NOTE: This method should be used after installing application:
2009 onos-app-sdnip
2010 Description:
2011 Obtain the total IPv4 routes number in the system
2012 """
2013 try:
2014 cmdStr = "routes -s -j"
2015 handle = self.sendline( cmdStr )
Jon Hallc6793552016-01-19 14:18:37 -08002016 assert "Command not found:" not in handle, handle
pingping-lin54b03372015-08-13 14:43:10 -07002017 jsonResult = json.loads( handle )
2018 return jsonResult['totalRoutes4']
Jon Hallc6793552016-01-19 14:18:37 -08002019 except AssertionError:
2020 main.log.exception( "" )
2021 return None
2022 except ( TypeError, ValueError ):
2023 main.log.exception( "{}: Object not as expected: {!r}".format( self.name, handle ) )
pingping-lin54b03372015-08-13 14:43:10 -07002024 return None
2025 except pexpect.EOF:
2026 main.log.error( self.name + ": EOF exception found" )
2027 main.log.error( self.name + ": " + self.handle.before )
2028 main.cleanup()
2029 main.exit()
2030 except Exception:
2031 main.log.exception( self.name + ": Uncaught exception!" )
2032 main.cleanup()
2033 main.exit()
2034
pingping-lin8244a3b2015-09-16 13:36:56 -07002035 def intents( self, jsonFormat = True, summary = False, **intentargs):
kelvin8ec71442015-01-15 16:57:00 -08002036 """
andrewonlabe6745342014-10-17 14:29:13 -04002037 Description:
Jon Hallff566d52016-01-15 14:45:36 -08002038 Obtain intents from the ONOS cli.
2039 Optional:
2040 * jsonFormat: Enable output formatting in json, default to True
2041 * summary: Whether only output the intent summary, defaults to False
2042 * type: Only output a certain type of intent. This options is valid
2043 only when jsonFormat is True and summary is True.
kelvin-onlab898a6c62015-01-16 14:13:53 -08002044 """
andrewonlabe6745342014-10-17 14:29:13 -04002045 try:
Jon Hallc6358dd2015-04-10 12:44:28 -07002046 cmdStr = "intents"
pingping-lin8244a3b2015-09-16 13:36:56 -07002047 if summary:
2048 cmdStr += " -s"
kelvin-onlabd3b64892015-01-20 13:26:24 -08002049 if jsonFormat:
Jon Hallc6358dd2015-04-10 12:44:28 -07002050 cmdStr += " -j"
2051 handle = self.sendline( cmdStr )
Jon Hallc6793552016-01-19 14:18:37 -08002052 assert "Command not found:" not in handle, handle
pingping-lin8244a3b2015-09-16 13:36:56 -07002053 args = utilities.parse_args( [ "TYPE" ], **intentargs )
acsmars5b5fbaf2015-09-18 10:38:20 -07002054 if "TYPE" in args.keys():
Jon Hallff566d52016-01-15 14:45:36 -08002055 intentType = args[ "TYPE" ]
acsmars5b5fbaf2015-09-18 10:38:20 -07002056 else:
Jon Hallff566d52016-01-15 14:45:36 -08002057 intentType = ""
2058 # IF we want the summary of a specific intent type
2059 if jsonFormat and summary and ( intentType != "" ):
pingping-lin8244a3b2015-09-16 13:36:56 -07002060 jsonResult = json.loads( handle )
Jon Hallff566d52016-01-15 14:45:36 -08002061 if intentType in jsonResult.keys():
2062 return jsonResult[ intentType ]
pingping-lin8244a3b2015-09-16 13:36:56 -07002063 else:
Jon Hallff566d52016-01-15 14:45:36 -08002064 main.log.error( "unknown TYPE, returning all types of intents" )
pingping-lin8244a3b2015-09-16 13:36:56 -07002065 return handle
2066 else:
2067 return handle
Jon Hallc6793552016-01-19 14:18:37 -08002068 except AssertionError:
2069 main.log.exception( "" )
2070 return None
2071 except ( TypeError, ValueError ):
2072 main.log.exception( "{}: Object not as expected: {!r}".format( self.name, handle ) )
pingping-lin54b03372015-08-13 14:43:10 -07002073 return None
2074 except pexpect.EOF:
2075 main.log.error( self.name + ": EOF exception found" )
2076 main.log.error( self.name + ": " + self.handle.before )
2077 main.cleanup()
2078 main.exit()
2079 except Exception:
2080 main.log.exception( self.name + ": Uncaught exception!" )
2081 main.cleanup()
2082 main.exit()
2083
kelvin-onlab54400a92015-02-26 18:05:51 -08002084 def getIntentState(self, intentsId, intentsJson=None):
2085 """
You Wangfdcbfc42016-05-16 12:16:53 -07002086 Description:
2087 Gets intent state. Accepts a single intent ID (string type) or a
2088 list of intent IDs.
2089 Parameters:
2090 intentsId: intent ID, both string type and list type are acceptable
kelvin-onlab54400a92015-02-26 18:05:51 -08002091 intentsJson: parsed json object from the onos:intents api
You Wangfdcbfc42016-05-16 12:16:53 -07002092 Returns:
2093 Returns the state (string type) of the ID if a single intent ID is
2094 accepted.
2095 Returns a list of dictionaries if a list of intent IDs is accepted,
2096 and each dictionary maps 'id' to the Intent ID and 'state' to
2097 corresponding intent state.
kelvin-onlab54400a92015-02-26 18:05:51 -08002098 """
kelvin-onlab54400a92015-02-26 18:05:51 -08002099 try:
2100 state = "State is Undefined"
2101 if not intentsJson:
Jon Hallc6793552016-01-19 14:18:37 -08002102 rawJson = self.intents()
kelvin-onlab54400a92015-02-26 18:05:51 -08002103 else:
Jon Hallc6793552016-01-19 14:18:37 -08002104 rawJson = intentsJson
2105 parsedIntentsJson = json.loads( rawJson )
Jon Hallefbd9792015-03-05 16:11:36 -08002106 if isinstance( intentsId, types.StringType ):
Jon Hallc6793552016-01-19 14:18:37 -08002107 for intent in parsedIntentsJson:
kelvin-onlabc2dcd3f2015-04-09 16:40:02 -07002108 if intentsId == intent[ 'id' ]:
2109 state = intent[ 'state' ]
kelvin-onlab54400a92015-02-26 18:05:51 -08002110 return state
Jon Hallefbd9792015-03-05 16:11:36 -08002111 main.log.info( "Cannot find intent ID" + str( intentsId ) +
2112 " on the list" )
kelvin-onlab54400a92015-02-26 18:05:51 -08002113 return state
Jon Hallefbd9792015-03-05 16:11:36 -08002114 elif isinstance( intentsId, types.ListType ):
kelvin-onlab07dbd012015-03-04 16:29:39 -08002115 dictList = []
kelvin-onlabc2dcd3f2015-04-09 16:40:02 -07002116 for i in xrange( len( intentsId ) ):
kelvin-onlab07dbd012015-03-04 16:29:39 -08002117 stateDict = {}
Jon Hallc6793552016-01-19 14:18:37 -08002118 for intents in parsedIntentsJson:
kelvin-onlabc2dcd3f2015-04-09 16:40:02 -07002119 if intentsId[ i ] == intents[ 'id' ]:
2120 stateDict[ 'state' ] = intents[ 'state' ]
2121 stateDict[ 'id' ] = intentsId[ i ]
Jon Hallefbd9792015-03-05 16:11:36 -08002122 dictList.append( stateDict )
kelvin-onlab54400a92015-02-26 18:05:51 -08002123 break
Jon Hallefbd9792015-03-05 16:11:36 -08002124 if len( intentsId ) != len( dictList ):
2125 main.log.info( "Cannot find some of the intent ID state" )
kelvin-onlab07dbd012015-03-04 16:29:39 -08002126 return dictList
kelvin-onlab54400a92015-02-26 18:05:51 -08002127 else:
kelvin-onlabc2dcd3f2015-04-09 16:40:02 -07002128 main.log.info( "Invalid intents ID entry" )
kelvin-onlab54400a92015-02-26 18:05:51 -08002129 return None
Jon Hallc6793552016-01-19 14:18:37 -08002130 except ( TypeError, ValueError ):
2131 main.log.exception( "{}: Object not as expected: {!r}".format( self.name, rawJson ) )
kelvin-onlab54400a92015-02-26 18:05:51 -08002132 return None
2133 except pexpect.EOF:
2134 main.log.error( self.name + ": EOF exception found" )
2135 main.log.error( self.name + ": " + self.handle.before )
2136 main.cleanup()
2137 main.exit()
Jon Hallfebb1c72015-03-05 13:30:09 -08002138 except Exception:
kelvin-onlab54400a92015-02-26 18:05:51 -08002139 main.log.exception( self.name + ": Uncaught exception!" )
andrewonlabe6745342014-10-17 14:29:13 -04002140 main.cleanup()
2141 main.exit()
Jon Hall390696c2015-05-05 17:13:41 -07002142
kelvin-onlabf512e942015-06-08 19:42:59 -07002143 def checkIntentState( self, intentsId, expectedState='INSTALLED' ):
kelvin-onlabc2dcd3f2015-04-09 16:40:02 -07002144 """
2145 Description:
2146 Check intents state
2147 Required:
2148 intentsId - List of intents ID to be checked
2149 Optional:
kelvin-onlabf512e942015-06-08 19:42:59 -07002150 expectedState - Check the expected state(s) of each intents
2151 state in the list.
2152 *NOTE: You can pass in a list of expected state,
2153 Eg: expectedState = [ 'INSTALLED' , 'INSTALLING' ]
kelvin-onlabc2dcd3f2015-04-09 16:40:02 -07002154 Return:
kelvin-onlabf512e942015-06-08 19:42:59 -07002155 Returns main.TRUE only if all intent are the same as expected states
2156 , otherwise, returns main.FALSE.
kelvin-onlabc2dcd3f2015-04-09 16:40:02 -07002157 """
2158 try:
2159 # Generating a dictionary: intent id as a key and state as value
kelvin-onlabf512e942015-06-08 19:42:59 -07002160 returnValue = main.TRUE
kelvin-onlabc2dcd3f2015-04-09 16:40:02 -07002161 intentsDict = self.getIntentState( intentsId )
kelvin-onlabc2dcd3f2015-04-09 16:40:02 -07002162 if len( intentsId ) != len( intentsDict ):
Jon Hallae04e622016-01-27 10:38:05 -08002163 main.log.info( self.name + ": There is something wrong " +
kelvin-onlabc2dcd3f2015-04-09 16:40:02 -07002164 "getting intents state" )
2165 return main.FALSE
kelvin-onlabf512e942015-06-08 19:42:59 -07002166
2167 if isinstance( expectedState, types.StringType ):
2168 for intents in intentsDict:
2169 if intents.get( 'state' ) != expectedState:
kelvin-onlaba297c4d2015-06-01 13:53:55 -07002170 main.log.debug( self.name + " : Intent ID - " +
2171 intents.get( 'id' ) +
kelvin-onlabf512e942015-06-08 19:42:59 -07002172 " actual state = " +
2173 intents.get( 'state' )
2174 + " does not equal expected state = "
2175 + expectedState )
kelvin-onlaba297c4d2015-06-01 13:53:55 -07002176 returnValue = main.FALSE
kelvin-onlabf512e942015-06-08 19:42:59 -07002177
2178 elif isinstance( expectedState, types.ListType ):
2179 for intents in intentsDict:
2180 if not any( state == intents.get( 'state' ) for state in
2181 expectedState ):
2182 main.log.debug( self.name + " : Intent ID - " +
2183 intents.get( 'id' ) +
2184 " actual state = " +
2185 intents.get( 'state' ) +
2186 " does not equal expected states = "
2187 + str( expectedState ) )
2188 returnValue = main.FALSE
2189
kelvin-onlabc2dcd3f2015-04-09 16:40:02 -07002190 if returnValue == main.TRUE:
2191 main.log.info( self.name + ": All " +
2192 str( len( intentsDict ) ) +
kelvin-onlabf512e942015-06-08 19:42:59 -07002193 " intents are in " + str( expectedState ) +
2194 " state" )
kelvin-onlabc2dcd3f2015-04-09 16:40:02 -07002195 return returnValue
2196 except TypeError:
2197 main.log.exception( self.name + ": Object not as expected" )
2198 return None
2199 except pexpect.EOF:
2200 main.log.error( self.name + ": EOF exception found" )
2201 main.log.error( self.name + ": " + self.handle.before )
2202 main.cleanup()
2203 main.exit()
2204 except Exception:
2205 main.log.exception( self.name + ": Uncaught exception!" )
2206 main.cleanup()
2207 main.exit()
andrewonlabe6745342014-10-17 14:29:13 -04002208
You Wang66518af2016-05-16 15:32:59 -07002209 def compareIntent( self, intentDict ):
2210 """
2211 Description:
2212 Compare the intent ids and states provided in the argument with all intents in ONOS
2213 Return:
2214 Returns main.TRUE if the two sets of intents match exactly, otherwise main.FALSE
2215 Arguments:
2216 intentDict: a dictionary which maps intent ids to intent states
2217 """
2218 try:
2219 intentsRaw = self.intents()
2220 intentsJson = json.loads( intentsRaw )
2221 intentDictONOS = {}
2222 for intent in intentsJson:
2223 intentDictONOS[ intent[ 'id' ] ] = intent[ 'state' ]
You Wang58d04452016-09-21 15:13:05 -07002224 returnValue = main.TRUE
You Wang66518af2016-05-16 15:32:59 -07002225 if len( intentDict ) != len( intentDictONOS ):
You Wang58d04452016-09-21 15:13:05 -07002226 main.log.warn( self.name + ": expected intent count does not match that in ONOS, " +
You Wang66518af2016-05-16 15:32:59 -07002227 str( len( intentDict ) ) + " expected and " +
2228 str( len( intentDictONOS ) ) + " actual" )
You Wang58d04452016-09-21 15:13:05 -07002229 returnValue = main.FALSE
You Wang66518af2016-05-16 15:32:59 -07002230 for intentID in intentDict.keys():
2231 if not intentID in intentDictONOS.keys():
2232 main.log.debug( self.name + ": intent ID - " + intentID + " is not in ONOS" )
2233 returnValue = main.FALSE
You Wang58d04452016-09-21 15:13:05 -07002234 else:
2235 if intentDict[ intentID ] != intentDictONOS[ intentID ]:
2236 main.log.debug( self.name + ": intent ID - " + intentID +
2237 " expected state is " + intentDict[ intentID ] +
2238 " but actual state is " + intentDictONOS[ intentID ] )
2239 returnValue = main.FALSE
2240 intentDictONOS.pop( intentID )
2241 if len( intentDictONOS ) > 0:
2242 returnValue = main.FALSE
2243 for intentID in intentDictONOS.keys():
2244 main.log.debug( self.name + ": find extra intent in ONOS: intent ID " + intentID )
You Wang66518af2016-05-16 15:32:59 -07002245 if returnValue == main.TRUE:
2246 main.log.info( self.name + ": all intent IDs and states match that in ONOS" )
2247 return returnValue
You Wang1be9a512016-05-26 16:54:17 -07002248 except KeyError:
2249 main.log.exception( self.name + ": KeyError exception found" )
2250 return main.ERROR
You Wang66518af2016-05-16 15:32:59 -07002251 except ( TypeError, ValueError ):
2252 main.log.exception( "{}: Object not as expected: {!r}".format( self.name, intentsRaw ) )
You Wang85560372016-05-18 10:44:33 -07002253 return main.ERROR
You Wang66518af2016-05-16 15:32:59 -07002254 except pexpect.EOF:
2255 main.log.error( self.name + ": EOF exception found" )
2256 main.log.error( self.name + ": " + self.handle.before )
2257 main.cleanup()
2258 main.exit()
2259 except Exception:
2260 main.log.exception( self.name + ": Uncaught exception!" )
2261 main.cleanup()
2262 main.exit()
2263
YPZhang14a4aa92016-07-15 13:37:15 -07002264 def checkIntentSummary( self, timeout=60, noExit=True ):
GlennRCed771242016-01-13 17:02:47 -08002265 """
2266 Description:
2267 Check the number of installed intents.
2268 Optional:
2269 timeout - the timeout for pexcept
YPZhang14a4aa92016-07-15 13:37:15 -07002270 noExit - If noExit, TestON will not exit if any except.
GlennRCed771242016-01-13 17:02:47 -08002271 Return:
2272 Returns main.TRUE only if the number of all installed intents are the same as total intents number
2273 , otherwise, returns main.FALSE.
2274 """
2275
2276 try:
2277 cmd = "intents -s -j"
2278
2279 # Check response if something wrong
YPZhang14a4aa92016-07-15 13:37:15 -07002280 response = self.sendline( cmd, timeout=timeout, noExit=noExit )
GlennRCed771242016-01-13 17:02:47 -08002281 if response == None:
YPZhang0584d432016-06-21 15:20:13 -07002282 return main.FALSE
GlennRCed771242016-01-13 17:02:47 -08002283 response = json.loads( response )
2284
2285 # get total and installed number, see if they are match
2286 allState = response.get( 'all' )
2287 if allState.get('total') == allState.get('installed'):
YPZhangb5d3f832016-01-23 22:54:26 -08002288 main.log.info( 'Total Intents: {} Installed Intents: {}'.format( allState.get('total'), allState.get('installed') ) )
GlennRCed771242016-01-13 17:02:47 -08002289 return main.TRUE
YPZhangb5d3f832016-01-23 22:54:26 -08002290 main.log.info( 'Verified Intents failed Excepte intetnes: {} installed intents: {}'.format( allState.get('total'), allState.get('installed') ) )
GlennRCed771242016-01-13 17:02:47 -08002291 return main.FALSE
2292
Jon Hallc6793552016-01-19 14:18:37 -08002293 except ( TypeError, ValueError ):
2294 main.log.exception( "{}: Object not as expected: {!r}".format( self.name, response ) )
GlennRCed771242016-01-13 17:02:47 -08002295 return None
2296 except pexpect.EOF:
2297 main.log.error( self.name + ": EOF exception found" )
2298 main.log.error( self.name + ": " + self.handle.before )
YPZhang14a4aa92016-07-15 13:37:15 -07002299 if noExit:
2300 return main.FALSE
2301 else:
2302 main.cleanup()
2303 main.exit()
GlennRCed771242016-01-13 17:02:47 -08002304 except Exception:
2305 main.log.exception( self.name + ": Uncaught exception!" )
YPZhang14a4aa92016-07-15 13:37:15 -07002306 if noExit:
2307 return main.FALSE
2308 else:
2309 main.cleanup()
2310 main.exit()
YPZhangebf9eb52016-05-12 15:20:24 -07002311 except pexpect.TIMEOUT:
2312 main.log.error( self.name + ": ONOS timeout" )
2313 return None
GlennRCed771242016-01-13 17:02:47 -08002314
Jeremy Songster306ed7a2016-07-19 10:59:07 -07002315 def flows( self, state="", jsonFormat=True, timeout=60, noExit=False, noCore=False ):
kelvin8ec71442015-01-15 16:57:00 -08002316 """
Shreya Shah0f01c812014-10-26 20:15:28 -04002317 Optional:
kelvin-onlabd3b64892015-01-20 13:26:24 -08002318 * jsonFormat: enable output formatting in json
Jeremy Songster306ed7a2016-07-19 10:59:07 -07002319 * noCore: suppress core flows
Shreya Shah0f01c812014-10-26 20:15:28 -04002320 Description:
Jon Halle3f39ff2015-01-13 11:50:53 -08002321 Obtain flows currently installed
kelvin-onlab898a6c62015-01-16 14:13:53 -08002322 """
Shreya Shah0f01c812014-10-26 20:15:28 -04002323 try:
Jon Hallc6358dd2015-04-10 12:44:28 -07002324 cmdStr = "flows"
kelvin-onlabd3b64892015-01-20 13:26:24 -08002325 if jsonFormat:
GlennRCed771242016-01-13 17:02:47 -08002326 cmdStr += " -j "
Jeremy Songster306ed7a2016-07-19 10:59:07 -07002327 if noCore:
2328 cmdStr += " -n "
GlennRCed771242016-01-13 17:02:47 -08002329 cmdStr += state
YPZhangebf9eb52016-05-12 15:20:24 -07002330 handle = self.sendline( cmdStr, timeout=timeout, noExit=noExit )
Jon Hallc6793552016-01-19 14:18:37 -08002331 assert "Command not found:" not in handle, handle
2332 if re.search( "Error:", handle ):
2333 main.log.error( self.name + ": flows() response: " +
2334 str( handle ) )
2335 return handle
2336 except AssertionError:
2337 main.log.exception( "" )
GlennRCed771242016-01-13 17:02:47 -08002338 return None
Jon Halld4d4b372015-01-28 16:02:41 -08002339 except TypeError:
2340 main.log.exception( self.name + ": Object not as expected" )
2341 return None
Jon Hallc6793552016-01-19 14:18:37 -08002342 except pexpect.TIMEOUT:
2343 main.log.error( self.name + ": ONOS timeout" )
2344 return None
Shreya Shah0f01c812014-10-26 20:15:28 -04002345 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08002346 main.log.error( self.name + ": EOF exception found" )
2347 main.log.error( self.name + ": " + self.handle.before )
Shreya Shah0f01c812014-10-26 20:15:28 -04002348 main.cleanup()
2349 main.exit()
Jon Hallfebb1c72015-03-05 13:30:09 -08002350 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -08002351 main.log.exception( self.name + ": Uncaught exception!" )
Shreya Shah0f01c812014-10-26 20:15:28 -04002352 main.cleanup()
2353 main.exit()
2354
Flavio Castrod2ffffa2016-04-26 15:56:56 -07002355 def checkFlowCount(self, min=0, timeout=60 ):
Flavio Castroa1286fe2016-07-25 14:48:51 -07002356 count = self.getTotalFlowsNum( timeout=timeout )
2357 count = int (count) if count else 0
Flavio Castrod2ffffa2016-04-26 15:56:56 -07002358 return count if (count > min) else False
GlennRCed771242016-01-13 17:02:47 -08002359
YPZhangebf9eb52016-05-12 15:20:24 -07002360 def checkFlowsState( self, isPENDING=True, timeout=60,noExit=False ):
kelvin-onlab4df89f22015-04-13 18:10:23 -07002361 """
2362 Description:
GlennRCed771242016-01-13 17:02:47 -08002363 Check the if all the current flows are in ADDED state
Jon Hallc6793552016-01-19 14:18:37 -08002364 We check PENDING_ADD, PENDING_REMOVE, REMOVED, and FAILED flows,
2365 if the count of those states is 0, which means all current flows
2366 are in ADDED state, and return main.TRUE otherwise return main.FALSE
pingping-linbab7f8a2015-09-21 17:33:36 -07002367 Optional:
GlennRCed771242016-01-13 17:02:47 -08002368 * isPENDING: whether the PENDING_ADD is also a correct status
kelvin-onlab4df89f22015-04-13 18:10:23 -07002369 Return:
2370 returnValue - Returns main.TRUE only if all flows are in
Jon Hallc6793552016-01-19 14:18:37 -08002371 ADDED state or PENDING_ADD if the isPENDING
pingping-linbab7f8a2015-09-21 17:33:36 -07002372 parameter is set true, return main.FALSE otherwise.
kelvin-onlab4df89f22015-04-13 18:10:23 -07002373 """
2374 try:
GlennRCed771242016-01-13 17:02:47 -08002375 states = ["PENDING_ADD", "PENDING_REMOVE", "REMOVED", "FAILED"]
2376 checkedStates = []
2377 statesCount = [0, 0, 0, 0]
2378 for s in states:
Jon Hallc6793552016-01-19 14:18:37 -08002379 rawFlows = self.flows( state=s, timeout = timeout )
YPZhang240842b2016-05-17 12:00:50 -07002380 if rawFlows:
2381 # if we didn't get flows or flows function return None, we should return
2382 # main.Flase
2383 checkedStates.append( json.loads( rawFlows ) )
2384 else:
2385 return main.FALSE
Jon Hallc6793552016-01-19 14:18:37 -08002386 for i in range( len( states ) ):
GlennRCed771242016-01-13 17:02:47 -08002387 for c in checkedStates[i]:
Jon Hallc6793552016-01-19 14:18:37 -08002388 try:
2389 statesCount[i] += int( c.get( "flowCount" ) )
2390 except TypeError:
2391 main.log.exception( "Json object not as expected" )
2392 main.log.info( states[i] + " flows: " + str( statesCount[i] ) )
kelvin-onlabf2ec6e02015-05-27 14:15:28 -07002393
GlennRCed771242016-01-13 17:02:47 -08002394 # We want to count PENDING_ADD if isPENDING is true
2395 if isPENDING:
2396 if statesCount[1] + statesCount[2] + statesCount[3] > 0:
2397 return main.FALSE
pingping-linbab7f8a2015-09-21 17:33:36 -07002398 else:
GlennRCed771242016-01-13 17:02:47 -08002399 if statesCount[0] + statesCount[1] + statesCount[2] + statesCount[3] > 0:
2400 return main.FALSE
GlennRCed771242016-01-13 17:02:47 -08002401 return main.TRUE
Jon Hallc6793552016-01-19 14:18:37 -08002402 except ( TypeError, ValueError ):
2403 main.log.exception( "{}: Object not as expected: {!r}".format( self.name, rawFlows ) )
kelvin-onlab4df89f22015-04-13 18:10:23 -07002404 return None
Jeremy Songster9385d412016-06-02 17:57:36 -07002405
YPZhang240842b2016-05-17 12:00:50 -07002406 except AssertionError:
2407 main.log.exception( "" )
2408 return None
kelvin-onlab4df89f22015-04-13 18:10:23 -07002409 except pexpect.EOF:
2410 main.log.error( self.name + ": EOF exception found" )
2411 main.log.error( self.name + ": " + self.handle.before )
2412 main.cleanup()
2413 main.exit()
2414 except Exception:
2415 main.log.exception( self.name + ": Uncaught exception!" )
2416 main.cleanup()
2417 main.exit()
YPZhangebf9eb52016-05-12 15:20:24 -07002418 except pexpect.TIMEOUT:
2419 main.log.error( self.name + ": ONOS timeout" )
2420 return None
2421
kelvin-onlab4df89f22015-04-13 18:10:23 -07002422
GlennRCed771242016-01-13 17:02:47 -08002423 def pushTestIntents( self, ingress, egress, batchSize, offset="",
YPZhangb34b7e12016-06-14 14:28:19 -07002424 options="", timeout=10, background = False, noExit=False, getResponse=False ):
kelvin8ec71442015-01-15 16:57:00 -08002425 """
andrewonlab87852b02014-11-19 18:44:19 -05002426 Description:
Jon Halle3f39ff2015-01-13 11:50:53 -08002427 Push a number of intents in a batch format to
andrewonlab87852b02014-11-19 18:44:19 -05002428 a specific point-to-point intent definition
2429 Required:
GlennRCed771242016-01-13 17:02:47 -08002430 * ingress: specify source dpid
2431 * egress: specify destination dpid
2432 * batchSize: specify number of intents to push
andrewonlab87852b02014-11-19 18:44:19 -05002433 Optional:
GlennRCed771242016-01-13 17:02:47 -08002434 * offset: the keyOffset is where the next batch of intents
2435 will be installed
YPZhangb34b7e12016-06-14 14:28:19 -07002436 * noExit: If set to True, TestON will not exit if any error when issus command
2437 * getResponse: If set to True, function will return ONOS response.
2438
GlennRCed771242016-01-13 17:02:47 -08002439 Returns: If failed to push test intents, it will returen None,
2440 if successful, return true.
2441 Timeout expection will return None,
2442 TypeError will return false
2443 other expections will exit()
kelvin8ec71442015-01-15 16:57:00 -08002444 """
andrewonlab87852b02014-11-19 18:44:19 -05002445 try:
GlennRCed771242016-01-13 17:02:47 -08002446 if background:
2447 back = "&"
andrewonlab87852b02014-11-19 18:44:19 -05002448 else:
GlennRCed771242016-01-13 17:02:47 -08002449 back = ""
2450 cmd = "push-test-intents {} {} {} {} {} {}".format( options,
Jon Hallc6793552016-01-19 14:18:37 -08002451 ingress,
2452 egress,
2453 batchSize,
2454 offset,
2455 back )
YPZhangebf9eb52016-05-12 15:20:24 -07002456 response = self.sendline( cmd, timeout=timeout, noExit=noExit )
Jon Hallc6793552016-01-19 14:18:37 -08002457 assert "Command not found:" not in response, response
GlennRCed771242016-01-13 17:02:47 -08002458 main.log.info( response )
2459 if response == None:
2460 return None
2461
YPZhangb34b7e12016-06-14 14:28:19 -07002462 if getResponse:
2463 return response
2464
GlennRCed771242016-01-13 17:02:47 -08002465 # TODO: We should handle if there is failure in installation
2466 return main.TRUE
2467
Jon Hallc6793552016-01-19 14:18:37 -08002468 except AssertionError:
2469 main.log.exception( "" )
2470 return None
GlennRCed771242016-01-13 17:02:47 -08002471 except pexpect.TIMEOUT:
2472 main.log.error( self.name + ": ONOS timeout" )
Jon Halld4d4b372015-01-28 16:02:41 -08002473 return None
andrewonlab87852b02014-11-19 18:44:19 -05002474 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08002475 main.log.error( self.name + ": EOF exception found" )
2476 main.log.error( self.name + ": " + self.handle.before )
andrewonlab87852b02014-11-19 18:44:19 -05002477 main.cleanup()
2478 main.exit()
GlennRCed771242016-01-13 17:02:47 -08002479 except TypeError:
2480 main.log.exception( self.name + ": Object not as expected" )
Jon Hallc6793552016-01-19 14:18:37 -08002481 return None
Jon Hallfebb1c72015-03-05 13:30:09 -08002482 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -08002483 main.log.exception( self.name + ": Uncaught exception!" )
andrewonlab87852b02014-11-19 18:44:19 -05002484 main.cleanup()
2485 main.exit()
2486
YPZhangebf9eb52016-05-12 15:20:24 -07002487 def getTotalFlowsNum( self, timeout=60, noExit=False ):
YPZhangb5d3f832016-01-23 22:54:26 -08002488 """
2489 Description:
YPZhangf6f14a02016-01-28 15:17:31 -08002490 Get the number of ADDED flows.
YPZhangb5d3f832016-01-23 22:54:26 -08002491 Return:
YPZhangf6f14a02016-01-28 15:17:31 -08002492 The number of ADDED flows
YPZhang14a4aa92016-07-15 13:37:15 -07002493 Or return None if any exceptions
YPZhangb5d3f832016-01-23 22:54:26 -08002494 """
YPZhange3109a72016-02-02 11:25:37 -08002495
YPZhangb5d3f832016-01-23 22:54:26 -08002496 try:
YPZhange3109a72016-02-02 11:25:37 -08002497 # get total added flows number
YPZhang14a4aa92016-07-15 13:37:15 -07002498 cmd = "flows -c added"
2499 rawFlows = self.sendline( cmd, timeout=timeout, noExit=noExit )
2500 if rawFlows:
2501 rawFlows = rawFlows.split("\n")
YPZhange3109a72016-02-02 11:25:37 -08002502 totalFlows = 0
YPZhang14a4aa92016-07-15 13:37:15 -07002503 for l in rawFlows:
2504 totalFlows += int(l.split("Count=")[1])
2505 else:
2506 main.log.error("Response not as expected!")
2507 return None
2508 return totalFlows
YPZhange3109a72016-02-02 11:25:37 -08002509
You Wangd3cb2ce2016-05-16 14:01:24 -07002510 except ( TypeError, ValueError ):
YPZhang14a4aa92016-07-15 13:37:15 -07002511 main.log.exception( "{}: Object not as expected!".format( self.name ) )
YPZhangb5d3f832016-01-23 22:54:26 -08002512 return None
2513 except pexpect.EOF:
2514 main.log.error( self.name + ": EOF exception found" )
2515 main.log.error( self.name + ": " + self.handle.before )
YPZhang14a4aa92016-07-15 13:37:15 -07002516 if not noExit:
2517 main.cleanup()
2518 main.exit()
2519 return None
YPZhangb5d3f832016-01-23 22:54:26 -08002520 except Exception:
2521 main.log.exception( self.name + ": Uncaught exception!" )
YPZhang14a4aa92016-07-15 13:37:15 -07002522 if not noExit:
2523 main.cleanup()
2524 main.exit()
2525 return None
YPZhangebf9eb52016-05-12 15:20:24 -07002526 except pexpect.TIMEOUT:
2527 main.log.error( self.name + ": ONOS timeout" )
2528 return None
YPZhangb5d3f832016-01-23 22:54:26 -08002529
YPZhang14a4aa92016-07-15 13:37:15 -07002530 def getTotalIntentsNum( self, timeout=60, noExit = False ):
YPZhangb5d3f832016-01-23 22:54:26 -08002531 """
2532 Description:
2533 Get the total number of intents, include every states.
YPZhang14a4aa92016-07-15 13:37:15 -07002534 Optional:
2535 noExit - If noExit, TestON will not exit if any except.
YPZhangb5d3f832016-01-23 22:54:26 -08002536 Return:
2537 The number of intents
2538 """
2539 try:
2540 cmd = "summary -j"
YPZhang14a4aa92016-07-15 13:37:15 -07002541 response = self.sendline( cmd, timeout=timeout, noExit=noExit )
YPZhangb5d3f832016-01-23 22:54:26 -08002542 if response == None:
2543 return -1
2544 response = json.loads( response )
2545 return int( response.get("intents") )
You Wangd3cb2ce2016-05-16 14:01:24 -07002546 except ( TypeError, ValueError ):
2547 main.log.exception( "{}: Object not as expected: {!r}".format( self.name, response ) )
YPZhangb5d3f832016-01-23 22:54:26 -08002548 return None
2549 except pexpect.EOF:
2550 main.log.error( self.name + ": EOF exception found" )
2551 main.log.error( self.name + ": " + self.handle.before )
YPZhang14a4aa92016-07-15 13:37:15 -07002552 if noExit:
2553 return -1
2554 else:
2555 main.cleanup()
2556 main.exit()
YPZhangb5d3f832016-01-23 22:54:26 -08002557 except Exception:
2558 main.log.exception( self.name + ": Uncaught exception!" )
YPZhang14a4aa92016-07-15 13:37:15 -07002559 if noExit:
2560 return -1
2561 else:
2562 main.cleanup()
2563 main.exit()
YPZhangb5d3f832016-01-23 22:54:26 -08002564
kelvin-onlabd3b64892015-01-20 13:26:24 -08002565 def intentsEventsMetrics( self, jsonFormat=True ):
kelvin8ec71442015-01-15 16:57:00 -08002566 """
Jon Halle3f39ff2015-01-13 11:50:53 -08002567 Description:Returns topology metrics
andrewonlab0dbb6ec2014-11-06 13:46:55 -05002568 Optional:
kelvin-onlabd3b64892015-01-20 13:26:24 -08002569 * jsonFormat: enable json formatting of output
kelvin8ec71442015-01-15 16:57:00 -08002570 """
andrewonlab0dbb6ec2014-11-06 13:46:55 -05002571 try:
Jon Hallc6358dd2015-04-10 12:44:28 -07002572 cmdStr = "intents-events-metrics"
kelvin-onlabd3b64892015-01-20 13:26:24 -08002573 if jsonFormat:
Jon Hallc6358dd2015-04-10 12:44:28 -07002574 cmdStr += " -j"
2575 handle = self.sendline( cmdStr )
Jon Hallc6793552016-01-19 14:18:37 -08002576 assert "Command not found:" not in handle, handle
andrewonlab0dbb6ec2014-11-06 13:46:55 -05002577 return handle
Jon Hallc6793552016-01-19 14:18:37 -08002578 except AssertionError:
2579 main.log.exception( "" )
2580 return None
Jon Halld4d4b372015-01-28 16:02:41 -08002581 except TypeError:
2582 main.log.exception( self.name + ": Object not as expected" )
2583 return None
andrewonlab0dbb6ec2014-11-06 13:46:55 -05002584 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08002585 main.log.error( self.name + ": EOF exception found" )
2586 main.log.error( self.name + ": " + self.handle.before )
andrewonlab0dbb6ec2014-11-06 13:46:55 -05002587 main.cleanup()
2588 main.exit()
Jon Hallfebb1c72015-03-05 13:30:09 -08002589 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -08002590 main.log.exception( self.name + ": Uncaught exception!" )
andrewonlab0dbb6ec2014-11-06 13:46:55 -05002591 main.cleanup()
2592 main.exit()
Shreya Shah0f01c812014-10-26 20:15:28 -04002593
kelvin-onlabd3b64892015-01-20 13:26:24 -08002594 def topologyEventsMetrics( self, jsonFormat=True ):
kelvin8ec71442015-01-15 16:57:00 -08002595 """
2596 Description:Returns topology metrics
andrewonlab867212a2014-10-22 20:13:38 -04002597 Optional:
kelvin-onlabd3b64892015-01-20 13:26:24 -08002598 * jsonFormat: enable json formatting of output
kelvin8ec71442015-01-15 16:57:00 -08002599 """
andrewonlab867212a2014-10-22 20:13:38 -04002600 try:
Jon Hallc6358dd2015-04-10 12:44:28 -07002601 cmdStr = "topology-events-metrics"
kelvin-onlabd3b64892015-01-20 13:26:24 -08002602 if jsonFormat:
Jon Hallc6358dd2015-04-10 12:44:28 -07002603 cmdStr += " -j"
2604 handle = self.sendline( cmdStr )
Jon Hallc6793552016-01-19 14:18:37 -08002605 assert "Command not found:" not in handle, handle
jenkins7ead5a82015-03-13 10:28:21 -07002606 if handle:
2607 return handle
Jon Hallc6358dd2015-04-10 12:44:28 -07002608 elif jsonFormat:
Jon Hallbe379602015-03-24 13:39:32 -07002609 # Return empty json
jenkins7ead5a82015-03-13 10:28:21 -07002610 return '{}'
Jon Hallc6358dd2015-04-10 12:44:28 -07002611 else:
2612 return handle
Jon Hallc6793552016-01-19 14:18:37 -08002613 except AssertionError:
2614 main.log.exception( "" )
2615 return None
Jon Halld4d4b372015-01-28 16:02:41 -08002616 except TypeError:
2617 main.log.exception( self.name + ": Object not as expected" )
2618 return None
andrewonlab867212a2014-10-22 20:13:38 -04002619 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08002620 main.log.error( self.name + ": EOF exception found" )
2621 main.log.error( self.name + ": " + self.handle.before )
andrewonlab867212a2014-10-22 20:13:38 -04002622 main.cleanup()
2623 main.exit()
Jon Hallfebb1c72015-03-05 13:30:09 -08002624 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -08002625 main.log.exception( self.name + ": Uncaught exception!" )
andrewonlab867212a2014-10-22 20:13:38 -04002626 main.cleanup()
2627 main.exit()
2628
kelvin8ec71442015-01-15 16:57:00 -08002629 # Wrapper functions ****************
2630 # Wrapper functions use existing driver
2631 # functions and extends their use case.
2632 # For example, we may use the output of
2633 # a normal driver function, and parse it
2634 # using a wrapper function
andrewonlabc2d05aa2014-10-13 16:51:10 -04002635
kelvin-onlabd3b64892015-01-20 13:26:24 -08002636 def getAllIntentsId( self ):
kelvin8ec71442015-01-15 16:57:00 -08002637 """
andrewonlab9a50dfe2014-10-17 17:22:31 -04002638 Description:
2639 Obtain all intent id's in a list
kelvin8ec71442015-01-15 16:57:00 -08002640 """
andrewonlab9a50dfe2014-10-17 17:22:31 -04002641 try:
kelvin8ec71442015-01-15 16:57:00 -08002642 # Obtain output of intents function
kelvin-onlabfb521662015-02-27 09:52:40 -08002643 intentsStr = self.intents(jsonFormat=False)
kelvin-onlabd3b64892015-01-20 13:26:24 -08002644 intentIdList = []
andrewonlab9a50dfe2014-10-17 17:22:31 -04002645
kelvin8ec71442015-01-15 16:57:00 -08002646 # Parse the intents output for ID's
kelvin-onlabd3b64892015-01-20 13:26:24 -08002647 intentsList = [ s.strip() for s in intentsStr.splitlines() ]
2648 for intents in intentsList:
kelvin-onlabfb521662015-02-27 09:52:40 -08002649 match = re.search('id=0x([\da-f]+),', intents)
2650 if match:
2651 tmpId = match.group()[3:-1]
2652 intentIdList.append( tmpId )
kelvin-onlabd3b64892015-01-20 13:26:24 -08002653 return intentIdList
andrewonlab9a50dfe2014-10-17 17:22:31 -04002654
Jon Halld4d4b372015-01-28 16:02:41 -08002655 except TypeError:
2656 main.log.exception( self.name + ": Object not as expected" )
2657 return None
andrewonlab9a50dfe2014-10-17 17:22:31 -04002658 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08002659 main.log.error( self.name + ": EOF exception found" )
2660 main.log.error( self.name + ": " + self.handle.before )
andrewonlab9a50dfe2014-10-17 17:22:31 -04002661 main.cleanup()
2662 main.exit()
Jon Hallfebb1c72015-03-05 13:30:09 -08002663 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -08002664 main.log.exception( self.name + ": Uncaught exception!" )
andrewonlab9a50dfe2014-10-17 17:22:31 -04002665 main.cleanup()
2666 main.exit()
2667
You Wang3c276252016-09-21 15:21:36 -07002668 def flowAddedCount( self, deviceId, core=False ):
Jon Hall30b82fa2015-03-04 17:15:43 -08002669 """
2670 Determine the number of flow rules for the given device id that are
2671 in the added state
You Wang3c276252016-09-21 15:21:36 -07002672 Params:
2673 core: if True, only return the number of core flows added
Jon Hall30b82fa2015-03-04 17:15:43 -08002674 """
2675 try:
You Wang3c276252016-09-21 15:21:36 -07002676 if core:
2677 cmdStr = "flows any " + str( deviceId ) + " | " +\
2678 "grep 'state=ADDED' | grep org.onosproject.core | wc -l"
2679 else:
2680 cmdStr = "flows any " + str( deviceId ) + " | " +\
2681 "grep 'state=ADDED' | wc -l"
Jon Hall30b82fa2015-03-04 17:15:43 -08002682 handle = self.sendline( cmdStr )
Jon Hallc6793552016-01-19 14:18:37 -08002683 assert "Command not found:" not in handle, handle
Jon Hall30b82fa2015-03-04 17:15:43 -08002684 return handle
Jon Hallc6793552016-01-19 14:18:37 -08002685 except AssertionError:
2686 main.log.exception( "" )
2687 return None
Jon Hall30b82fa2015-03-04 17:15:43 -08002688 except pexpect.EOF:
2689 main.log.error( self.name + ": EOF exception found" )
2690 main.log.error( self.name + ": " + self.handle.before )
2691 main.cleanup()
2692 main.exit()
Jon Hallfebb1c72015-03-05 13:30:09 -08002693 except Exception:
Jon Hall30b82fa2015-03-04 17:15:43 -08002694 main.log.exception( self.name + ": Uncaught exception!" )
andrewonlab95ce8322014-10-13 14:12:04 -04002695 main.cleanup()
2696 main.exit()
2697
kelvin-onlabd3b64892015-01-20 13:26:24 -08002698 def getAllDevicesId( self ):
kelvin8ec71442015-01-15 16:57:00 -08002699 """
andrewonlab7e4d2d32014-10-15 13:23:21 -04002700 Use 'devices' function to obtain list of all devices
2701 and parse the result to obtain a list of all device
2702 id's. Returns this list. Returns empty list if no
2703 devices exist
kelvin8ec71442015-01-15 16:57:00 -08002704 List is ordered sequentially
2705
andrewonlab3e15ead2014-10-15 14:21:34 -04002706 This function may be useful if you are not sure of the
kelvin8ec71442015-01-15 16:57:00 -08002707 device id, and wish to execute other commands using
andrewonlab3e15ead2014-10-15 14:21:34 -04002708 the ids. By obtaining the list of device ids on the fly,
2709 you can iterate through the list to get mastership, etc.
kelvin8ec71442015-01-15 16:57:00 -08002710 """
andrewonlab7e4d2d32014-10-15 13:23:21 -04002711 try:
kelvin8ec71442015-01-15 16:57:00 -08002712 # Call devices and store result string
kelvin-onlabd3b64892015-01-20 13:26:24 -08002713 devicesStr = self.devices( jsonFormat=False )
2714 idList = []
kelvin8ec71442015-01-15 16:57:00 -08002715
kelvin-onlabd3b64892015-01-20 13:26:24 -08002716 if not devicesStr:
kelvin8ec71442015-01-15 16:57:00 -08002717 main.log.info( "There are no devices to get id from" )
kelvin-onlabd3b64892015-01-20 13:26:24 -08002718 return idList
kelvin8ec71442015-01-15 16:57:00 -08002719
2720 # Split the string into list by comma
kelvin-onlabd3b64892015-01-20 13:26:24 -08002721 deviceList = devicesStr.split( "," )
kelvin8ec71442015-01-15 16:57:00 -08002722 # Get temporary list of all arguments with string 'id='
kelvin-onlabd3b64892015-01-20 13:26:24 -08002723 tempList = [ dev for dev in deviceList if "id=" in dev ]
kelvin8ec71442015-01-15 16:57:00 -08002724 # Split list further into arguments before and after string
2725 # 'id='. Get the latter portion ( the actual device id ) and
kelvin-onlabd3b64892015-01-20 13:26:24 -08002726 # append to idList
2727 for arg in tempList:
2728 idList.append( arg.split( "id=" )[ 1 ] )
2729 return idList
andrewonlab7e4d2d32014-10-15 13:23:21 -04002730
Jon Halld4d4b372015-01-28 16:02:41 -08002731 except TypeError:
2732 main.log.exception( self.name + ": Object not as expected" )
2733 return None
andrewonlab7e4d2d32014-10-15 13:23:21 -04002734 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08002735 main.log.error( self.name + ": EOF exception found" )
2736 main.log.error( self.name + ": " + self.handle.before )
andrewonlab7e4d2d32014-10-15 13:23:21 -04002737 main.cleanup()
2738 main.exit()
Jon Hallfebb1c72015-03-05 13:30:09 -08002739 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -08002740 main.log.exception( self.name + ": Uncaught exception!" )
andrewonlab7e4d2d32014-10-15 13:23:21 -04002741 main.cleanup()
2742 main.exit()
2743
kelvin-onlabd3b64892015-01-20 13:26:24 -08002744 def getAllNodesId( self ):
kelvin8ec71442015-01-15 16:57:00 -08002745 """
andrewonlab7c211572014-10-15 16:45:20 -04002746 Uses 'nodes' function to obtain list of all nodes
2747 and parse the result of nodes to obtain just the
kelvin8ec71442015-01-15 16:57:00 -08002748 node id's.
andrewonlab7c211572014-10-15 16:45:20 -04002749 Returns:
2750 list of node id's
kelvin8ec71442015-01-15 16:57:00 -08002751 """
andrewonlab7c211572014-10-15 16:45:20 -04002752 try:
Jon Hall5aa168b2015-03-23 14:23:09 -07002753 nodesStr = self.nodes( jsonFormat=True )
kelvin-onlabd3b64892015-01-20 13:26:24 -08002754 idList = []
Jon Hall5aa168b2015-03-23 14:23:09 -07002755 # Sample nodesStr output
Jon Hallbd182782016-03-28 16:42:22 -07002756 # id=local, address=127.0.0.1:9876, state=READY *
kelvin-onlabd3b64892015-01-20 13:26:24 -08002757 if not nodesStr:
kelvin8ec71442015-01-15 16:57:00 -08002758 main.log.info( "There are no nodes to get id from" )
kelvin-onlabd3b64892015-01-20 13:26:24 -08002759 return idList
Jon Hall5aa168b2015-03-23 14:23:09 -07002760 nodesJson = json.loads( nodesStr )
2761 idList = [ node.get('id') for node in nodesJson ]
kelvin-onlabd3b64892015-01-20 13:26:24 -08002762 return idList
Jon Hallc6793552016-01-19 14:18:37 -08002763 except ( TypeError, ValueError ):
2764 main.log.exception( "{}: Object not as expected: {!r}".format( self.name, nodesStr ) )
Jon Halld4d4b372015-01-28 16:02:41 -08002765 return None
andrewonlab7c211572014-10-15 16:45:20 -04002766 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08002767 main.log.error( self.name + ": EOF exception found" )
2768 main.log.error( self.name + ": " + self.handle.before )
andrewonlab7c211572014-10-15 16:45:20 -04002769 main.cleanup()
2770 main.exit()
Jon Hallfebb1c72015-03-05 13:30:09 -08002771 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -08002772 main.log.exception( self.name + ": Uncaught exception!" )
andrewonlab7c211572014-10-15 16:45:20 -04002773 main.cleanup()
2774 main.exit()
andrewonlab7e4d2d32014-10-15 13:23:21 -04002775
kelvin-onlabd3b64892015-01-20 13:26:24 -08002776 def getDevice( self, dpid=None ):
kelvin8ec71442015-01-15 16:57:00 -08002777 """
Jon Halla91c4dc2014-10-22 12:57:04 -04002778 Return the first device from the devices api whose 'id' contains 'dpid'
2779 Return None if there is no match
kelvin8ec71442015-01-15 16:57:00 -08002780 """
Jon Halla91c4dc2014-10-22 12:57:04 -04002781 try:
kelvin8ec71442015-01-15 16:57:00 -08002782 if dpid is None:
Jon Halla91c4dc2014-10-22 12:57:04 -04002783 return None
2784 else:
kelvin8ec71442015-01-15 16:57:00 -08002785 dpid = dpid.replace( ':', '' )
kelvin-onlabd3b64892015-01-20 13:26:24 -08002786 rawDevices = self.devices()
2787 devicesJson = json.loads( rawDevices )
kelvin8ec71442015-01-15 16:57:00 -08002788 # search json for the device with dpid then return the device
kelvin-onlabd3b64892015-01-20 13:26:24 -08002789 for device in devicesJson:
kelvin8ec71442015-01-15 16:57:00 -08002790 # print "%s in %s?" % ( dpid, device[ 'id' ] )
2791 if dpid in device[ 'id' ]:
Jon Halla91c4dc2014-10-22 12:57:04 -04002792 return device
2793 return None
Jon Hallc6793552016-01-19 14:18:37 -08002794 except ( TypeError, ValueError ):
2795 main.log.exception( "{}: Object not as expected: {!r}".format( self.name, rawDevices ) )
Jon Halld4d4b372015-01-28 16:02:41 -08002796 return None
Jon Halla91c4dc2014-10-22 12:57:04 -04002797 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08002798 main.log.error( self.name + ": EOF exception found" )
2799 main.log.error( self.name + ": " + self.handle.before )
Jon Halla91c4dc2014-10-22 12:57:04 -04002800 main.cleanup()
2801 main.exit()
Jon Hallfebb1c72015-03-05 13:30:09 -08002802 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -08002803 main.log.exception( self.name + ": Uncaught exception!" )
Jon Halla91c4dc2014-10-22 12:57:04 -04002804 main.cleanup()
2805 main.exit()
2806
You Wang24139872016-05-03 11:48:47 -07002807 def getTopology( self, topologyOutput ):
2808 """
2809 Definition:
2810 Loads a json topology output
2811 Return:
2812 topology = current ONOS topology
2813 """
2814 import json
2815 try:
2816 # either onos:topology or 'topology' will work in CLI
2817 topology = json.loads(topologyOutput)
Jeremy Songsterbc2d8ac2016-05-04 11:25:42 -07002818 main.log.debug( topology )
You Wang24139872016-05-03 11:48:47 -07002819 return topology
You Wangd3cb2ce2016-05-16 14:01:24 -07002820 except ( TypeError, ValueError ):
2821 main.log.exception( "{}: Object not as expected: {!r}".format( self.name, topologyOutput ) )
2822 return None
You Wang24139872016-05-03 11:48:47 -07002823 except pexpect.EOF:
2824 main.log.error( self.name + ": EOF exception found" )
2825 main.log.error( self.name + ": " + self.handle.before )
2826 main.cleanup()
2827 main.exit()
2828 except Exception:
2829 main.log.exception( self.name + ": Uncaught exception!" )
2830 main.cleanup()
2831 main.exit()
2832
Flavio Castro82ee2f62016-06-07 15:04:12 -07002833 def checkStatus(self, numoswitch, numolink, numoctrl = -1, logLevel="info"):
kelvin8ec71442015-01-15 16:57:00 -08002834 """
Jon Hallefbd9792015-03-05 16:11:36 -08002835 Checks the number of switches & links that ONOS sees against the
kelvin8ec71442015-01-15 16:57:00 -08002836 supplied values. By default this will report to main.log, but the
You Wang24139872016-05-03 11:48:47 -07002837 log level can be specific.
kelvin8ec71442015-01-15 16:57:00 -08002838
Flavio Castro82ee2f62016-06-07 15:04:12 -07002839 Params: numoswitch = expected number of switches
Jon Hallefbd9792015-03-05 16:11:36 -08002840 numolink = expected number of links
Flavio Castro82ee2f62016-06-07 15:04:12 -07002841 numoctrl = expected number of controllers
You Wang24139872016-05-03 11:48:47 -07002842 logLevel = level to log to.
2843 Currently accepts 'info', 'warn' and 'report'
Jon Hall42db6dc2014-10-24 19:03:48 -04002844
Jon Hallefbd9792015-03-05 16:11:36 -08002845 Returns: main.TRUE if the number of switches and links are correct,
2846 main.FALSE if the number of switches and links is incorrect,
Jon Hall42db6dc2014-10-24 19:03:48 -04002847 and main.ERROR otherwise
kelvin8ec71442015-01-15 16:57:00 -08002848 """
Flavio Castro82ee2f62016-06-07 15:04:12 -07002849 import json
Jon Hall42db6dc2014-10-24 19:03:48 -04002850 try:
You Wang13310252016-07-31 10:56:14 -07002851 summary = self.summary()
2852 summary = json.loads( summary )
Flavio Castrof5b3f872016-06-23 17:52:31 -07002853 except ( TypeError, ValueError ):
2854 main.log.exception( "{}: Object not as expected: {!r}".format( self.name, summary ) )
2855 return main.ERROR
2856 try:
2857 topology = self.getTopology( self.topology() )
Flavio Castro82ee2f62016-06-07 15:04:12 -07002858 if topology == {} or topology == None or summary == {} or summary == None:
Jon Hall42db6dc2014-10-24 19:03:48 -04002859 return main.ERROR
2860 output = ""
kelvin8ec71442015-01-15 16:57:00 -08002861 # Is the number of switches is what we expected
2862 devices = topology.get( 'devices', False )
2863 links = topology.get( 'links', False )
Flavio Castro82ee2f62016-06-07 15:04:12 -07002864 nodes = summary.get( 'nodes', False )
2865 if devices is False or links is False or nodes is False:
Jon Hall42db6dc2014-10-24 19:03:48 -04002866 return main.ERROR
kelvin-onlabd3b64892015-01-20 13:26:24 -08002867 switchCheck = ( int( devices ) == int( numoswitch ) )
kelvin8ec71442015-01-15 16:57:00 -08002868 # Is the number of links is what we expected
kelvin-onlabd3b64892015-01-20 13:26:24 -08002869 linkCheck = ( int( links ) == int( numolink ) )
Flavio Castro82ee2f62016-06-07 15:04:12 -07002870 nodeCheck = ( int( nodes ) == int( numoctrl ) ) or int( numoctrl ) == -1
2871 if switchCheck and linkCheck and nodeCheck:
kelvin8ec71442015-01-15 16:57:00 -08002872 # We expected the correct numbers
You Wang24139872016-05-03 11:48:47 -07002873 output = output + "The number of links and switches match "\
2874 + "what was expected"
Jon Hall42db6dc2014-10-24 19:03:48 -04002875 result = main.TRUE
2876 else:
You Wang24139872016-05-03 11:48:47 -07002877 output = output + \
2878 "The number of links and switches does not match " + \
2879 "what was expected"
Jon Hall42db6dc2014-10-24 19:03:48 -04002880 result = main.FALSE
You Wang24139872016-05-03 11:48:47 -07002881 output = output + "\n ONOS sees %i devices" % int( devices )
2882 output = output + " (%i expected) " % int( numoswitch )
2883 output = output + "and %i links " % int( links )
2884 output = output + "(%i expected)" % int( numolink )
YPZhangd7e4b6e2016-06-17 16:07:55 -07002885 if int( numoctrl ) > 0:
Flavio Castro82ee2f62016-06-07 15:04:12 -07002886 output = output + "and %i controllers " % int( nodes )
2887 output = output + "(%i expected)" % int( numoctrl )
kelvin-onlabd3b64892015-01-20 13:26:24 -08002888 if logLevel == "report":
kelvin8ec71442015-01-15 16:57:00 -08002889 main.log.report( output )
kelvin-onlabd3b64892015-01-20 13:26:24 -08002890 elif logLevel == "warn":
kelvin8ec71442015-01-15 16:57:00 -08002891 main.log.warn( output )
Jon Hall42db6dc2014-10-24 19:03:48 -04002892 else:
You Wang24139872016-05-03 11:48:47 -07002893 main.log.info( output )
kelvin8ec71442015-01-15 16:57:00 -08002894 return result
Jon Hall42db6dc2014-10-24 19:03:48 -04002895 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08002896 main.log.error( self.name + ": EOF exception found" )
2897 main.log.error( self.name + ": " + self.handle.before )
Jon Hall42db6dc2014-10-24 19:03:48 -04002898 main.cleanup()
2899 main.exit()
Jon Hallfebb1c72015-03-05 13:30:09 -08002900 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -08002901 main.log.exception( self.name + ": Uncaught exception!" )
Jon Hall42db6dc2014-10-24 19:03:48 -04002902 main.cleanup()
2903 main.exit()
Jon Hall1c9e8732014-10-27 19:29:27 -04002904
kelvin-onlabd3b64892015-01-20 13:26:24 -08002905 def deviceRole( self, deviceId, onosNode, role="master" ):
kelvin8ec71442015-01-15 16:57:00 -08002906 """
Jon Hall1c9e8732014-10-27 19:29:27 -04002907 Calls the device-role cli command.
kelvin-onlabd3b64892015-01-20 13:26:24 -08002908 deviceId must be the id of a device as seen in the onos devices command
2909 onosNode is the ip of one of the onos nodes in the cluster
Jon Hall1c9e8732014-10-27 19:29:27 -04002910 role must be either master, standby, or none
2911
Jon Halle3f39ff2015-01-13 11:50:53 -08002912 Returns:
2913 main.TRUE or main.FALSE based on argument verification and
2914 main.ERROR if command returns and error
kelvin-onlab898a6c62015-01-16 14:13:53 -08002915 """
Jon Hall1c9e8732014-10-27 19:29:27 -04002916 try:
Jon Halle3f39ff2015-01-13 11:50:53 -08002917 if role.lower() == "master" or role.lower() == "standby" or\
Jon Hall1c9e8732014-10-27 19:29:27 -04002918 role.lower() == "none":
kelvin-onlabd3b64892015-01-20 13:26:24 -08002919 cmdStr = "device-role " +\
2920 str( deviceId ) + " " +\
2921 str( onosNode ) + " " +\
kelvin-onlab898a6c62015-01-16 14:13:53 -08002922 str( role )
kelvin-onlabd3b64892015-01-20 13:26:24 -08002923 handle = self.sendline( cmdStr )
Jon Hallc6793552016-01-19 14:18:37 -08002924 assert "Command not found:" not in handle, handle
kelvin-onlab898a6c62015-01-16 14:13:53 -08002925 if re.search( "Error", handle ):
2926 # end color output to escape any colours
2927 # from the cli
kelvin8ec71442015-01-15 16:57:00 -08002928 main.log.error( self.name + ": " +
kelvin-onlab898a6c62015-01-16 14:13:53 -08002929 handle + '\033[0m' )
kelvin8ec71442015-01-15 16:57:00 -08002930 return main.ERROR
kelvin8ec71442015-01-15 16:57:00 -08002931 return main.TRUE
Jon Hall1c9e8732014-10-27 19:29:27 -04002932 else:
kelvin-onlab898a6c62015-01-16 14:13:53 -08002933 main.log.error( "Invalid 'role' given to device_role(). " +
2934 "Value was '" + str(role) + "'." )
Jon Hall1c9e8732014-10-27 19:29:27 -04002935 return main.FALSE
Jon Hallc6793552016-01-19 14:18:37 -08002936 except AssertionError:
2937 main.log.exception( "" )
2938 return None
Jon Halld4d4b372015-01-28 16:02:41 -08002939 except TypeError:
2940 main.log.exception( self.name + ": Object not as expected" )
2941 return None
Jon Hall1c9e8732014-10-27 19:29:27 -04002942 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08002943 main.log.error( self.name + ": EOF exception found" )
2944 main.log.error( self.name + ": " + self.handle.before )
Jon Hall1c9e8732014-10-27 19:29:27 -04002945 main.cleanup()
2946 main.exit()
Jon Hallfebb1c72015-03-05 13:30:09 -08002947 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -08002948 main.log.exception( self.name + ": Uncaught exception!" )
Jon Hall1c9e8732014-10-27 19:29:27 -04002949 main.cleanup()
2950 main.exit()
2951
kelvin-onlabd3b64892015-01-20 13:26:24 -08002952 def clusters( self, jsonFormat=True ):
kelvin8ec71442015-01-15 16:57:00 -08002953 """
Jon Hall73cf9cc2014-11-20 22:28:38 -08002954 Lists all clusters
Jon Hallffb386d2014-11-21 13:43:38 -08002955 Optional argument:
kelvin-onlabd3b64892015-01-20 13:26:24 -08002956 * jsonFormat - boolean indicating if you want output in json
kelvin8ec71442015-01-15 16:57:00 -08002957 """
Jon Hall73cf9cc2014-11-20 22:28:38 -08002958 try:
Jon Hallc6358dd2015-04-10 12:44:28 -07002959 cmdStr = "clusters"
kelvin-onlabd3b64892015-01-20 13:26:24 -08002960 if jsonFormat:
Jon Hallc6358dd2015-04-10 12:44:28 -07002961 cmdStr += " -j"
2962 handle = self.sendline( cmdStr )
Jon Hallc6793552016-01-19 14:18:37 -08002963 assert "Command not found:" not in handle, handle
Jon Hallc6358dd2015-04-10 12:44:28 -07002964 return handle
Jon Hallc6793552016-01-19 14:18:37 -08002965 except AssertionError:
2966 main.log.exception( "" )
2967 return None
Jon Halld4d4b372015-01-28 16:02:41 -08002968 except TypeError:
2969 main.log.exception( self.name + ": Object not as expected" )
2970 return None
Jon Hall73cf9cc2014-11-20 22:28:38 -08002971 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08002972 main.log.error( self.name + ": EOF exception found" )
2973 main.log.error( self.name + ": " + self.handle.before )
Jon Hall73cf9cc2014-11-20 22:28:38 -08002974 main.cleanup()
2975 main.exit()
Jon Hallfebb1c72015-03-05 13:30:09 -08002976 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -08002977 main.log.exception( self.name + ": Uncaught exception!" )
Jon Hall73cf9cc2014-11-20 22:28:38 -08002978 main.cleanup()
2979 main.exit()
2980
kelvin-onlabd3b64892015-01-20 13:26:24 -08002981 def electionTestLeader( self ):
kelvin-onlab898a6c62015-01-16 14:13:53 -08002982 """
Jon Halle3f39ff2015-01-13 11:50:53 -08002983 CLI command to get the current leader for the Election test application
2984 NOTE: Requires installation of the onos-app-election feature
2985 Returns: Node IP of the leader if one exists
2986 None if none exists
2987 Main.FALSE on error
kelvin-onlab898a6c62015-01-16 14:13:53 -08002988 """
Jon Hall94fd0472014-12-08 11:52:42 -08002989 try:
kelvin-onlabd3b64892015-01-20 13:26:24 -08002990 cmdStr = "election-test-leader"
2991 response = self.sendline( cmdStr )
Jon Hallc6793552016-01-19 14:18:37 -08002992 assert "Command not found:" not in response, response
Jon Halle3f39ff2015-01-13 11:50:53 -08002993 # Leader
2994 leaderPattern = "The\scurrent\sleader\sfor\sthe\sElection\s" +\
kelvin-onlab898a6c62015-01-16 14:13:53 -08002995 "app\sis\s(?P<node>.+)\."
kelvin-onlabd3b64892015-01-20 13:26:24 -08002996 nodeSearch = re.search( leaderPattern, response )
2997 if nodeSearch:
2998 node = nodeSearch.group( 'node' )
Jon Halle3f39ff2015-01-13 11:50:53 -08002999 main.log.info( "Election-test-leader on " + str( self.name ) +
kelvin-onlab898a6c62015-01-16 14:13:53 -08003000 " found " + node + " as the leader" )
Jon Hall94fd0472014-12-08 11:52:42 -08003001 return node
Jon Halle3f39ff2015-01-13 11:50:53 -08003002 # no leader
3003 nullPattern = "There\sis\scurrently\sno\sleader\selected\sfor\s" +\
kelvin-onlab898a6c62015-01-16 14:13:53 -08003004 "the\sElection\sapp"
kelvin-onlabd3b64892015-01-20 13:26:24 -08003005 nullSearch = re.search( nullPattern, response )
3006 if nullSearch:
Jon Halle3f39ff2015-01-13 11:50:53 -08003007 main.log.info( "Election-test-leader found no leader on " +
kelvin-onlab898a6c62015-01-16 14:13:53 -08003008 self.name )
Jon Hall94fd0472014-12-08 11:52:42 -08003009 return None
kelvin-onlab898a6c62015-01-16 14:13:53 -08003010 # error
Jon Hall97cf84a2016-06-20 13:35:58 -07003011 main.log.error( "Error in electionTestLeader on " + self.name +
3012 ": " + "unexpected response" )
3013 main.log.error( repr( response ) )
3014 return main.FALSE
Jon Hallc6793552016-01-19 14:18:37 -08003015 except AssertionError:
3016 main.log.exception( "" )
3017 return None
Jon Halld4d4b372015-01-28 16:02:41 -08003018 except TypeError:
3019 main.log.exception( self.name + ": Object not as expected" )
3020 return main.FALSE
Jon Hall94fd0472014-12-08 11:52:42 -08003021 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08003022 main.log.error( self.name + ": EOF exception found" )
3023 main.log.error( self.name + ": " + self.handle.before )
Jon Hall94fd0472014-12-08 11:52:42 -08003024 main.cleanup()
3025 main.exit()
Jon Hallfebb1c72015-03-05 13:30:09 -08003026 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -08003027 main.log.exception( self.name + ": Uncaught exception!" )
Jon Hall94fd0472014-12-08 11:52:42 -08003028 main.cleanup()
3029 main.exit()
3030
kelvin-onlabd3b64892015-01-20 13:26:24 -08003031 def electionTestRun( self ):
kelvin-onlab898a6c62015-01-16 14:13:53 -08003032 """
Jon Halle3f39ff2015-01-13 11:50:53 -08003033 CLI command to run for leadership of the Election test application.
3034 NOTE: Requires installation of the onos-app-election feature
3035 Returns: Main.TRUE on success
3036 Main.FALSE on error
kelvin-onlab898a6c62015-01-16 14:13:53 -08003037 """
Jon Hall94fd0472014-12-08 11:52:42 -08003038 try:
kelvin-onlabd3b64892015-01-20 13:26:24 -08003039 cmdStr = "election-test-run"
3040 response = self.sendline( cmdStr )
Jon Hallc6793552016-01-19 14:18:37 -08003041 assert "Command not found:" not in response, response
kelvin-onlab898a6c62015-01-16 14:13:53 -08003042 # success
Jon Halle3f39ff2015-01-13 11:50:53 -08003043 successPattern = "Entering\sleadership\selections\sfor\sthe\s" +\
kelvin-onlab898a6c62015-01-16 14:13:53 -08003044 "Election\sapp."
Jon Halle3f39ff2015-01-13 11:50:53 -08003045 search = re.search( successPattern, response )
Jon Hall94fd0472014-12-08 11:52:42 -08003046 if search:
Jon Halle3f39ff2015-01-13 11:50:53 -08003047 main.log.info( self.name + " entering leadership elections " +
kelvin-onlab898a6c62015-01-16 14:13:53 -08003048 "for the Election app." )
Jon Hall94fd0472014-12-08 11:52:42 -08003049 return main.TRUE
kelvin-onlab898a6c62015-01-16 14:13:53 -08003050 # error
Jon Hall97cf84a2016-06-20 13:35:58 -07003051 main.log.error( "Error in electionTestRun on " + self.name +
3052 ": " + "unexpected response" )
3053 main.log.error( repr( response ) )
3054 return main.FALSE
Jon Hallc6793552016-01-19 14:18:37 -08003055 except AssertionError:
3056 main.log.exception( "" )
3057 return None
Jon Halld4d4b372015-01-28 16:02:41 -08003058 except TypeError:
3059 main.log.exception( self.name + ": Object not as expected" )
3060 return main.FALSE
Jon Hall94fd0472014-12-08 11:52:42 -08003061 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08003062 main.log.error( self.name + ": EOF exception found" )
3063 main.log.error( self.name + ": " + self.handle.before )
Jon Hall94fd0472014-12-08 11:52:42 -08003064 main.cleanup()
3065 main.exit()
Jon Hallfebb1c72015-03-05 13:30:09 -08003066 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -08003067 main.log.exception( self.name + ": Uncaught exception!" )
Jon Hall94fd0472014-12-08 11:52:42 -08003068 main.cleanup()
3069 main.exit()
3070
kelvin-onlabd3b64892015-01-20 13:26:24 -08003071 def electionTestWithdraw( self ):
kelvin8ec71442015-01-15 16:57:00 -08003072 """
Jon Hall94fd0472014-12-08 11:52:42 -08003073 * CLI command to withdraw the local node from leadership election for
3074 * the Election test application.
3075 #NOTE: Requires installation of the onos-app-election feature
3076 Returns: Main.TRUE on success
3077 Main.FALSE on error
kelvin8ec71442015-01-15 16:57:00 -08003078 """
Jon Hall94fd0472014-12-08 11:52:42 -08003079 try:
kelvin-onlabd3b64892015-01-20 13:26:24 -08003080 cmdStr = "election-test-withdraw"
3081 response = self.sendline( cmdStr )
Jon Hallc6793552016-01-19 14:18:37 -08003082 assert "Command not found:" not in response, response
kelvin-onlab898a6c62015-01-16 14:13:53 -08003083 # success
Jon Halle3f39ff2015-01-13 11:50:53 -08003084 successPattern = "Withdrawing\sfrom\sleadership\selections\sfor" +\
kelvin-onlab898a6c62015-01-16 14:13:53 -08003085 "\sthe\sElection\sapp."
Jon Halle3f39ff2015-01-13 11:50:53 -08003086 if re.search( successPattern, response ):
3087 main.log.info( self.name + " withdrawing from leadership " +
kelvin-onlab898a6c62015-01-16 14:13:53 -08003088 "elections for the Election app." )
Jon Hall94fd0472014-12-08 11:52:42 -08003089 return main.TRUE
kelvin-onlab898a6c62015-01-16 14:13:53 -08003090 # error
Jon Hall97cf84a2016-06-20 13:35:58 -07003091 main.log.error( "Error in electionTestWithdraw on " +
3092 self.name + ": " + "unexpected response" )
3093 main.log.error( repr( response ) )
3094 return main.FALSE
Jon Hallc6793552016-01-19 14:18:37 -08003095 except AssertionError:
3096 main.log.exception( "" )
3097 return None
Jon Halld4d4b372015-01-28 16:02:41 -08003098 except TypeError:
3099 main.log.exception( self.name + ": Object not as expected" )
3100 return main.FALSE
Jon Hall94fd0472014-12-08 11:52:42 -08003101 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08003102 main.log.error( self.name + ": EOF exception found" )
3103 main.log.error( self.name + ": " + self.handle.before )
Jon Hall94fd0472014-12-08 11:52:42 -08003104 main.cleanup()
3105 main.exit()
Jon Hallfebb1c72015-03-05 13:30:09 -08003106 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -08003107 main.log.exception( self.name + ": Uncaught exception!" )
Jon Hall94fd0472014-12-08 11:52:42 -08003108 main.cleanup()
3109 main.exit()
Jon Hall1c9e8732014-10-27 19:29:27 -04003110
kelvin8ec71442015-01-15 16:57:00 -08003111 def getDevicePortsEnabledCount( self, dpid ):
3112 """
Hari Krishnaa43d4e92014-12-19 13:22:40 -08003113 Get the count of all enabled ports on a particular device/switch
kelvin8ec71442015-01-15 16:57:00 -08003114 """
Hari Krishnaa43d4e92014-12-19 13:22:40 -08003115 try:
Jon Halle3f39ff2015-01-13 11:50:53 -08003116 dpid = str( dpid )
kelvin-onlabd3b64892015-01-20 13:26:24 -08003117 cmdStr = "onos:ports -e " + dpid + " | wc -l"
3118 output = self.sendline( cmdStr )
Jon Halla495f562016-05-16 18:03:26 -07003119 assert output is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08003120 assert "Command not found:" not in output, output
Jon Halle3f39ff2015-01-13 11:50:53 -08003121 if re.search( "No such device", output ):
3122 main.log.error( "Error in getting ports" )
3123 return ( output, "Error" )
Jon Halla495f562016-05-16 18:03:26 -07003124 return output
Jon Hallc6793552016-01-19 14:18:37 -08003125 except AssertionError:
3126 main.log.exception( "" )
3127 return None
Jon Halld4d4b372015-01-28 16:02:41 -08003128 except TypeError:
3129 main.log.exception( self.name + ": Object not as expected" )
3130 return ( output, "Error" )
Hari Krishnaa43d4e92014-12-19 13:22:40 -08003131 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08003132 main.log.error( self.name + ": EOF exception found" )
3133 main.log.error( self.name + ": " + self.handle.before )
Hari Krishnaa43d4e92014-12-19 13:22:40 -08003134 main.cleanup()
3135 main.exit()
Jon Hallfebb1c72015-03-05 13:30:09 -08003136 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -08003137 main.log.exception( self.name + ": Uncaught exception!" )
Hari Krishnaa43d4e92014-12-19 13:22:40 -08003138 main.cleanup()
3139 main.exit()
3140
kelvin8ec71442015-01-15 16:57:00 -08003141 def getDeviceLinksActiveCount( self, dpid ):
3142 """
Hari Krishnaa43d4e92014-12-19 13:22:40 -08003143 Get the count of all enabled ports on a particular device/switch
kelvin8ec71442015-01-15 16:57:00 -08003144 """
Hari Krishnaa43d4e92014-12-19 13:22:40 -08003145 try:
kelvin-onlab898a6c62015-01-16 14:13:53 -08003146 dpid = str( dpid )
kelvin-onlabd3b64892015-01-20 13:26:24 -08003147 cmdStr = "onos:links " + dpid + " | grep ACTIVE | wc -l"
3148 output = self.sendline( cmdStr )
Jon Halla495f562016-05-16 18:03:26 -07003149 assert output is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08003150 assert "Command not found:" not in output, output
Jon Halle3f39ff2015-01-13 11:50:53 -08003151 if re.search( "No such device", output ):
kelvin-onlab898a6c62015-01-16 14:13:53 -08003152 main.log.error( "Error in getting ports " )
3153 return ( output, "Error " )
Jon Halla495f562016-05-16 18:03:26 -07003154 return output
Jon Hallc6793552016-01-19 14:18:37 -08003155 except AssertionError:
3156 main.log.exception( "" )
3157 return None
Jon Halld4d4b372015-01-28 16:02:41 -08003158 except TypeError:
3159 main.log.exception( self.name + ": Object not as expected" )
3160 return ( output, "Error " )
Hari Krishnaa43d4e92014-12-19 13:22:40 -08003161 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08003162 main.log.error( self.name + ": EOF exception found" )
3163 main.log.error( self.name + ": " + self.handle.before )
Hari Krishnaa43d4e92014-12-19 13:22:40 -08003164 main.cleanup()
3165 main.exit()
Jon Hallfebb1c72015-03-05 13:30:09 -08003166 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -08003167 main.log.exception( self.name + ": Uncaught exception!" )
Hari Krishnaa43d4e92014-12-19 13:22:40 -08003168 main.cleanup()
3169 main.exit()
3170
kelvin8ec71442015-01-15 16:57:00 -08003171 def getAllIntentIds( self ):
3172 """
Hari Krishnaa43d4e92014-12-19 13:22:40 -08003173 Return a list of all Intent IDs
kelvin8ec71442015-01-15 16:57:00 -08003174 """
Hari Krishnaa43d4e92014-12-19 13:22:40 -08003175 try:
kelvin-onlabd3b64892015-01-20 13:26:24 -08003176 cmdStr = "onos:intents | grep id="
3177 output = self.sendline( cmdStr )
Jon Halla495f562016-05-16 18:03:26 -07003178 assert output is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08003179 assert "Command not found:" not in output, output
Jon Halle3f39ff2015-01-13 11:50:53 -08003180 if re.search( "Error", output ):
3181 main.log.error( "Error in getting ports" )
3182 return ( output, "Error" )
Jon Halla495f562016-05-16 18:03:26 -07003183 return output
Jon Hallc6793552016-01-19 14:18:37 -08003184 except AssertionError:
3185 main.log.exception( "" )
3186 return None
Jon Halld4d4b372015-01-28 16:02:41 -08003187 except TypeError:
3188 main.log.exception( self.name + ": Object not as expected" )
3189 return ( output, "Error" )
Hari Krishnaa43d4e92014-12-19 13:22:40 -08003190 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08003191 main.log.error( self.name + ": EOF exception found" )
3192 main.log.error( self.name + ": " + self.handle.before )
Hari Krishnaa43d4e92014-12-19 13:22:40 -08003193 main.cleanup()
3194 main.exit()
Jon Hallfebb1c72015-03-05 13:30:09 -08003195 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -08003196 main.log.exception( self.name + ": Uncaught exception!" )
3197 main.cleanup()
3198 main.exit()
3199
Jon Hall73509952015-02-24 16:42:56 -08003200 def intentSummary( self ):
3201 """
Jon Hallefbd9792015-03-05 16:11:36 -08003202 Returns a dictionary containing the current intent states and the count
Jon Hall73509952015-02-24 16:42:56 -08003203 """
3204 try:
3205 intents = self.intents( )
Jon Hall08f61bc2015-04-13 16:00:30 -07003206 states = []
Jon Hall5aa168b2015-03-23 14:23:09 -07003207 for intent in json.loads( intents ):
Jon Hall08f61bc2015-04-13 16:00:30 -07003208 states.append( intent.get( 'state', None ) )
3209 out = [ ( i, states.count( i ) ) for i in set( states ) ]
Jon Hall63604932015-02-26 17:09:50 -08003210 main.log.info( dict( out ) )
Jon Hall73509952015-02-24 16:42:56 -08003211 return dict( out )
Jon Hallc6793552016-01-19 14:18:37 -08003212 except ( TypeError, ValueError ):
3213 main.log.exception( "{}: Object not as expected: {!r}".format( self.name, intents ) )
Jon Hall73509952015-02-24 16:42:56 -08003214 return None
3215 except pexpect.EOF:
3216 main.log.error( self.name + ": EOF exception found" )
3217 main.log.error( self.name + ": " + self.handle.before )
3218 main.cleanup()
3219 main.exit()
Jon Hallfebb1c72015-03-05 13:30:09 -08003220 except Exception:
Jon Hall73509952015-02-24 16:42:56 -08003221 main.log.exception( self.name + ": Uncaught exception!" )
3222 main.cleanup()
3223 main.exit()
Jon Hall63604932015-02-26 17:09:50 -08003224
Jon Hall61282e32015-03-19 11:34:11 -07003225 def leaders( self, jsonFormat=True ):
Jon Hall63604932015-02-26 17:09:50 -08003226 """
3227 Returns the output of the leaders command.
Jon Hall61282e32015-03-19 11:34:11 -07003228 Optional argument:
3229 * jsonFormat - boolean indicating if you want output in json
Jon Hall63604932015-02-26 17:09:50 -08003230 """
Jon Hall63604932015-02-26 17:09:50 -08003231 try:
Jon Hallc6358dd2015-04-10 12:44:28 -07003232 cmdStr = "onos:leaders"
Jon Hall61282e32015-03-19 11:34:11 -07003233 if jsonFormat:
Jon Hallc6358dd2015-04-10 12:44:28 -07003234 cmdStr += " -j"
3235 output = self.sendline( cmdStr )
Jon Halla495f562016-05-16 18:03:26 -07003236 assert output is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08003237 assert "Command not found:" not in output, output
Jon Hallc6358dd2015-04-10 12:44:28 -07003238 return output
Jon Hallc6793552016-01-19 14:18:37 -08003239 except AssertionError:
3240 main.log.exception( "" )
3241 return None
Jon Hall63604932015-02-26 17:09:50 -08003242 except TypeError:
3243 main.log.exception( self.name + ": Object not as expected" )
3244 return None
Hari Krishnaa43d4e92014-12-19 13:22:40 -08003245 except pexpect.EOF:
3246 main.log.error( self.name + ": EOF exception found" )
3247 main.log.error( self.name + ": " + self.handle.before )
3248 main.cleanup()
3249 main.exit()
Jon Hall77ba41c2015-04-06 10:25:40 -07003250 except Exception:
Jon Hall63604932015-02-26 17:09:50 -08003251 main.log.exception( self.name + ": Uncaught exception!" )
Hari Krishnaa43d4e92014-12-19 13:22:40 -08003252 main.cleanup()
3253 main.exit()
Jon Hall63604932015-02-26 17:09:50 -08003254
acsmarsa4a4d1e2015-07-10 16:01:24 -07003255 def leaderCandidates( self, jsonFormat=True ):
3256 """
3257 Returns the output of the leaders -c command.
3258 Optional argument:
3259 * jsonFormat - boolean indicating if you want output in json
3260 """
3261 try:
3262 cmdStr = "onos:leaders -c"
3263 if jsonFormat:
3264 cmdStr += " -j"
3265 output = self.sendline( cmdStr )
Jon Halla495f562016-05-16 18:03:26 -07003266 assert output is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08003267 assert "Command not found:" not in output, output
acsmarsa4a4d1e2015-07-10 16:01:24 -07003268 return output
Jon Hallc6793552016-01-19 14:18:37 -08003269 except AssertionError:
3270 main.log.exception( "" )
3271 return None
acsmarsa4a4d1e2015-07-10 16:01:24 -07003272 except TypeError:
3273 main.log.exception( self.name + ": Object not as expected" )
3274 return None
3275 except pexpect.EOF:
3276 main.log.error( self.name + ": EOF exception found" )
3277 main.log.error( self.name + ": " + self.handle.before )
3278 main.cleanup()
3279 main.exit()
3280 except Exception:
3281 main.log.exception( self.name + ": Uncaught exception!" )
3282 main.cleanup()
3283 main.exit()
3284
Jon Hallc6793552016-01-19 14:18:37 -08003285 def specificLeaderCandidate( self, topic ):
acsmarsa4a4d1e2015-07-10 16:01:24 -07003286 """
3287 Returns a list in format [leader,candidate1,candidate2,...] for a given
3288 topic parameter and an empty list if the topic doesn't exist
3289 If no leader is elected leader in the returned list will be "none"
3290 Returns None if there is a type error processing the json object
3291 """
3292 try:
Jon Hall6e709752016-02-01 13:38:46 -08003293 cmdStr = "onos:leaders -j"
Jon Hallc6793552016-01-19 14:18:37 -08003294 rawOutput = self.sendline( cmdStr )
Jon Halla495f562016-05-16 18:03:26 -07003295 assert rawOutput is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08003296 assert "Command not found:" not in rawOutput, rawOutput
3297 output = json.loads( rawOutput )
acsmarsa4a4d1e2015-07-10 16:01:24 -07003298 results = []
3299 for dict in output:
3300 if dict["topic"] == topic:
3301 leader = dict["leader"]
Jon Hallc6793552016-01-19 14:18:37 -08003302 candidates = re.split( ", ", dict["candidates"][1:-1] )
3303 results.append( leader )
3304 results.extend( candidates )
acsmarsa4a4d1e2015-07-10 16:01:24 -07003305 return results
Jon Hallc6793552016-01-19 14:18:37 -08003306 except AssertionError:
3307 main.log.exception( "" )
3308 return None
3309 except ( TypeError, ValueError ):
3310 main.log.exception( "{}: Object not as expected: {!r}".format( self.name, rawOutput ) )
acsmarsa4a4d1e2015-07-10 16:01:24 -07003311 return None
3312 except pexpect.EOF:
3313 main.log.error( self.name + ": EOF exception found" )
3314 main.log.error( self.name + ": " + self.handle.before )
3315 main.cleanup()
3316 main.exit()
3317 except Exception:
3318 main.log.exception( self.name + ": Uncaught exception!" )
3319 main.cleanup()
3320 main.exit()
3321
Jon Hall61282e32015-03-19 11:34:11 -07003322 def pendingMap( self, jsonFormat=True ):
Jon Hall63604932015-02-26 17:09:50 -08003323 """
3324 Returns the output of the intent Pending map.
3325 """
Jon Hall63604932015-02-26 17:09:50 -08003326 try:
Jon Hallc6358dd2015-04-10 12:44:28 -07003327 cmdStr = "onos:intents -p"
Jon Hall61282e32015-03-19 11:34:11 -07003328 if jsonFormat:
Jon Hallc6358dd2015-04-10 12:44:28 -07003329 cmdStr += " -j"
3330 output = self.sendline( cmdStr )
Jon Halla495f562016-05-16 18:03:26 -07003331 assert output is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08003332 assert "Command not found:" not in output, output
Jon Hallc6358dd2015-04-10 12:44:28 -07003333 return output
Jon Hallc6793552016-01-19 14:18:37 -08003334 except AssertionError:
3335 main.log.exception( "" )
3336 return None
Jon Hall63604932015-02-26 17:09:50 -08003337 except TypeError:
3338 main.log.exception( self.name + ": Object not as expected" )
3339 return None
3340 except pexpect.EOF:
3341 main.log.error( self.name + ": EOF exception found" )
3342 main.log.error( self.name + ": " + self.handle.before )
3343 main.cleanup()
3344 main.exit()
Jon Hall77ba41c2015-04-06 10:25:40 -07003345 except Exception:
Jon Hall63604932015-02-26 17:09:50 -08003346 main.log.exception( self.name + ": Uncaught exception!" )
3347 main.cleanup()
3348 main.exit()
3349
Jon Hall61282e32015-03-19 11:34:11 -07003350 def partitions( self, jsonFormat=True ):
Jon Hall63604932015-02-26 17:09:50 -08003351 """
3352 Returns the output of the raft partitions command for ONOS.
3353 """
Jon Hall61282e32015-03-19 11:34:11 -07003354 # Sample JSON
3355 # {
3356 # "leader": "tcp://10.128.30.11:7238",
3357 # "members": [
3358 # "tcp://10.128.30.11:7238",
3359 # "tcp://10.128.30.17:7238",
3360 # "tcp://10.128.30.13:7238",
3361 # ],
3362 # "name": "p1",
3363 # "term": 3
3364 # },
Jon Hall63604932015-02-26 17:09:50 -08003365 try:
Jon Hallc6358dd2015-04-10 12:44:28 -07003366 cmdStr = "onos:partitions"
Jon Hall61282e32015-03-19 11:34:11 -07003367 if jsonFormat:
Jon Hallc6358dd2015-04-10 12:44:28 -07003368 cmdStr += " -j"
3369 output = self.sendline( cmdStr )
Jon Halla495f562016-05-16 18:03:26 -07003370 assert output is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08003371 assert "Command not found:" not in output, output
Jon Hallc6358dd2015-04-10 12:44:28 -07003372 return output
Jon Hallc6793552016-01-19 14:18:37 -08003373 except AssertionError:
3374 main.log.exception( "" )
3375 return None
Jon Hall63604932015-02-26 17:09:50 -08003376 except TypeError:
3377 main.log.exception( self.name + ": Object not as expected" )
3378 return None
3379 except pexpect.EOF:
3380 main.log.error( self.name + ": EOF exception found" )
3381 main.log.error( self.name + ": " + self.handle.before )
3382 main.cleanup()
3383 main.exit()
Jon Hall77ba41c2015-04-06 10:25:40 -07003384 except Exception:
Jon Hall63604932015-02-26 17:09:50 -08003385 main.log.exception( self.name + ": Uncaught exception!" )
3386 main.cleanup()
3387 main.exit()
3388
Jon Halle9f909e2016-09-23 10:43:12 -07003389 def apps( self, summary=False, active=False, jsonFormat=True ):
Jon Hallbe379602015-03-24 13:39:32 -07003390 """
3391 Returns the output of the apps command for ONOS. This command lists
3392 information about installed ONOS applications
3393 """
3394 # Sample JSON object
3395 # [{"name":"org.onosproject.openflow","id":0,"version":"1.2.0",
3396 # "description":"ONOS OpenFlow protocol southbound providers",
3397 # "origin":"ON.Lab","permissions":"[]","featuresRepo":"",
3398 # "features":"[onos-openflow]","state":"ACTIVE"}]
3399 try:
Jon Hallc6358dd2015-04-10 12:44:28 -07003400 cmdStr = "onos:apps"
Jon Halle9f909e2016-09-23 10:43:12 -07003401 if summary:
3402 cmdStr += " -s"
3403 if active:
3404 cmdStr += " -a"
Jon Hallbe379602015-03-24 13:39:32 -07003405 if jsonFormat:
Jon Hallc6358dd2015-04-10 12:44:28 -07003406 cmdStr += " -j"
3407 output = self.sendline( cmdStr )
Jon Halla495f562016-05-16 18:03:26 -07003408 assert output is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08003409 assert "Command not found:" not in output, output
3410 assert "Error executing command" not in output, output
Jon Hallc6358dd2015-04-10 12:44:28 -07003411 return output
Jon Hallbe379602015-03-24 13:39:32 -07003412 # FIXME: look at specific exceptions/Errors
3413 except AssertionError:
Jon Hallc6793552016-01-19 14:18:37 -08003414 main.log.exception( "Error in processing onos:app command." )
Jon Hallbe379602015-03-24 13:39:32 -07003415 return None
3416 except TypeError:
3417 main.log.exception( self.name + ": Object not as expected" )
3418 return None
3419 except pexpect.EOF:
3420 main.log.error( self.name + ": EOF exception found" )
3421 main.log.error( self.name + ": " + self.handle.before )
3422 main.cleanup()
3423 main.exit()
Jon Hall77ba41c2015-04-06 10:25:40 -07003424 except Exception:
Jon Hallbe379602015-03-24 13:39:32 -07003425 main.log.exception( self.name + ": Uncaught exception!" )
3426 main.cleanup()
3427 main.exit()
3428
Jon Hall146f1522015-03-24 15:33:24 -07003429 def appStatus( self, appName ):
3430 """
3431 Uses the onos:apps cli command to return the status of an application.
3432 Returns:
3433 "ACTIVE" - If app is installed and activated
3434 "INSTALLED" - If app is installed and deactivated
3435 "UNINSTALLED" - If app is not installed
3436 None - on error
3437 """
Jon Hall146f1522015-03-24 15:33:24 -07003438 try:
3439 if not isinstance( appName, types.StringType ):
3440 main.log.error( self.name + ".appStatus(): appName must be" +
3441 " a string" )
3442 return None
3443 output = self.apps( jsonFormat=True )
3444 appsJson = json.loads( output )
3445 state = None
3446 for app in appsJson:
3447 if appName == app.get('name'):
3448 state = app.get('state')
3449 break
3450 if state == "ACTIVE" or state == "INSTALLED":
3451 return state
3452 elif state is None:
3453 return "UNINSTALLED"
3454 elif state:
3455 main.log.error( "Unexpected state from 'onos:apps': " +
3456 str( state ) )
3457 return state
Jon Hallc6793552016-01-19 14:18:37 -08003458 except ( TypeError, ValueError ):
3459 main.log.exception( "{}: Object not as expected: {!r}".format( self.name, output ) )
Jon Hall146f1522015-03-24 15:33:24 -07003460 return None
3461 except pexpect.EOF:
3462 main.log.error( self.name + ": EOF exception found" )
3463 main.log.error( self.name + ": " + self.handle.before )
3464 main.cleanup()
3465 main.exit()
Jon Hall77ba41c2015-04-06 10:25:40 -07003466 except Exception:
Jon Hall146f1522015-03-24 15:33:24 -07003467 main.log.exception( self.name + ": Uncaught exception!" )
3468 main.cleanup()
3469 main.exit()
3470
Jon Hallbe379602015-03-24 13:39:32 -07003471 def app( self, appName, option ):
3472 """
3473 Interacts with the app command for ONOS. This command manages
3474 application inventory.
3475 """
Jon Hallbe379602015-03-24 13:39:32 -07003476 try:
Jon Hallbd16b922015-03-26 17:53:15 -07003477 # Validate argument types
3478 valid = True
3479 if not isinstance( appName, types.StringType ):
3480 main.log.error( self.name + ".app(): appName must be a " +
3481 "string" )
3482 valid = False
3483 if not isinstance( option, types.StringType ):
3484 main.log.error( self.name + ".app(): option must be a string" )
3485 valid = False
3486 if not valid:
3487 return main.FALSE
3488 # Validate Option
3489 option = option.lower()
3490 # NOTE: Install may become a valid option
3491 if option == "activate":
3492 pass
3493 elif option == "deactivate":
3494 pass
3495 elif option == "uninstall":
3496 pass
3497 else:
3498 # Invalid option
3499 main.log.error( "The ONOS app command argument only takes " +
3500 "the values: (activate|deactivate|uninstall)" +
3501 "; was given '" + option + "'")
3502 return main.FALSE
Jon Hall146f1522015-03-24 15:33:24 -07003503 cmdStr = "onos:app " + option + " " + appName
Jon Hallbe379602015-03-24 13:39:32 -07003504 output = self.sendline( cmdStr )
Jon Hallbe379602015-03-24 13:39:32 -07003505 if "Error executing command" in output:
3506 main.log.error( "Error in processing onos:app command: " +
3507 str( output ) )
Jon Hall146f1522015-03-24 15:33:24 -07003508 return main.FALSE
Jon Hallbe379602015-03-24 13:39:32 -07003509 elif "No such application" in output:
3510 main.log.error( "The application '" + appName +
3511 "' is not installed in ONOS" )
Jon Hall146f1522015-03-24 15:33:24 -07003512 return main.FALSE
3513 elif "Command not found:" in output:
3514 main.log.error( "Error in processing onos:app command: " +
3515 str( output ) )
3516 return main.FALSE
Jon Hallbd16b922015-03-26 17:53:15 -07003517 elif "Unsupported command:" in output:
3518 main.log.error( "Incorrect command given to 'app': " +
3519 str( output ) )
Jon Hallbe379602015-03-24 13:39:32 -07003520 # NOTE: we may need to add more checks here
Jon Hallbd16b922015-03-26 17:53:15 -07003521 # else: Command was successful
Jon Hall08f61bc2015-04-13 16:00:30 -07003522 # main.log.debug( "app response: " + repr( output ) )
Jon Hallbe379602015-03-24 13:39:32 -07003523 return main.TRUE
3524 except TypeError:
3525 main.log.exception( self.name + ": Object not as expected" )
3526 return main.ERROR
3527 except pexpect.EOF:
3528 main.log.error( self.name + ": EOF exception found" )
3529 main.log.error( self.name + ": " + self.handle.before )
3530 main.cleanup()
3531 main.exit()
Jon Hall77ba41c2015-04-06 10:25:40 -07003532 except Exception:
Jon Hallbe379602015-03-24 13:39:32 -07003533 main.log.exception( self.name + ": Uncaught exception!" )
3534 main.cleanup()
3535 main.exit()
Jon Hall146f1522015-03-24 15:33:24 -07003536
Jon Hallbd16b922015-03-26 17:53:15 -07003537 def activateApp( self, appName, check=True ):
Jon Hall146f1522015-03-24 15:33:24 -07003538 """
3539 Activate an app that is already installed in ONOS
Jon Hallbd16b922015-03-26 17:53:15 -07003540 appName is the hierarchical app name, not the feature name
3541 If check is True, method will check the status of the app after the
3542 command is issued
Jon Hall146f1522015-03-24 15:33:24 -07003543 Returns main.TRUE if the command was successfully sent
3544 main.FALSE if the cli responded with an error or given
3545 incorrect input
3546 """
3547 try:
3548 if not isinstance( appName, types.StringType ):
3549 main.log.error( self.name + ".activateApp(): appName must be" +
3550 " a string" )
3551 return main.FALSE
3552 status = self.appStatus( appName )
3553 if status == "INSTALLED":
3554 response = self.app( appName, "activate" )
Jon Hallbd16b922015-03-26 17:53:15 -07003555 if check and response == main.TRUE:
3556 for i in range(10): # try 10 times then give up
Jon Hallbd16b922015-03-26 17:53:15 -07003557 status = self.appStatus( appName )
3558 if status == "ACTIVE":
3559 return main.TRUE
3560 else:
Jon Hall050e1bd2015-03-30 13:33:02 -07003561 main.log.debug( "The state of application " +
3562 appName + " is " + status )
Jon Hallbd16b922015-03-26 17:53:15 -07003563 time.sleep( 1 )
3564 return main.FALSE
3565 else: # not 'check' or command didn't succeed
3566 return response
Jon Hall146f1522015-03-24 15:33:24 -07003567 elif status == "ACTIVE":
3568 return main.TRUE
3569 elif status == "UNINSTALLED":
3570 main.log.error( self.name + ": Tried to activate the " +
3571 "application '" + appName + "' which is not " +
3572 "installed." )
3573 else:
3574 main.log.error( "Unexpected return value from appStatus: " +
3575 str( status ) )
3576 return main.ERROR
3577 except TypeError:
3578 main.log.exception( self.name + ": Object not as expected" )
3579 return main.ERROR
3580 except pexpect.EOF:
3581 main.log.error( self.name + ": EOF exception found" )
3582 main.log.error( self.name + ": " + self.handle.before )
3583 main.cleanup()
3584 main.exit()
Jon Hall77ba41c2015-04-06 10:25:40 -07003585 except Exception:
Jon Hall146f1522015-03-24 15:33:24 -07003586 main.log.exception( self.name + ": Uncaught exception!" )
3587 main.cleanup()
3588 main.exit()
3589
Jon Hallbd16b922015-03-26 17:53:15 -07003590 def deactivateApp( self, appName, check=True ):
Jon Hall146f1522015-03-24 15:33:24 -07003591 """
3592 Deactivate an app that is already activated in ONOS
Jon Hallbd16b922015-03-26 17:53:15 -07003593 appName is the hierarchical app name, not the feature name
3594 If check is True, method will check the status of the app after the
3595 command is issued
Jon Hall146f1522015-03-24 15:33:24 -07003596 Returns main.TRUE if the command was successfully sent
3597 main.FALSE if the cli responded with an error or given
3598 incorrect input
3599 """
3600 try:
3601 if not isinstance( appName, types.StringType ):
3602 main.log.error( self.name + ".deactivateApp(): appName must " +
3603 "be a string" )
3604 return main.FALSE
3605 status = self.appStatus( appName )
3606 if status == "INSTALLED":
3607 return main.TRUE
3608 elif status == "ACTIVE":
3609 response = self.app( appName, "deactivate" )
Jon Hallbd16b922015-03-26 17:53:15 -07003610 if check and response == main.TRUE:
3611 for i in range(10): # try 10 times then give up
3612 status = self.appStatus( appName )
3613 if status == "INSTALLED":
3614 return main.TRUE
3615 else:
3616 time.sleep( 1 )
3617 return main.FALSE
3618 else: # not check or command didn't succeed
3619 return response
Jon Hall146f1522015-03-24 15:33:24 -07003620 elif status == "UNINSTALLED":
3621 main.log.warn( self.name + ": Tried to deactivate the " +
3622 "application '" + appName + "' which is not " +
3623 "installed." )
3624 return main.TRUE
3625 else:
3626 main.log.error( "Unexpected return value from appStatus: " +
3627 str( status ) )
3628 return main.ERROR
3629 except TypeError:
3630 main.log.exception( self.name + ": Object not as expected" )
3631 return main.ERROR
3632 except pexpect.EOF:
3633 main.log.error( self.name + ": EOF exception found" )
3634 main.log.error( self.name + ": " + self.handle.before )
3635 main.cleanup()
3636 main.exit()
Jon Hall77ba41c2015-04-06 10:25:40 -07003637 except Exception:
Jon Hall146f1522015-03-24 15:33:24 -07003638 main.log.exception( self.name + ": Uncaught exception!" )
3639 main.cleanup()
3640 main.exit()
3641
Jon Hallbd16b922015-03-26 17:53:15 -07003642 def uninstallApp( self, appName, check=True ):
Jon Hall146f1522015-03-24 15:33:24 -07003643 """
3644 Uninstall an app that is already installed in ONOS
Jon Hallbd16b922015-03-26 17:53:15 -07003645 appName is the hierarchical app name, not the feature name
3646 If check is True, method will check the status of the app after the
3647 command is issued
Jon Hall146f1522015-03-24 15:33:24 -07003648 Returns main.TRUE if the command was successfully sent
3649 main.FALSE if the cli responded with an error or given
3650 incorrect input
3651 """
3652 # TODO: check with Thomas about the state machine for apps
3653 try:
3654 if not isinstance( appName, types.StringType ):
3655 main.log.error( self.name + ".uninstallApp(): appName must " +
3656 "be a string" )
3657 return main.FALSE
3658 status = self.appStatus( appName )
3659 if status == "INSTALLED":
3660 response = self.app( appName, "uninstall" )
Jon Hallbd16b922015-03-26 17:53:15 -07003661 if check and response == main.TRUE:
3662 for i in range(10): # try 10 times then give up
3663 status = self.appStatus( appName )
3664 if status == "UNINSTALLED":
3665 return main.TRUE
3666 else:
3667 time.sleep( 1 )
3668 return main.FALSE
3669 else: # not check or command didn't succeed
3670 return response
Jon Hall146f1522015-03-24 15:33:24 -07003671 elif status == "ACTIVE":
3672 main.log.warn( self.name + ": Tried to uninstall the " +
3673 "application '" + appName + "' which is " +
3674 "currently active." )
3675 response = self.app( appName, "uninstall" )
Jon Hallbd16b922015-03-26 17:53:15 -07003676 if check and response == main.TRUE:
3677 for i in range(10): # try 10 times then give up
3678 status = self.appStatus( appName )
3679 if status == "UNINSTALLED":
3680 return main.TRUE
3681 else:
3682 time.sleep( 1 )
3683 return main.FALSE
3684 else: # not check or command didn't succeed
3685 return response
Jon Hall146f1522015-03-24 15:33:24 -07003686 elif status == "UNINSTALLED":
3687 return main.TRUE
3688 else:
3689 main.log.error( "Unexpected return value from appStatus: " +
3690 str( status ) )
3691 return main.ERROR
3692 except TypeError:
3693 main.log.exception( self.name + ": Object not as expected" )
3694 return main.ERROR
3695 except pexpect.EOF:
3696 main.log.error( self.name + ": EOF exception found" )
3697 main.log.error( self.name + ": " + self.handle.before )
3698 main.cleanup()
3699 main.exit()
Jon Hall77ba41c2015-04-06 10:25:40 -07003700 except Exception:
Jon Hall146f1522015-03-24 15:33:24 -07003701 main.log.exception( self.name + ": Uncaught exception!" )
3702 main.cleanup()
3703 main.exit()
Jon Hallbd16b922015-03-26 17:53:15 -07003704
3705 def appIDs( self, jsonFormat=True ):
3706 """
3707 Show the mappings between app id and app names given by the 'app-ids'
3708 cli command
3709 """
3710 try:
3711 cmdStr = "app-ids"
3712 if jsonFormat:
3713 cmdStr += " -j"
Jon Hallc6358dd2015-04-10 12:44:28 -07003714 output = self.sendline( cmdStr )
Jon Halla495f562016-05-16 18:03:26 -07003715 assert output is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08003716 assert "Command not found:" not in output, output
3717 assert "Error executing command" not in output, output
Jon Hallc6358dd2015-04-10 12:44:28 -07003718 return output
Jon Hallbd16b922015-03-26 17:53:15 -07003719 except AssertionError:
Jon Hallc6793552016-01-19 14:18:37 -08003720 main.log.exception( "Error in processing onos:app-ids command." )
Jon Hallbd16b922015-03-26 17:53:15 -07003721 return None
3722 except TypeError:
3723 main.log.exception( self.name + ": Object not as expected" )
3724 return None
3725 except pexpect.EOF:
3726 main.log.error( self.name + ": EOF exception found" )
3727 main.log.error( self.name + ": " + self.handle.before )
3728 main.cleanup()
3729 main.exit()
Jon Hall77ba41c2015-04-06 10:25:40 -07003730 except Exception:
Jon Hallbd16b922015-03-26 17:53:15 -07003731 main.log.exception( self.name + ": Uncaught exception!" )
3732 main.cleanup()
3733 main.exit()
3734
3735 def appToIDCheck( self ):
3736 """
3737 This method will check that each application's ID listed in 'apps' is
3738 the same as the ID listed in 'app-ids'. The check will also check that
3739 there are no duplicate IDs issued. Note that an app ID should be
3740 a globaly unique numerical identifier for app/app-like features. Once
3741 an ID is registered, the ID is never freed up so that if an app is
3742 reinstalled it will have the same ID.
3743
3744 Returns: main.TRUE if the check passes and
3745 main.FALSE if the check fails or
3746 main.ERROR if there is some error in processing the test
3747 """
3748 try:
Jon Hall390696c2015-05-05 17:13:41 -07003749 bail = False
Jon Hallc6793552016-01-19 14:18:37 -08003750 rawJson = self.appIDs( jsonFormat=True )
3751 if rawJson:
3752 ids = json.loads( rawJson )
Jon Hall390696c2015-05-05 17:13:41 -07003753 else:
Jon Hallc6793552016-01-19 14:18:37 -08003754 main.log.error( "app-ids returned nothing:" + repr( rawJson ) )
Jon Hall390696c2015-05-05 17:13:41 -07003755 bail = True
Jon Hallc6793552016-01-19 14:18:37 -08003756 rawJson = self.apps( jsonFormat=True )
3757 if rawJson:
3758 apps = json.loads( rawJson )
Jon Hall390696c2015-05-05 17:13:41 -07003759 else:
Jon Hallc6793552016-01-19 14:18:37 -08003760 main.log.error( "apps returned nothing:" + repr( rawJson ) )
Jon Hall390696c2015-05-05 17:13:41 -07003761 bail = True
3762 if bail:
3763 return main.FALSE
Jon Hallbd16b922015-03-26 17:53:15 -07003764 result = main.TRUE
3765 for app in apps:
3766 appID = app.get( 'id' )
3767 if appID is None:
3768 main.log.error( "Error parsing app: " + str( app ) )
3769 result = main.FALSE
3770 appName = app.get( 'name' )
3771 if appName is None:
3772 main.log.error( "Error parsing app: " + str( app ) )
3773 result = main.FALSE
3774 # get the entry in ids that has the same appID
Jon Hall390696c2015-05-05 17:13:41 -07003775 current = filter( lambda item: item[ 'id' ] == appID, ids )
Jon Hall050e1bd2015-03-30 13:33:02 -07003776 # main.log.debug( "Comparing " + str( app ) + " to " +
3777 # str( current ) )
Jon Hallbd16b922015-03-26 17:53:15 -07003778 if not current: # if ids doesn't have this id
3779 result = main.FALSE
3780 main.log.error( "'app-ids' does not have the ID for " +
3781 str( appName ) + " that apps does." )
3782 elif len( current ) > 1:
3783 # there is more than one app with this ID
3784 result = main.FALSE
3785 # We will log this later in the method
3786 elif not current[0][ 'name' ] == appName:
3787 currentName = current[0][ 'name' ]
3788 result = main.FALSE
3789 main.log.error( "'app-ids' has " + str( currentName ) +
3790 " registered under id:" + str( appID ) +
3791 " but 'apps' has " + str( appName ) )
3792 else:
3793 pass # id and name match!
3794 # now make sure that app-ids has no duplicates
3795 idsList = []
3796 namesList = []
3797 for item in ids:
3798 idsList.append( item[ 'id' ] )
3799 namesList.append( item[ 'name' ] )
3800 if len( idsList ) != len( set( idsList ) ) or\
3801 len( namesList ) != len( set( namesList ) ):
3802 main.log.error( "'app-ids' has some duplicate entries: \n"
3803 + json.dumps( ids,
3804 sort_keys=True,
3805 indent=4,
3806 separators=( ',', ': ' ) ) )
3807 result = main.FALSE
3808 return result
Jon Hallc6793552016-01-19 14:18:37 -08003809 except ( TypeError, ValueError ):
3810 main.log.exception( "{}: Object not as expected: {!r}".format( self.name, rawJson ) )
Jon Hallbd16b922015-03-26 17:53:15 -07003811 return main.ERROR
3812 except pexpect.EOF:
3813 main.log.error( self.name + ": EOF exception found" )
3814 main.log.error( self.name + ": " + self.handle.before )
3815 main.cleanup()
3816 main.exit()
Jon Hall77ba41c2015-04-06 10:25:40 -07003817 except Exception:
Jon Hallbd16b922015-03-26 17:53:15 -07003818 main.log.exception( self.name + ": Uncaught exception!" )
3819 main.cleanup()
3820 main.exit()
3821
Jon Hallfb760a02015-04-13 15:35:03 -07003822 def getCfg( self, component=None, propName=None, short=False,
3823 jsonFormat=True ):
3824 """
3825 Get configuration settings from onos cli
3826 Optional arguments:
3827 component - Optionally only list configurations for a specific
3828 component. If None, all components with configurations
3829 are displayed. Case Sensitive string.
3830 propName - If component is specified, propName option will show
3831 only this specific configuration from that component.
3832 Case Sensitive string.
3833 jsonFormat - Returns output as json. Note that this will override
3834 the short option
3835 short - Short, less verbose, version of configurations.
3836 This is overridden by the json option
3837 returns:
3838 Output from cli as a string or None on error
3839 """
3840 try:
3841 baseStr = "cfg"
3842 cmdStr = " get"
3843 componentStr = ""
3844 if component:
3845 componentStr += " " + component
3846 if propName:
3847 componentStr += " " + propName
3848 if jsonFormat:
3849 baseStr += " -j"
3850 elif short:
3851 baseStr += " -s"
3852 output = self.sendline( baseStr + cmdStr + componentStr )
Jon Halla495f562016-05-16 18:03:26 -07003853 assert output is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08003854 assert "Command not found:" not in output, output
3855 assert "Error executing command" not in output, output
Jon Hallfb760a02015-04-13 15:35:03 -07003856 return output
3857 except AssertionError:
Jon Hallc6793552016-01-19 14:18:37 -08003858 main.log.exception( "Error in processing 'cfg get' command." )
Jon Hallfb760a02015-04-13 15:35:03 -07003859 return None
3860 except TypeError:
3861 main.log.exception( self.name + ": Object not as expected" )
3862 return None
3863 except pexpect.EOF:
3864 main.log.error( self.name + ": EOF exception found" )
3865 main.log.error( self.name + ": " + self.handle.before )
3866 main.cleanup()
3867 main.exit()
3868 except Exception:
3869 main.log.exception( self.name + ": Uncaught exception!" )
3870 main.cleanup()
3871 main.exit()
3872
3873 def setCfg( self, component, propName, value=None, check=True ):
3874 """
3875 Set/Unset configuration settings from ONOS cli
Jon Hall390696c2015-05-05 17:13:41 -07003876 Required arguments:
Jon Hallfb760a02015-04-13 15:35:03 -07003877 component - The case sensitive name of the component whose
3878 property is to be set
3879 propName - The case sensitive name of the property to be set/unset
Jon Hall390696c2015-05-05 17:13:41 -07003880 Optional arguments:
Jon Hallfb760a02015-04-13 15:35:03 -07003881 value - The value to set the property to. If None, will unset the
3882 property and revert it to it's default value(if applicable)
3883 check - Boolean, Check whether the option was successfully set this
3884 only applies when a value is given.
3885 returns:
3886 main.TRUE on success or main.FALSE on failure. If check is False,
3887 will return main.TRUE unless there is an error
3888 """
3889 try:
3890 baseStr = "cfg"
3891 cmdStr = " set " + str( component ) + " " + str( propName )
3892 if value is not None:
3893 cmdStr += " " + str( value )
3894 output = self.sendline( baseStr + cmdStr )
Jon Halla495f562016-05-16 18:03:26 -07003895 assert output is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08003896 assert "Command not found:" not in output, output
3897 assert "Error executing command" not in output, output
Jon Hallfb760a02015-04-13 15:35:03 -07003898 if value and check:
3899 results = self.getCfg( component=str( component ),
3900 propName=str( propName ),
3901 jsonFormat=True )
3902 # Check if current value is what we just set
3903 try:
3904 jsonOutput = json.loads( results )
3905 current = jsonOutput[ 'value' ]
Jon Hallc6793552016-01-19 14:18:37 -08003906 except ( TypeError, ValueError ):
Jon Hallfb760a02015-04-13 15:35:03 -07003907 main.log.exception( "Error parsing cfg output" )
3908 main.log.error( "output:" + repr( results ) )
3909 return main.FALSE
3910 if current == str( value ):
3911 return main.TRUE
3912 return main.FALSE
3913 return main.TRUE
3914 except AssertionError:
Jon Hallc6793552016-01-19 14:18:37 -08003915 main.log.exception( "Error in processing 'cfg set' command." )
Jon Hallfb760a02015-04-13 15:35:03 -07003916 return main.FALSE
Jon Hallc6793552016-01-19 14:18:37 -08003917 except ( TypeError, ValueError ):
3918 main.log.exception( "{}: Object not as expected: {!r}".format( self.name, results ) )
Jon Hallfb760a02015-04-13 15:35:03 -07003919 return main.FALSE
3920 except pexpect.EOF:
3921 main.log.error( self.name + ": EOF exception found" )
3922 main.log.error( self.name + ": " + self.handle.before )
3923 main.cleanup()
3924 main.exit()
3925 except Exception:
3926 main.log.exception( self.name + ": Uncaught exception!" )
3927 main.cleanup()
3928 main.exit()
3929
Jon Hall390696c2015-05-05 17:13:41 -07003930 def setTestAdd( self, setName, values ):
3931 """
3932 CLI command to add elements to a distributed set.
3933 Arguments:
3934 setName - The name of the set to add to.
3935 values - The value(s) to add to the set, space seperated.
3936 Example usages:
3937 setTestAdd( "set1", "a b c" )
3938 setTestAdd( "set2", "1" )
3939 returns:
3940 main.TRUE on success OR
3941 main.FALSE if elements were already in the set OR
3942 main.ERROR on error
3943 """
3944 try:
3945 cmdStr = "set-test-add " + str( setName ) + " " + str( values )
3946 output = self.sendline( cmdStr )
Jon Halla495f562016-05-16 18:03:26 -07003947 assert output is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08003948 assert "Command not found:" not in output, output
Jon Hallfeff3082015-05-19 10:23:26 -07003949 try:
3950 # TODO: Maybe make this less hardcoded
3951 # ConsistentMap Exceptions
3952 assert "org.onosproject.store.service" not in output
3953 # Node not leader
3954 assert "java.lang.IllegalStateException" not in output
3955 except AssertionError:
Jon Halle1a3b752015-07-22 13:02:46 -07003956 main.log.error( "Error in processing '" + cmdStr + "' " +
Jon Hallfeff3082015-05-19 10:23:26 -07003957 "command: " + str( output ) )
3958 retryTime = 30 # Conservative time, given by Madan
3959 main.log.info( "Waiting " + str( retryTime ) +
3960 "seconds before retrying." )
3961 time.sleep( retryTime ) # Due to change in mastership
3962 output = self.sendline( cmdStr )
Jon Halla495f562016-05-16 18:03:26 -07003963 assert output is not None, "Error in sendline"
Jon Hall390696c2015-05-05 17:13:41 -07003964 assert "Error executing command" not in output
3965 positiveMatch = "\[(.*)\] was added to the set " + str( setName )
3966 negativeMatch = "\[(.*)\] was already in set " + str( setName )
3967 main.log.info( self.name + ": " + output )
3968 if re.search( positiveMatch, output):
3969 return main.TRUE
3970 elif re.search( negativeMatch, output):
3971 return main.FALSE
3972 else:
3973 main.log.error( self.name + ": setTestAdd did not" +
3974 " match expected output" )
Jon Hall390696c2015-05-05 17:13:41 -07003975 main.log.debug( self.name + " actual: " + repr( output ) )
3976 return main.ERROR
3977 except AssertionError:
Jon Hallc6793552016-01-19 14:18:37 -08003978 main.log.exception( "Error in processing '" + cmdStr + "' command. " )
Jon Hall390696c2015-05-05 17:13:41 -07003979 return main.ERROR
3980 except TypeError:
3981 main.log.exception( self.name + ": Object not as expected" )
3982 return main.ERROR
3983 except pexpect.EOF:
3984 main.log.error( self.name + ": EOF exception found" )
3985 main.log.error( self.name + ": " + self.handle.before )
3986 main.cleanup()
3987 main.exit()
3988 except Exception:
3989 main.log.exception( self.name + ": Uncaught exception!" )
3990 main.cleanup()
3991 main.exit()
3992
3993 def setTestRemove( self, setName, values, clear=False, retain=False ):
3994 """
3995 CLI command to remove elements from a distributed set.
3996 Required arguments:
3997 setName - The name of the set to remove from.
3998 values - The value(s) to remove from the set, space seperated.
3999 Optional arguments:
4000 clear - Clear all elements from the set
4001 retain - Retain only the given values. (intersection of the
4002 original set and the given set)
4003 returns:
4004 main.TRUE on success OR
4005 main.FALSE if the set was not changed OR
4006 main.ERROR on error
4007 """
4008 try:
4009 cmdStr = "set-test-remove "
4010 if clear:
4011 cmdStr += "-c " + str( setName )
4012 elif retain:
4013 cmdStr += "-r " + str( setName ) + " " + str( values )
4014 else:
4015 cmdStr += str( setName ) + " " + str( values )
4016 output = self.sendline( cmdStr )
Jon Hallfeff3082015-05-19 10:23:26 -07004017 try:
Jon Halla495f562016-05-16 18:03:26 -07004018 assert output is not None, "Error in sendline"
Jon Hallfeff3082015-05-19 10:23:26 -07004019 # TODO: Maybe make this less hardcoded
4020 # ConsistentMap Exceptions
4021 assert "org.onosproject.store.service" not in output
4022 # Node not leader
4023 assert "java.lang.IllegalStateException" not in output
4024 except AssertionError:
Jon Halle1a3b752015-07-22 13:02:46 -07004025 main.log.error( "Error in processing '" + cmdStr + "' " +
Jon Hallfeff3082015-05-19 10:23:26 -07004026 "command: " + str( output ) )
4027 retryTime = 30 # Conservative time, given by Madan
4028 main.log.info( "Waiting " + str( retryTime ) +
4029 "seconds before retrying." )
4030 time.sleep( retryTime ) # Due to change in mastership
4031 output = self.sendline( cmdStr )
Jon Halla495f562016-05-16 18:03:26 -07004032 assert output is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08004033 assert "Command not found:" not in output, output
4034 assert "Error executing command" not in output, output
Jon Hall390696c2015-05-05 17:13:41 -07004035 main.log.info( self.name + ": " + output )
4036 if clear:
4037 pattern = "Set " + str( setName ) + " cleared"
4038 if re.search( pattern, output ):
4039 return main.TRUE
4040 elif retain:
4041 positivePattern = str( setName ) + " was pruned to contain " +\
4042 "only elements of set \[(.*)\]"
4043 negativePattern = str( setName ) + " was not changed by " +\
4044 "retaining only elements of the set " +\
4045 "\[(.*)\]"
4046 if re.search( positivePattern, output ):
4047 return main.TRUE
4048 elif re.search( negativePattern, output ):
4049 return main.FALSE
4050 else:
4051 positivePattern = "\[(.*)\] was removed from the set " +\
4052 str( setName )
4053 if ( len( values.split() ) == 1 ):
4054 negativePattern = "\[(.*)\] was not in set " +\
4055 str( setName )
4056 else:
4057 negativePattern = "No element of \[(.*)\] was in set " +\
4058 str( setName )
4059 if re.search( positivePattern, output ):
4060 return main.TRUE
4061 elif re.search( negativePattern, output ):
4062 return main.FALSE
4063 main.log.error( self.name + ": setTestRemove did not" +
4064 " match expected output" )
4065 main.log.debug( self.name + " expected: " + pattern )
4066 main.log.debug( self.name + " actual: " + repr( output ) )
4067 return main.ERROR
4068 except AssertionError:
Jon Hallc6793552016-01-19 14:18:37 -08004069 main.log.exception( "Error in processing '" + cmdStr + "' commandr. " )
Jon Hall390696c2015-05-05 17:13:41 -07004070 return main.ERROR
4071 except TypeError:
4072 main.log.exception( self.name + ": Object not as expected" )
4073 return main.ERROR
4074 except pexpect.EOF:
4075 main.log.error( self.name + ": EOF exception found" )
4076 main.log.error( self.name + ": " + self.handle.before )
4077 main.cleanup()
4078 main.exit()
4079 except Exception:
4080 main.log.exception( self.name + ": Uncaught exception!" )
4081 main.cleanup()
4082 main.exit()
4083
4084 def setTestGet( self, setName, values="" ):
4085 """
4086 CLI command to get the elements in a distributed set.
4087 Required arguments:
4088 setName - The name of the set to remove from.
4089 Optional arguments:
4090 values - The value(s) to check if in the set, space seperated.
4091 returns:
4092 main.ERROR on error OR
4093 A list of elements in the set if no optional arguments are
4094 supplied OR
4095 A tuple containing the list then:
4096 main.FALSE if the given values are not in the set OR
4097 main.TRUE if the given values are in the set OR
4098 """
4099 try:
4100 values = str( values ).strip()
4101 setName = str( setName ).strip()
4102 length = len( values.split() )
4103 containsCheck = None
4104 # Patterns to match
4105 setPattern = "\[(.*)\]"
Jon Hall67253832016-12-05 09:47:13 -08004106 pattern = "Items in set " + setName + ":\r\n" + setPattern
Jon Hall390696c2015-05-05 17:13:41 -07004107 containsTrue = "Set " + setName + " contains the value " + values
4108 containsFalse = "Set " + setName + " did not contain the value " +\
4109 values
4110 containsAllTrue = "Set " + setName + " contains the the subset " +\
4111 setPattern
4112 containsAllFalse = "Set " + setName + " did not contain the the" +\
4113 " subset " + setPattern
4114
4115 cmdStr = "set-test-get "
4116 cmdStr += setName + " " + values
4117 output = self.sendline( cmdStr )
Jon Hallfeff3082015-05-19 10:23:26 -07004118 try:
Jon Halla495f562016-05-16 18:03:26 -07004119 assert output is not None, "Error in sendline"
Jon Hallfeff3082015-05-19 10:23:26 -07004120 # TODO: Maybe make this less hardcoded
4121 # ConsistentMap Exceptions
4122 assert "org.onosproject.store.service" not in output
4123 # Node not leader
4124 assert "java.lang.IllegalStateException" not in output
4125 except AssertionError:
Jon Halle1a3b752015-07-22 13:02:46 -07004126 main.log.error( "Error in processing '" + cmdStr + "' " +
Jon Hallfeff3082015-05-19 10:23:26 -07004127 "command: " + str( output ) )
4128 retryTime = 30 # Conservative time, given by Madan
4129 main.log.info( "Waiting " + str( retryTime ) +
4130 "seconds before retrying." )
4131 time.sleep( retryTime ) # Due to change in mastership
4132 output = self.sendline( cmdStr )
Jon Halla495f562016-05-16 18:03:26 -07004133 assert output is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08004134 assert "Command not found:" not in output, output
4135 assert "Error executing command" not in output, output
Jon Hall390696c2015-05-05 17:13:41 -07004136 main.log.info( self.name + ": " + output )
4137
4138 if length == 0:
4139 match = re.search( pattern, output )
4140 else: # if given values
4141 if length == 1: # Contains output
Jon Hall54b994f2016-12-05 10:48:59 -08004142 patternTrue = pattern + "\r\n" + containsTrue
4143 patternFalse = pattern + "\r\n" + containsFalse
Jon Hall390696c2015-05-05 17:13:41 -07004144 else: # ContainsAll output
Jon Hall54b994f2016-12-05 10:48:59 -08004145 patternTrue = pattern + "\r\n" + containsAllTrue
4146 patternFalse = pattern + "\r\n" + containsAllFalse
Jon Hall390696c2015-05-05 17:13:41 -07004147 matchTrue = re.search( patternTrue, output )
4148 matchFalse = re.search( patternFalse, output )
4149 if matchTrue:
4150 containsCheck = main.TRUE
4151 match = matchTrue
4152 elif matchFalse:
4153 containsCheck = main.FALSE
4154 match = matchFalse
4155 else:
4156 main.log.error( self.name + " setTestGet did not match " +\
4157 "expected output" )
4158 main.log.debug( self.name + " expected: " + pattern )
4159 main.log.debug( self.name + " actual: " + repr( output ) )
4160 match = None
4161 if match:
4162 setMatch = match.group( 1 )
4163 if setMatch == '':
4164 setList = []
4165 else:
4166 setList = setMatch.split( ", " )
4167 if length > 0:
4168 return ( setList, containsCheck )
4169 else:
4170 return setList
4171 else: # no match
4172 main.log.error( self.name + ": setTestGet did not" +
4173 " match expected output" )
4174 main.log.debug( self.name + " expected: " + pattern )
4175 main.log.debug( self.name + " actual: " + repr( output ) )
4176 return main.ERROR
4177 except AssertionError:
Jon Hallc6793552016-01-19 14:18:37 -08004178 main.log.exception( "Error in processing '" + cmdStr + "' command." )
Jon Hall390696c2015-05-05 17:13:41 -07004179 return main.ERROR
4180 except TypeError:
4181 main.log.exception( self.name + ": Object not as expected" )
4182 return main.ERROR
4183 except pexpect.EOF:
4184 main.log.error( self.name + ": EOF exception found" )
4185 main.log.error( self.name + ": " + self.handle.before )
4186 main.cleanup()
4187 main.exit()
4188 except Exception:
4189 main.log.exception( self.name + ": Uncaught exception!" )
4190 main.cleanup()
4191 main.exit()
4192
4193 def setTestSize( self, setName ):
4194 """
4195 CLI command to get the elements in a distributed set.
4196 Required arguments:
4197 setName - The name of the set to remove from.
4198 returns:
Jon Hallfeff3082015-05-19 10:23:26 -07004199 The integer value of the size returned or
Jon Hall390696c2015-05-05 17:13:41 -07004200 None on error
4201 """
4202 try:
4203 # TODO: Should this check against the number of elements returned
4204 # and then return true/false based on that?
4205 setName = str( setName ).strip()
4206 # Patterns to match
4207 setPattern = "\[(.*)\]"
Jon Hall67253832016-12-05 09:47:13 -08004208 pattern = "There are (\d+) items in set " + setName + ":\r\n" +\
Jon Hall390696c2015-05-05 17:13:41 -07004209 setPattern
4210 cmdStr = "set-test-get -s "
4211 cmdStr += setName
4212 output = self.sendline( cmdStr )
Jon Hallfeff3082015-05-19 10:23:26 -07004213 try:
Jon Halla495f562016-05-16 18:03:26 -07004214 assert output is not None, "Error in sendline"
Jon Hallfeff3082015-05-19 10:23:26 -07004215 # TODO: Maybe make this less hardcoded
4216 # ConsistentMap Exceptions
4217 assert "org.onosproject.store.service" not in output
4218 # Node not leader
4219 assert "java.lang.IllegalStateException" not in output
4220 except AssertionError:
Jon Halle1a3b752015-07-22 13:02:46 -07004221 main.log.error( "Error in processing '" + cmdStr + "' " +
Jon Hallfeff3082015-05-19 10:23:26 -07004222 "command: " + str( output ) )
4223 retryTime = 30 # Conservative time, given by Madan
4224 main.log.info( "Waiting " + str( retryTime ) +
4225 "seconds before retrying." )
4226 time.sleep( retryTime ) # Due to change in mastership
4227 output = self.sendline( cmdStr )
Jon Halla495f562016-05-16 18:03:26 -07004228 assert output is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08004229 assert "Command not found:" not in output, output
4230 assert "Error executing command" not in output, output
Jon Hall390696c2015-05-05 17:13:41 -07004231 main.log.info( self.name + ": " + output )
4232 match = re.search( pattern, output )
4233 if match:
4234 setSize = int( match.group( 1 ) )
4235 setMatch = match.group( 2 )
4236 if len( setMatch.split() ) == setSize:
4237 main.log.info( "The size returned by " + self.name +
4238 " matches the number of elements in " +
4239 "the returned set" )
4240 else:
4241 main.log.error( "The size returned by " + self.name +
4242 " does not match the number of " +
4243 "elements in the returned set." )
4244 return setSize
4245 else: # no match
4246 main.log.error( self.name + ": setTestGet did not" +
4247 " match expected output" )
4248 main.log.debug( self.name + " expected: " + pattern )
4249 main.log.debug( self.name + " actual: " + repr( output ) )
4250 return None
4251 except AssertionError:
Jon Hallc6793552016-01-19 14:18:37 -08004252 main.log.exception( "Error in processing '" + cmdStr + "' command." )
acsmarsa4a4d1e2015-07-10 16:01:24 -07004253 return None
Jon Hall390696c2015-05-05 17:13:41 -07004254 except TypeError:
4255 main.log.exception( self.name + ": Object not as expected" )
4256 return None
4257 except pexpect.EOF:
4258 main.log.error( self.name + ": EOF exception found" )
4259 main.log.error( self.name + ": " + self.handle.before )
4260 main.cleanup()
4261 main.exit()
4262 except Exception:
4263 main.log.exception( self.name + ": Uncaught exception!" )
4264 main.cleanup()
4265 main.exit()
4266
Jon Hall80daded2015-05-27 16:07:00 -07004267 def counters( self, jsonFormat=True ):
Jon Hall390696c2015-05-05 17:13:41 -07004268 """
4269 Command to list the various counters in the system.
4270 returns:
Jon Hall80daded2015-05-27 16:07:00 -07004271 if jsonFormat, a string of the json object returned by the cli
4272 command
4273 if not jsonFormat, the normal string output of the cli command
Jon Hall390696c2015-05-05 17:13:41 -07004274 None on error
4275 """
Jon Hall390696c2015-05-05 17:13:41 -07004276 try:
4277 counters = {}
4278 cmdStr = "counters"
Jon Hall80daded2015-05-27 16:07:00 -07004279 if jsonFormat:
4280 cmdStr += " -j"
Jon Hall390696c2015-05-05 17:13:41 -07004281 output = self.sendline( cmdStr )
Jon Halla495f562016-05-16 18:03:26 -07004282 assert output is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08004283 assert "Command not found:" not in output, output
4284 assert "Error executing command" not in output, output
Jon Hall390696c2015-05-05 17:13:41 -07004285 main.log.info( self.name + ": " + output )
Jon Hall80daded2015-05-27 16:07:00 -07004286 return output
Jon Hall390696c2015-05-05 17:13:41 -07004287 except AssertionError:
Jon Hallc6793552016-01-19 14:18:37 -08004288 main.log.exception( "Error in processing 'counters' command." )
Jon Hall80daded2015-05-27 16:07:00 -07004289 return None
Jon Hall390696c2015-05-05 17:13:41 -07004290 except TypeError:
4291 main.log.exception( self.name + ": Object not as expected" )
Jon Hall80daded2015-05-27 16:07:00 -07004292 return None
Jon Hall390696c2015-05-05 17:13:41 -07004293 except pexpect.EOF:
4294 main.log.error( self.name + ": EOF exception found" )
4295 main.log.error( self.name + ": " + self.handle.before )
4296 main.cleanup()
4297 main.exit()
4298 except Exception:
4299 main.log.exception( self.name + ": Uncaught exception!" )
4300 main.cleanup()
4301 main.exit()
4302
Jon Hall935db192016-04-19 00:22:04 -07004303 def counterTestAddAndGet( self, counter, delta=1 ):
Jon Hall390696c2015-05-05 17:13:41 -07004304 """
Jon Halle1a3b752015-07-22 13:02:46 -07004305 CLI command to add a delta to then get a distributed counter.
Jon Hall390696c2015-05-05 17:13:41 -07004306 Required arguments:
4307 counter - The name of the counter to increment.
4308 Optional arguments:
Jon Halle1a3b752015-07-22 13:02:46 -07004309 delta - The long to add to the counter
Jon Hall390696c2015-05-05 17:13:41 -07004310 returns:
4311 integer value of the counter or
4312 None on Error
4313 """
4314 try:
4315 counter = str( counter )
Jon Halle1a3b752015-07-22 13:02:46 -07004316 delta = int( delta )
Jon Hall390696c2015-05-05 17:13:41 -07004317 cmdStr = "counter-test-increment "
Jon Hall390696c2015-05-05 17:13:41 -07004318 cmdStr += counter
Jon Halle1a3b752015-07-22 13:02:46 -07004319 if delta != 1:
4320 cmdStr += " " + str( delta )
Jon Hall390696c2015-05-05 17:13:41 -07004321 output = self.sendline( cmdStr )
Jon Hallfeff3082015-05-19 10:23:26 -07004322 try:
Jon Halla495f562016-05-16 18:03:26 -07004323 assert output is not None, "Error in sendline"
Jon Hallfeff3082015-05-19 10:23:26 -07004324 # TODO: Maybe make this less hardcoded
4325 # ConsistentMap Exceptions
4326 assert "org.onosproject.store.service" not in output
4327 # Node not leader
4328 assert "java.lang.IllegalStateException" not in output
4329 except AssertionError:
Jon Halle1a3b752015-07-22 13:02:46 -07004330 main.log.error( "Error in processing '" + cmdStr + "' " +
Jon Hallfeff3082015-05-19 10:23:26 -07004331 "command: " + str( output ) )
4332 retryTime = 30 # Conservative time, given by Madan
4333 main.log.info( "Waiting " + str( retryTime ) +
4334 "seconds before retrying." )
4335 time.sleep( retryTime ) # Due to change in mastership
4336 output = self.sendline( cmdStr )
Jon Halla495f562016-05-16 18:03:26 -07004337 assert output is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08004338 assert "Command not found:" not in output, output
4339 assert "Error executing command" not in output, output
Jon Hall390696c2015-05-05 17:13:41 -07004340 main.log.info( self.name + ": " + output )
Jon Halle1a3b752015-07-22 13:02:46 -07004341 pattern = counter + " was updated to (-?\d+)"
Jon Hall390696c2015-05-05 17:13:41 -07004342 match = re.search( pattern, output )
4343 if match:
4344 return int( match.group( 1 ) )
4345 else:
Jon Halle1a3b752015-07-22 13:02:46 -07004346 main.log.error( self.name + ": counterTestAddAndGet did not" +
Jon Hall390696c2015-05-05 17:13:41 -07004347 " match expected output." )
4348 main.log.debug( self.name + " expected: " + pattern )
4349 main.log.debug( self.name + " actual: " + repr( output ) )
4350 return None
4351 except AssertionError:
Jon Hallc6793552016-01-19 14:18:37 -08004352 main.log.exception( "Error in processing '" + cmdStr + "' command." )
Jon Hall390696c2015-05-05 17:13:41 -07004353 return None
4354 except TypeError:
4355 main.log.exception( self.name + ": Object not as expected" )
4356 return None
4357 except pexpect.EOF:
4358 main.log.error( self.name + ": EOF exception found" )
4359 main.log.error( self.name + ": " + self.handle.before )
4360 main.cleanup()
4361 main.exit()
4362 except Exception:
4363 main.log.exception( self.name + ": Uncaught exception!" )
4364 main.cleanup()
4365 main.exit()
4366
Jon Hall935db192016-04-19 00:22:04 -07004367 def counterTestGetAndAdd( self, counter, delta=1 ):
Jon Halle1a3b752015-07-22 13:02:46 -07004368 """
4369 CLI command to get a distributed counter then add a delta to it.
4370 Required arguments:
4371 counter - The name of the counter to increment.
4372 Optional arguments:
4373 delta - The long to add to the counter
Jon Halle1a3b752015-07-22 13:02:46 -07004374 returns:
4375 integer value of the counter or
4376 None on Error
4377 """
4378 try:
4379 counter = str( counter )
4380 delta = int( delta )
4381 cmdStr = "counter-test-increment -g "
Jon Halle1a3b752015-07-22 13:02:46 -07004382 cmdStr += counter
4383 if delta != 1:
4384 cmdStr += " " + str( delta )
4385 output = self.sendline( cmdStr )
4386 try:
Jon Halla495f562016-05-16 18:03:26 -07004387 assert output is not None, "Error in sendline"
Jon Halle1a3b752015-07-22 13:02:46 -07004388 # TODO: Maybe make this less hardcoded
4389 # ConsistentMap Exceptions
4390 assert "org.onosproject.store.service" not in output
4391 # Node not leader
4392 assert "java.lang.IllegalStateException" not in output
4393 except AssertionError:
4394 main.log.error( "Error in processing '" + cmdStr + "' " +
4395 "command: " + str( output ) )
4396 retryTime = 30 # Conservative time, given by Madan
4397 main.log.info( "Waiting " + str( retryTime ) +
4398 "seconds before retrying." )
4399 time.sleep( retryTime ) # Due to change in mastership
4400 output = self.sendline( cmdStr )
Jon Halla495f562016-05-16 18:03:26 -07004401 assert output is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08004402 assert "Command not found:" not in output, output
4403 assert "Error executing command" not in output, output
Jon Halle1a3b752015-07-22 13:02:46 -07004404 main.log.info( self.name + ": " + output )
4405 pattern = counter + " was updated to (-?\d+)"
4406 match = re.search( pattern, output )
4407 if match:
4408 return int( match.group( 1 ) )
4409 else:
4410 main.log.error( self.name + ": counterTestGetAndAdd did not" +
4411 " match expected output." )
4412 main.log.debug( self.name + " expected: " + pattern )
4413 main.log.debug( self.name + " actual: " + repr( output ) )
4414 return None
4415 except AssertionError:
Jon Hallc6793552016-01-19 14:18:37 -08004416 main.log.exception( "Error in processing '" + cmdStr + "' command." )
Jon Halle1a3b752015-07-22 13:02:46 -07004417 return None
4418 except TypeError:
4419 main.log.exception( self.name + ": Object not as expected" )
4420 return None
4421 except pexpect.EOF:
4422 main.log.error( self.name + ": EOF exception found" )
4423 main.log.error( self.name + ": " + self.handle.before )
4424 main.cleanup()
4425 main.exit()
4426 except Exception:
4427 main.log.exception( self.name + ": Uncaught exception!" )
4428 main.cleanup()
4429 main.exit()
4430
YPZhangfebf7302016-05-24 16:45:56 -07004431 def summary( self, jsonFormat=True, timeout=30 ):
kelvin-onlaba297c4d2015-06-01 13:53:55 -07004432 """
4433 Description: Execute summary command in onos
4434 Returns: json object ( summary -j ), returns main.FALSE if there is
4435 no output
4436
4437 """
4438 try:
4439 cmdStr = "summary"
4440 if jsonFormat:
4441 cmdStr += " -j"
YPZhangfebf7302016-05-24 16:45:56 -07004442 handle = self.sendline( cmdStr, timeout=timeout )
Jon Halla495f562016-05-16 18:03:26 -07004443 assert handle is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08004444 assert "Command not found:" not in handle, handle
Jon Hall6e709752016-02-01 13:38:46 -08004445 assert "Error:" not in handle, handle
kelvin-onlaba297c4d2015-06-01 13:53:55 -07004446 if not handle:
4447 main.log.error( self.name + ": There is no output in " +
4448 "summary command" )
4449 return main.FALSE
4450 return handle
Jon Hallc6793552016-01-19 14:18:37 -08004451 except AssertionError:
Jon Hall6e709752016-02-01 13:38:46 -08004452 main.log.exception( "{} Error in summary output:".format( self.name ) )
Jon Hallc6793552016-01-19 14:18:37 -08004453 return None
kelvin-onlaba297c4d2015-06-01 13:53:55 -07004454 except TypeError:
4455 main.log.exception( self.name + ": Object not as expected" )
4456 return None
4457 except pexpect.EOF:
4458 main.log.error( self.name + ": EOF exception found" )
4459 main.log.error( self.name + ": " + self.handle.before )
4460 main.cleanup()
4461 main.exit()
4462 except Exception:
4463 main.log.exception( self.name + ": Uncaught exception!" )
4464 main.cleanup()
4465 main.exit()
Jon Hall2a5002c2015-08-21 16:49:11 -07004466
Jon Hall935db192016-04-19 00:22:04 -07004467 def transactionalMapGet( self, keyName ):
Jon Hall2a5002c2015-08-21 16:49:11 -07004468 """
4469 CLI command to get the value of a key in a consistent map using
4470 transactions. This a test function and can only get keys from the
4471 test map hard coded into the cli command
4472 Required arguments:
4473 keyName - The name of the key to get
Jon Hall2a5002c2015-08-21 16:49:11 -07004474 returns:
4475 The string value of the key or
4476 None on Error
4477 """
4478 try:
4479 keyName = str( keyName )
4480 cmdStr = "transactional-map-test-get "
Jon Hall2a5002c2015-08-21 16:49:11 -07004481 cmdStr += keyName
4482 output = self.sendline( cmdStr )
Jon Halla495f562016-05-16 18:03:26 -07004483 assert output is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08004484 assert "Command not found:" not in output, output
Jon Hall2a5002c2015-08-21 16:49:11 -07004485 try:
4486 # TODO: Maybe make this less hardcoded
4487 # ConsistentMap Exceptions
4488 assert "org.onosproject.store.service" not in output
4489 # Node not leader
4490 assert "java.lang.IllegalStateException" not in output
4491 except AssertionError:
4492 main.log.error( "Error in processing '" + cmdStr + "' " +
4493 "command: " + str( output ) )
4494 return None
4495 pattern = "Key-value pair \(" + keyName + ", (?P<value>.+)\) found."
4496 if "Key " + keyName + " not found." in output:
Jon Hall9bfadd22016-05-11 14:48:07 -07004497 main.log.warn( output )
Jon Hall2a5002c2015-08-21 16:49:11 -07004498 return None
4499 else:
4500 match = re.search( pattern, output )
4501 if match:
4502 return match.groupdict()[ 'value' ]
4503 else:
4504 main.log.error( self.name + ": transactionlMapGet did not" +
4505 " match expected output." )
4506 main.log.debug( self.name + " expected: " + pattern )
4507 main.log.debug( self.name + " actual: " + repr( output ) )
4508 return None
Jon Hallc6793552016-01-19 14:18:37 -08004509 except AssertionError:
4510 main.log.exception( "" )
4511 return None
Jon Hall2a5002c2015-08-21 16:49:11 -07004512 except TypeError:
4513 main.log.exception( self.name + ": Object not as expected" )
4514 return None
4515 except pexpect.EOF:
4516 main.log.error( self.name + ": EOF exception found" )
4517 main.log.error( self.name + ": " + self.handle.before )
4518 main.cleanup()
4519 main.exit()
4520 except Exception:
4521 main.log.exception( self.name + ": Uncaught exception!" )
4522 main.cleanup()
4523 main.exit()
4524
Jon Hall935db192016-04-19 00:22:04 -07004525 def transactionalMapPut( self, numKeys, value ):
Jon Hall2a5002c2015-08-21 16:49:11 -07004526 """
4527 CLI command to put a value into 'numKeys' number of keys in a
4528 consistent map using transactions. This a test function and can only
4529 put into keys named 'Key#' of the test map hard coded into the cli command
4530 Required arguments:
4531 numKeys - Number of keys to add the value to
4532 value - The string value to put into the keys
Jon Hall2a5002c2015-08-21 16:49:11 -07004533 returns:
4534 A dictionary whose keys are the name of the keys put into the map
4535 and the values of the keys are dictionaries whose key-values are
4536 'value': value put into map and optionaly
4537 'oldValue': Previous value in the key or
4538 None on Error
4539
4540 Example output
4541 { 'Key1': {'oldValue': 'oldTestValue', 'value': 'Testing'},
4542 'Key2': {'value': 'Testing'} }
4543 """
4544 try:
4545 numKeys = str( numKeys )
4546 value = str( value )
4547 cmdStr = "transactional-map-test-put "
Jon Hall2a5002c2015-08-21 16:49:11 -07004548 cmdStr += numKeys + " " + value
4549 output = self.sendline( cmdStr )
Jon Halla495f562016-05-16 18:03:26 -07004550 assert output is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08004551 assert "Command not found:" not in output, output
Jon Hall2a5002c2015-08-21 16:49:11 -07004552 try:
4553 # TODO: Maybe make this less hardcoded
4554 # ConsistentMap Exceptions
4555 assert "org.onosproject.store.service" not in output
4556 # Node not leader
4557 assert "java.lang.IllegalStateException" not in output
4558 except AssertionError:
4559 main.log.error( "Error in processing '" + cmdStr + "' " +
4560 "command: " + str( output ) )
4561 return None
4562 newPattern = 'Created Key (?P<key>(\w)+) with value (?P<value>(.)+)\.'
4563 updatedPattern = "Put (?P<value>(.)+) into key (?P<key>(\w)+)\. The old value was (?P<oldValue>(.)+)\."
4564 results = {}
4565 for line in output.splitlines():
4566 new = re.search( newPattern, line )
4567 updated = re.search( updatedPattern, line )
4568 if new:
4569 results[ new.groupdict()[ 'key' ] ] = { 'value': new.groupdict()[ 'value' ] }
4570 elif updated:
4571 results[ updated.groupdict()[ 'key' ] ] = { 'value': updated.groupdict()[ 'value' ],
Jon Hallc6793552016-01-19 14:18:37 -08004572 'oldValue': updated.groupdict()[ 'oldValue' ] }
Jon Hall2a5002c2015-08-21 16:49:11 -07004573 else:
4574 main.log.error( self.name + ": transactionlMapGet did not" +
4575 " match expected output." )
Jon Hallc6793552016-01-19 14:18:37 -08004576 main.log.debug( "{} expected: {!r} or {!r}".format( self.name,
4577 newPattern,
4578 updatedPattern ) )
Jon Hall2a5002c2015-08-21 16:49:11 -07004579 main.log.debug( self.name + " actual: " + repr( output ) )
4580 return results
Jon Hallc6793552016-01-19 14:18:37 -08004581 except AssertionError:
4582 main.log.exception( "" )
4583 return None
Jon Hall2a5002c2015-08-21 16:49:11 -07004584 except TypeError:
4585 main.log.exception( self.name + ": Object not as expected" )
4586 return None
4587 except pexpect.EOF:
4588 main.log.error( self.name + ": EOF exception found" )
4589 main.log.error( self.name + ": " + self.handle.before )
4590 main.cleanup()
4591 main.exit()
4592 except Exception:
4593 main.log.exception( self.name + ": Uncaught exception!" )
4594 main.cleanup()
4595 main.exit()
Jon Hallc6793552016-01-19 14:18:37 -08004596
acsmarsdaea66c2015-09-03 11:44:06 -07004597 def maps( self, jsonFormat=True ):
4598 """
4599 Description: Returns result of onos:maps
4600 Optional:
4601 * jsonFormat: enable json formatting of output
4602 """
4603 try:
4604 cmdStr = "maps"
4605 if jsonFormat:
4606 cmdStr += " -j"
4607 handle = self.sendline( cmdStr )
Jon Halla495f562016-05-16 18:03:26 -07004608 assert handle is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08004609 assert "Command not found:" not in handle, handle
acsmarsdaea66c2015-09-03 11:44:06 -07004610 return handle
Jon Hallc6793552016-01-19 14:18:37 -08004611 except AssertionError:
4612 main.log.exception( "" )
4613 return None
acsmarsdaea66c2015-09-03 11:44:06 -07004614 except TypeError:
4615 main.log.exception( self.name + ": Object not as expected" )
4616 return None
4617 except pexpect.EOF:
4618 main.log.error( self.name + ": EOF exception found" )
4619 main.log.error( self.name + ": " + self.handle.before )
4620 main.cleanup()
4621 main.exit()
4622 except Exception:
4623 main.log.exception( self.name + ": Uncaught exception!" )
4624 main.cleanup()
4625 main.exit()
GlennRC050596c2015-11-18 17:06:41 -08004626
4627 def getSwController( self, uri, jsonFormat=True ):
4628 """
4629 Descrition: Gets the controller information from the device
4630 """
4631 try:
4632 cmd = "device-controllers "
4633 if jsonFormat:
4634 cmd += "-j "
4635 response = self.sendline( cmd + uri )
Jon Halla495f562016-05-16 18:03:26 -07004636 assert response is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08004637 assert "Command not found:" not in response, response
GlennRC050596c2015-11-18 17:06:41 -08004638 return response
Jon Hallc6793552016-01-19 14:18:37 -08004639 except AssertionError:
4640 main.log.exception( "" )
4641 return None
GlennRC050596c2015-11-18 17:06:41 -08004642 except TypeError:
4643 main.log.exception( self.name + ": Object not as expected" )
4644 return None
4645 except pexpect.EOF:
4646 main.log.error( self.name + ": EOF exception found" )
4647 main.log.error( self.name + ": " + self.handle.before )
4648 main.cleanup()
4649 main.exit()
4650 except Exception:
4651 main.log.exception( self.name + ": Uncaught exception!" )
4652 main.cleanup()
4653 main.exit()
4654
4655 def setSwController( self, uri, ip, proto="tcp", port="6653", jsonFormat=True ):
4656 """
4657 Descrition: sets the controller(s) for the specified device
4658
4659 Parameters:
4660 Required: uri - String: The uri of the device(switch).
4661 ip - String or List: The ip address of the controller.
4662 This parameter can be formed in a couple of different ways.
4663 VALID:
4664 10.0.0.1 - just the ip address
4665 tcp:10.0.0.1 - the protocol and the ip address
4666 tcp:10.0.0.1:6653 - the protocol and port can be specified,
4667 so that you can add controllers with different
4668 protocols and ports
4669 INVALID:
4670 10.0.0.1:6653 - this is not supported by ONOS
4671
4672 Optional: proto - The type of connection e.g. tcp, ssl. If a list of ips are given
4673 port - The port number.
4674 jsonFormat - If set ONOS will output in json NOTE: This is currently not supported
4675
4676 Returns: main.TRUE if ONOS returns without any errors, otherwise returns main.FALSE
4677 """
4678 try:
4679 cmd = "device-setcontrollers"
4680
4681 if jsonFormat:
4682 cmd += " -j"
4683 cmd += " " + uri
4684 if isinstance( ip, str ):
4685 ip = [ip]
4686 for item in ip:
4687 if ":" in item:
4688 sitem = item.split( ":" )
4689 if len(sitem) == 3:
4690 cmd += " " + item
4691 elif "." in sitem[1]:
4692 cmd += " {}:{}".format(item, port)
4693 else:
4694 main.log.error( "Malformed entry: " + item )
4695 raise TypeError
4696 else:
4697 cmd += " {}:{}:{}".format( proto, item, port )
GlennRC050596c2015-11-18 17:06:41 -08004698 response = self.sendline( cmd )
Jon Halla495f562016-05-16 18:03:26 -07004699 assert response is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08004700 assert "Command not found:" not in response, response
GlennRC050596c2015-11-18 17:06:41 -08004701 if "Error" in response:
4702 main.log.error( response )
4703 return main.FALSE
GlennRC050596c2015-11-18 17:06:41 -08004704 return main.TRUE
Jon Hallc6793552016-01-19 14:18:37 -08004705 except AssertionError:
4706 main.log.exception( "" )
4707 return None
GlennRC050596c2015-11-18 17:06:41 -08004708 except TypeError:
4709 main.log.exception( self.name + ": Object not as expected" )
4710 return main.FALSE
4711 except pexpect.EOF:
4712 main.log.error( self.name + ": EOF exception found" )
4713 main.log.error( self.name + ": " + self.handle.before )
4714 main.cleanup()
4715 main.exit()
4716 except Exception:
4717 main.log.exception( self.name + ": Uncaught exception!" )
4718 main.cleanup()
4719 main.exit()
GlennRC20fc6522015-12-23 23:26:57 -08004720
4721 def removeDevice( self, device ):
4722 '''
4723 Description:
4724 Remove a device from ONOS by passing the uri of the device(s).
4725 Parameters:
4726 device - (str or list) the id or uri of the device ex. "of:0000000000000001"
4727 Returns:
4728 Returns main.FALSE if an exception is thrown or an error is present
4729 in the response. Otherwise, returns main.TRUE.
4730 NOTE:
4731 If a host cannot be removed, then this function will return main.FALSE
4732 '''
4733 try:
4734 if type( device ) is str:
You Wang823f5022016-08-18 15:24:41 -07004735 deviceStr = device
4736 device = []
4737 device.append( deviceStr )
GlennRC20fc6522015-12-23 23:26:57 -08004738
4739 for d in device:
4740 time.sleep( 1 )
4741 response = self.sendline( "device-remove {}".format( d ) )
Jon Halla495f562016-05-16 18:03:26 -07004742 assert response is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08004743 assert "Command not found:" not in response, response
GlennRC20fc6522015-12-23 23:26:57 -08004744 if "Error" in response:
4745 main.log.warn( "Error for device: {}\nResponse: {}".format( d, response ) )
4746 return main.FALSE
GlennRC20fc6522015-12-23 23:26:57 -08004747 return main.TRUE
Jon Hallc6793552016-01-19 14:18:37 -08004748 except AssertionError:
4749 main.log.exception( "" )
4750 return main.FALSE
GlennRC20fc6522015-12-23 23:26:57 -08004751 except TypeError:
4752 main.log.exception( self.name + ": Object not as expected" )
4753 return main.FALSE
4754 except pexpect.EOF:
4755 main.log.error( self.name + ": EOF exception found" )
4756 main.log.error( self.name + ": " + self.handle.before )
4757 main.cleanup()
4758 main.exit()
4759 except Exception:
4760 main.log.exception( self.name + ": Uncaught exception!" )
4761 main.cleanup()
4762 main.exit()
4763
4764 def removeHost( self, host ):
4765 '''
4766 Description:
4767 Remove a host from ONOS by passing the id of the host(s)
4768 Parameters:
4769 hostId - (str or list) the id or mac of the host ex. "00:00:00:00:00:01"
4770 Returns:
4771 Returns main.FALSE if an exception is thrown or an error is present
4772 in the response. Otherwise, returns main.TRUE.
4773 NOTE:
4774 If a host cannot be removed, then this function will return main.FALSE
4775 '''
4776 try:
4777 if type( host ) is str:
4778 host = list( host )
4779
4780 for h in host:
4781 time.sleep( 1 )
4782 response = self.sendline( "host-remove {}".format( h ) )
Jon Halla495f562016-05-16 18:03:26 -07004783 assert response is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08004784 assert "Command not found:" not in response, response
GlennRC20fc6522015-12-23 23:26:57 -08004785 if "Error" in response:
4786 main.log.warn( "Error for host: {}\nResponse: {}".format( h, response ) )
4787 return main.FALSE
GlennRC20fc6522015-12-23 23:26:57 -08004788 return main.TRUE
Jon Hallc6793552016-01-19 14:18:37 -08004789 except AssertionError:
4790 main.log.exception( "" )
4791 return None
GlennRC20fc6522015-12-23 23:26:57 -08004792 except TypeError:
4793 main.log.exception( self.name + ": Object not as expected" )
4794 return main.FALSE
4795 except pexpect.EOF:
4796 main.log.error( self.name + ": EOF exception found" )
4797 main.log.error( self.name + ": " + self.handle.before )
4798 main.cleanup()
4799 main.exit()
4800 except Exception:
4801 main.log.exception( self.name + ": Uncaught exception!" )
4802 main.cleanup()
4803 main.exit()
GlennRCed771242016-01-13 17:02:47 -08004804
YPZhangfebf7302016-05-24 16:45:56 -07004805 def link( self, begin, end, state, timeout=30, showResponse=True ):
GlennRCed771242016-01-13 17:02:47 -08004806 '''
4807 Description:
4808 Bring link down or up in the null-provider.
4809 params:
4810 begin - (string) One end of a device or switch.
4811 end - (string) the other end of the device or switch
4812 returns:
4813 main.TRUE if no exceptions were thrown and no Errors are
4814 present in the resoponse. Otherwise, returns main.FALSE
4815 '''
4816 try:
Jon Hallc6793552016-01-19 14:18:37 -08004817 cmd = "null-link null:{} null:{} {}".format( begin, end, state )
YPZhangfebf7302016-05-24 16:45:56 -07004818 response = self.sendline( cmd, showResponse=showResponse, timeout=timeout )
Jon Halla495f562016-05-16 18:03:26 -07004819 assert response is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08004820 assert "Command not found:" not in response, response
GlennRCed771242016-01-13 17:02:47 -08004821 if "Error" in response or "Failure" in response:
4822 main.log.error( response )
4823 return main.FALSE
GlennRCed771242016-01-13 17:02:47 -08004824 return main.TRUE
Jon Hallc6793552016-01-19 14:18:37 -08004825 except AssertionError:
4826 main.log.exception( "" )
4827 return None
GlennRCed771242016-01-13 17:02:47 -08004828 except TypeError:
4829 main.log.exception( self.name + ": Object not as expected" )
4830 return main.FALSE
4831 except pexpect.EOF:
4832 main.log.error( self.name + ": EOF exception found" )
4833 main.log.error( self.name + ": " + self.handle.before )
4834 main.cleanup()
4835 main.exit()
4836 except Exception:
4837 main.log.exception( self.name + ": Uncaught exception!" )
4838 main.cleanup()
4839 main.exit()
4840
Flavio Castro82ee2f62016-06-07 15:04:12 -07004841 def portstate(self, dpid='of:0000000000000102', port='2', state='enable'):
4842 '''
4843 Description:
4844 Changes the state of port in an OF switch by means of the
4845 PORTSTATUS OF messages.
4846 params:
4847 dpid - (string) Datapath ID of the device
4848 port - (string) target port in the device
4849 state - (string) target state (enable or disabled)
4850 returns:
4851 main.TRUE if no exceptions were thrown and no Errors are
4852 present in the resoponse. Otherwise, returns main.FALSE
4853 '''
4854 try:
4855 cmd = "portstate {} {} {}".format( dpid, port, state )
4856 response = self.sendline( cmd, showResponse=True )
4857 assert response is not None, "Error in sendline"
4858 assert "Command not found:" not in response, response
4859 if "Error" in response or "Failure" in response:
4860 main.log.error( response )
4861 return main.FALSE
4862 return main.TRUE
4863 except AssertionError:
4864 main.log.exception( "" )
4865 return None
4866 except TypeError:
4867 main.log.exception( self.name + ": Object not as expected" )
4868 return main.FALSE
4869 except pexpect.EOF:
4870 main.log.error( self.name + ": EOF exception found" )
4871 main.log.error( self.name + ": " + self.handle.before )
4872 main.cleanup()
4873 main.exit()
4874 except Exception:
4875 main.log.exception( self.name + ": Uncaught exception!" )
4876 main.cleanup()
4877 main.exit()
4878
4879 def logSet( self, level="INFO", app="org.onosproject" ):
4880 """
4881 Set the logging level to lvl for a specific app
4882 returns main.TRUE on success
4883 returns main.FALSE if Error occurred
4884 if noExit is True, TestON will not exit, but clean up
4885 Available level: DEBUG, TRACE, INFO, WARN, ERROR
4886 Level defaults to INFO
4887 """
4888 try:
4889 self.handle.sendline( "log:set %s %s" %( level, app ) )
4890 self.handle.expect( "onos>" )
4891
4892 response = self.handle.before
4893 if re.search( "Error", response ):
4894 return main.FALSE
4895 return main.TRUE
4896 except pexpect.TIMEOUT:
4897 main.log.exception( self.name + ": TIMEOUT exception found" )
4898 main.cleanup()
4899 main.exit()
4900 except pexpect.EOF:
4901 main.log.error( self.name + ": EOF exception found" )
4902 main.log.error( self.name + ": " + self.handle.before )
4903 main.cleanup()
4904 main.exit()
4905 except Exception:
4906 main.log.exception( self.name + ": Uncaught exception!" )
4907 main.cleanup()
4908 main.exit()
You Wangdb8cd0a2016-05-26 15:19:45 -07004909
4910 def getGraphDict( self, timeout=60, includeHost=False ):
4911 """
4912 Return a dictionary which describes the latest network topology data as a
4913 graph.
4914 An example of the dictionary:
4915 { vertex1: { 'edges': ..., 'name': ..., 'protocol': ... },
4916 vertex2: { 'edges': ..., 'name': ..., 'protocol': ... } }
4917 Each vertex should at least have an 'edges' attribute which describes the
4918 adjacency information. The value of 'edges' attribute is also represented by
4919 a dictionary, which maps each edge (identified by the neighbor vertex) to a
4920 list of attributes.
4921 An example of the edges dictionary:
4922 'edges': { vertex2: { 'port': ..., 'weight': ... },
4923 vertex3: { 'port': ..., 'weight': ... } }
4924 If includeHost == True, all hosts (and host-switch links) will be included
4925 in topology data.
4926 """
4927 graphDict = {}
4928 try:
4929 links = self.links()
4930 links = json.loads( links )
4931 devices = self.devices()
4932 devices = json.loads( devices )
4933 idToDevice = {}
4934 for device in devices:
4935 idToDevice[ device[ 'id' ] ] = device
4936 if includeHost:
4937 hosts = self.hosts()
4938 # FIXME: support 'includeHost' argument
4939 for link in links:
4940 nodeA = link[ 'src' ][ 'device' ]
4941 nodeB = link[ 'dst' ][ 'device' ]
4942 assert idToDevice[ nodeA ][ 'available' ] and idToDevice[ nodeB ][ 'available' ]
4943 if not nodeA in graphDict.keys():
4944 graphDict[ nodeA ] = { 'edges':{},
4945 'dpid':idToDevice[ nodeA ][ 'id' ][3:],
4946 'type':idToDevice[ nodeA ][ 'type' ],
4947 'available':idToDevice[ nodeA ][ 'available' ],
4948 'role':idToDevice[ nodeA ][ 'role' ],
4949 'mfr':idToDevice[ nodeA ][ 'mfr' ],
4950 'hw':idToDevice[ nodeA ][ 'hw' ],
4951 'sw':idToDevice[ nodeA ][ 'sw' ],
4952 'serial':idToDevice[ nodeA ][ 'serial' ],
4953 'chassisId':idToDevice[ nodeA ][ 'chassisId' ],
4954 'annotations':idToDevice[ nodeA ][ 'annotations' ]}
4955 else:
4956 # Assert nodeB is not connected to any current links of nodeA
4957 assert nodeB not in graphDict[ nodeA ][ 'edges' ].keys()
4958 graphDict[ nodeA ][ 'edges' ][ nodeB ] = { 'port':link[ 'src' ][ 'port' ],
4959 'type':link[ 'type' ],
4960 'state':link[ 'state' ] }
4961 return graphDict
4962 except ( TypeError, ValueError ):
4963 main.log.exception( self.name + ": Object not as expected" )
4964 return None
4965 except KeyError:
4966 main.log.exception( self.name + ": KeyError exception found" )
4967 return None
4968 except AssertionError:
4969 main.log.exception( self.name + ": AssertionError exception found" )
4970 return None
4971 except pexpect.EOF:
4972 main.log.error( self.name + ": EOF exception found" )
4973 main.log.error( self.name + ": " + self.handle.before )
4974 return None
4975 except Exception:
4976 main.log.exception( self.name + ": Uncaught exception!" )
4977 return None
YPZhangcbc2a062016-07-11 10:55:44 -07004978
4979 def getIntentPerfSummary( self ):
4980 '''
4981 Send command to check intent-perf summary
4982 Returns: dictionary for intent-perf summary
4983 if something wrong, function will return None
4984 '''
4985 cmd = "intent-perf -s"
4986 respDic = {}
4987 resp = self.sendline( cmd )
4988 try:
4989 # Generate the dictionary to return
4990 for l in resp.split( "\n" ):
4991 # Delete any white space in line
4992 temp = re.sub( r'\s+', '', l )
4993 temp = temp.split( ":" )
4994 respDic[ temp[0] ] = temp[ 1 ]
4995
4996 except (TypeError, ValueError):
4997 main.log.exception( self.name + ": Object not as expected" )
4998 return None
4999 except KeyError:
5000 main.log.exception( self.name + ": KeyError exception found" )
5001 return None
5002 except AssertionError:
5003 main.log.exception( self.name + ": AssertionError exception found" )
5004 return None
5005 except pexpect.EOF:
5006 main.log.error( self.name + ": EOF exception found" )
5007 main.log.error( self.name + ": " + self.handle.before )
5008 return None
5009 except Exception:
5010 main.log.exception( self.name + ": Uncaught exception!" )
5011 return None
5012 return respDic
5013
chengchiyu08303a02016-09-08 17:40:26 -07005014 def logSearch( self, searchTerm, mode='all' ):
5015 """
5016 Searches the latest ONOS log file for the given search term and
5017 return a list that contains all the lines that have the search term.
YPZhangcbc2a062016-07-11 10:55:44 -07005018
chengchiyu08303a02016-09-08 17:40:26 -07005019 Arguments:
5020 searchTerm - A string to grep for in the ONOS log.
5021 mode:
5022 all: return all the strings that contain the search term
5023 last: return the last string that contains the search term
5024 first: return the first string that contains the search term
Chiyu Chengb8c2c842016-10-05 12:40:49 -07005025 num: return the number that the searchTerm appears in the log
chengchiyu08303a02016-09-08 17:40:26 -07005026 """
5027 try:
5028 assert type( searchTerm ) is str
Chiyu Chengb8c2c842016-10-05 12:40:49 -07005029 cmd = "cat /opt/onos/log/karaf.log | grep \'" + searchTerm + "\'"
chengchiyu08303a02016-09-08 17:40:26 -07005030 if mode == 'last':
5031 cmd = cmd + " | tail -n 1"
5032 if mode == 'first':
5033 cmd = cmd + " | head -n 1"
Chiyu Chengb8c2c842016-10-05 12:40:49 -07005034 if mode == 'num':
5035 cmd = "cat /opt/onos/log/karaf.log | grep -c \'" + searchTerm + "\'"
5036 num = self.sendline( cmd )
5037 return num
chengchiyu08303a02016-09-08 17:40:26 -07005038 before = self.sendline( cmd )
5039 before = before.splitlines()
5040 # make sure the returned list only contains the search term
5041 returnLines = [line for line in before if searchTerm in line]
5042 return returnLines
5043 except AssertionError:
5044 main.log.error( self.name + " searchTerm is not string type" )
5045 return None
5046 except pexpect.EOF:
5047 main.log.error( self.name + ": EOF exception found" )
5048 main.log.error( self.name + ": " + self.handle.before )
5049 main.cleanup()
5050 main.exit()
5051 except pexpect.TIMEOUT:
5052 main.log.error( self.name + ": TIMEOUT exception found" )
5053 main.log.error( self.name + ": " + self.handle.before )
5054 main.cleanup()
5055 main.exit()
5056 except Exception:
5057 main.log.exception( self.name + ": Uncaught exception!" )
5058 main.cleanup()
5059 main.exit()