blob: c5ac77eb6b6981ddf625ff5df6ada1fbadc59ae3 [file] [log] [blame]
andrewonlab95ce8322014-10-13 14:12:04 -04001#!/usr/bin/env python
2
kelvin8ec71442015-01-15 16:57:00 -08003"""
andrewonlab95ce8322014-10-13 14:12:04 -04004This driver enters the onos> prompt to issue commands.
5
kelvin8ec71442015-01-15 16:57:00 -08006Please follow the coding style demonstrated by existing
andrewonlab95ce8322014-10-13 14:12:04 -04007functions and document properly.
8
9If you are a contributor to the driver, please
10list your email here for future contact:
11
12jhall@onlab.us
13andrew@onlab.us
Jon Halle8217482014-10-17 13:49:14 -040014shreya@onlab.us
andrewonlab95ce8322014-10-13 14:12:04 -040015
16OCT 13 2014
17
kelvin8ec71442015-01-15 16:57:00 -080018"""
andrewonlab95ce8322014-10-13 14:12:04 -040019import pexpect
20import re
Jon Hall30b82fa2015-03-04 17:15:43 -080021import json
22import types
Jon Hallbd16b922015-03-26 17:53:15 -070023import time
kelvin-onlaba4074292015-07-09 15:19:49 -070024import os
andrewonlab95ce8322014-10-13 14:12:04 -040025from drivers.common.clidriver import CLI
26
andrewonlab95ce8322014-10-13 14:12:04 -040027
kelvin8ec71442015-01-15 16:57:00 -080028class OnosCliDriver( CLI ):
andrewonlab95ce8322014-10-13 14:12:04 -040029
kelvin8ec71442015-01-15 16:57:00 -080030 def __init__( self ):
31 """
32 Initialize client
33 """
Jon Hallefbd9792015-03-05 16:11:36 -080034 self.name = None
35 self.home = None
36 self.handle = None
kelvin8ec71442015-01-15 16:57:00 -080037 super( CLI, self ).__init__()
38
39 def connect( self, **connectargs ):
40 """
andrewonlab95ce8322014-10-13 14:12:04 -040041 Creates ssh handle for ONOS cli.
kelvin8ec71442015-01-15 16:57:00 -080042 """
andrewonlab95ce8322014-10-13 14:12:04 -040043 try:
44 for key in connectargs:
kelvin8ec71442015-01-15 16:57:00 -080045 vars( self )[ key ] = connectargs[ key ]
andrew@onlab.us658ec012015-03-11 15:13:09 -070046 self.home = "~/onos"
andrewonlab95ce8322014-10-13 14:12:04 -040047 for key in self.options:
48 if key == "home":
kelvin8ec71442015-01-15 16:57:00 -080049 self.home = self.options[ 'home' ]
andrewonlab95ce8322014-10-13 14:12:04 -040050 break
kelvin-onlabfb521662015-02-27 09:52:40 -080051 if self.home is None or self.home == "":
Jon Halle94919c2015-03-23 11:42:57 -070052 self.home = "~/onos"
andrewonlab95ce8322014-10-13 14:12:04 -040053
kelvin-onlaba4074292015-07-09 15:19:49 -070054 for key in self.options:
55 if key == 'onosIp':
56 self.onosIp = self.options[ 'onosIp' ]
57 break
58
kelvin8ec71442015-01-15 16:57:00 -080059 self.name = self.options[ 'name' ]
kelvin-onlaba4074292015-07-09 15:19:49 -070060
61 try:
Jon Hallc6793552016-01-19 14:18:37 -080062 if os.getenv( str( self.ip_address ) ) is not None:
kelvin-onlaba4074292015-07-09 15:19:49 -070063 self.ip_address = os.getenv( str( self.ip_address ) )
64 else:
65 main.log.info( self.name +
66 ": Trying to connect to " +
67 self.ip_address )
68
69 except KeyError:
70 main.log.info( "Invalid host name," +
71 " connecting to local host instead" )
72 self.ip_address = 'localhost'
73 except Exception as inst:
74 main.log.error( "Uncaught exception: " + str( inst ) )
75
kelvin8ec71442015-01-15 16:57:00 -080076 self.handle = super( OnosCliDriver, self ).connect(
kelvin-onlab08679eb2015-01-21 16:11:48 -080077 user_name=self.user_name,
78 ip_address=self.ip_address,
kelvin-onlab898a6c62015-01-16 14:13:53 -080079 port=self.port,
80 pwd=self.pwd,
81 home=self.home )
andrewonlab95ce8322014-10-13 14:12:04 -040082
kelvin8ec71442015-01-15 16:57:00 -080083 self.handle.sendline( "cd " + self.home )
84 self.handle.expect( "\$" )
andrewonlab95ce8322014-10-13 14:12:04 -040085 if self.handle:
86 return self.handle
kelvin8ec71442015-01-15 16:57:00 -080087 else:
88 main.log.info( "NO ONOS HANDLE" )
andrewonlab95ce8322014-10-13 14:12:04 -040089 return main.FALSE
Jon Halld4d4b372015-01-28 16:02:41 -080090 except TypeError:
91 main.log.exception( self.name + ": Object not as expected" )
92 return None
andrewonlab95ce8322014-10-13 14:12:04 -040093 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -080094 main.log.error( self.name + ": EOF exception found" )
95 main.log.error( self.name + ": " + self.handle.before )
andrewonlab95ce8322014-10-13 14:12:04 -040096 main.cleanup()
97 main.exit()
Jon Hallfebb1c72015-03-05 13:30:09 -080098 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -080099 main.log.exception( self.name + ": Uncaught exception!" )
andrewonlab95ce8322014-10-13 14:12:04 -0400100 main.cleanup()
101 main.exit()
102
kelvin8ec71442015-01-15 16:57:00 -0800103 def disconnect( self ):
104 """
andrewonlab95ce8322014-10-13 14:12:04 -0400105 Called when Test is complete to disconnect the ONOS handle.
kelvin8ec71442015-01-15 16:57:00 -0800106 """
Jon Halld61331b2015-02-17 16:35:47 -0800107 response = main.TRUE
andrewonlab95ce8322014-10-13 14:12:04 -0400108 try:
Jon Hall61282e32015-03-19 11:34:11 -0700109 if self.handle:
110 i = self.logout()
111 if i == main.TRUE:
112 self.handle.sendline( "" )
113 self.handle.expect( "\$" )
114 self.handle.sendline( "exit" )
115 self.handle.expect( "closed" )
Jon Halld4d4b372015-01-28 16:02:41 -0800116 except TypeError:
117 main.log.exception( self.name + ": Object not as expected" )
Jon Halld61331b2015-02-17 16:35:47 -0800118 response = main.FALSE
andrewonlab95ce8322014-10-13 14:12:04 -0400119 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -0800120 main.log.error( self.name + ": EOF exception found" )
121 main.log.error( self.name + ": " + self.handle.before )
Jon Hall61282e32015-03-19 11:34:11 -0700122 except ValueError:
Jon Hall1a77a1e2015-04-06 10:41:13 -0700123 main.log.exception( "Exception in disconnect of " + self.name )
Jon Hall61282e32015-03-19 11:34:11 -0700124 response = main.TRUE
Jon Hallfebb1c72015-03-05 13:30:09 -0800125 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -0800126 main.log.exception( self.name + ": Connection failed to the host" )
andrewonlab95ce8322014-10-13 14:12:04 -0400127 response = main.FALSE
128 return response
129
kelvin8ec71442015-01-15 16:57:00 -0800130 def logout( self ):
131 """
andrewonlab38d2b4a2014-11-13 16:28:47 -0500132 Sends 'logout' command to ONOS cli
Jon Hall61282e32015-03-19 11:34:11 -0700133 Returns main.TRUE if exited CLI and
134 main.FALSE on timeout (not guranteed you are disconnected)
135 None on TypeError
136 Exits test on unknown error or pexpect exits unexpectedly
kelvin8ec71442015-01-15 16:57:00 -0800137 """
andrewonlab38d2b4a2014-11-13 16:28:47 -0500138 try:
Jon Hall61282e32015-03-19 11:34:11 -0700139 if self.handle:
140 self.handle.sendline( "" )
141 i = self.handle.expect( [ "onos>", "\$", pexpect.TIMEOUT ],
142 timeout=10 )
143 if i == 0: # In ONOS CLI
144 self.handle.sendline( "logout" )
Jon Hallbfe00002016-04-05 10:23:54 -0700145 j = self.handle.expect( [ "\$",
146 "Command not found:",
147 pexpect.TIMEOUT ] )
148 if j == 0: # Successfully logged out
149 return main.TRUE
150 elif j == 1 or j == 2:
151 # ONOS didn't fully load, and logout command isn't working
152 # or the command timed out
153 self.handle.send( "\x04" ) # send ctrl-d
154 self.handle.expect( "\$" )
155 return main.TRUE
156 else: # some other output
157 main.log.warn( "Unknown repsonse to logout command: '{}'",
158 repr( self.handle.before ) )
159 return main.FALSE
Jon Hall61282e32015-03-19 11:34:11 -0700160 elif i == 1: # not in CLI
161 return main.TRUE
162 elif i == 3: # Timeout
163 return main.FALSE
164 else:
andrewonlab9627f432014-11-14 12:45:10 -0500165 return main.TRUE
Jon Halld4d4b372015-01-28 16:02:41 -0800166 except TypeError:
167 main.log.exception( self.name + ": Object not as expected" )
168 return None
andrewonlab38d2b4a2014-11-13 16:28:47 -0500169 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -0800170 main.log.error( self.name + ": eof exception found" )
Jon Hall61282e32015-03-19 11:34:11 -0700171 main.log.error( self.name + ": " + self.handle.before )
andrewonlab38d2b4a2014-11-13 16:28:47 -0500172 main.cleanup()
173 main.exit()
Jon Hall61282e32015-03-19 11:34:11 -0700174 except ValueError:
Jon Hall5aa168b2015-03-23 14:23:09 -0700175 main.log.error( self.name +
176 "ValueError exception in logout method" )
Jon Hallfebb1c72015-03-05 13:30:09 -0800177 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -0800178 main.log.exception( self.name + ": Uncaught exception!" )
andrewonlab38d2b4a2014-11-13 16:28:47 -0500179 main.cleanup()
180 main.exit()
181
kelvin-onlabd3b64892015-01-20 13:26:24 -0800182 def setCell( self, cellname ):
kelvin8ec71442015-01-15 16:57:00 -0800183 """
andrewonlab95ce8322014-10-13 14:12:04 -0400184 Calls 'cell <name>' to set the environment variables on ONOSbench
kelvin8ec71442015-01-15 16:57:00 -0800185
andrewonlab95ce8322014-10-13 14:12:04 -0400186 Before issuing any cli commands, set the environment variable first.
kelvin8ec71442015-01-15 16:57:00 -0800187 """
andrewonlab95ce8322014-10-13 14:12:04 -0400188 try:
189 if not cellname:
kelvin8ec71442015-01-15 16:57:00 -0800190 main.log.error( "Must define cellname" )
andrewonlab95ce8322014-10-13 14:12:04 -0400191 main.cleanup()
192 main.exit()
193 else:
kelvin8ec71442015-01-15 16:57:00 -0800194 self.handle.sendline( "cell " + str( cellname ) )
kelvin-onlabd3b64892015-01-20 13:26:24 -0800195 # Expect the cellname in the ONOSCELL variable.
kelvin8ec71442015-01-15 16:57:00 -0800196 # Note that this variable name is subject to change
andrewonlab95ce8322014-10-13 14:12:04 -0400197 # and that this driver will have to change accordingly
Cameron Franke9c94fb02015-01-21 10:20:20 -0800198 self.handle.expect(str(cellname))
andrew@onlab.usc400b112015-01-21 15:33:19 -0800199 handleBefore = self.handle.before
200 handleAfter = self.handle.after
kelvin8ec71442015-01-15 16:57:00 -0800201 # Get the rest of the handle
Cameron Franke9c94fb02015-01-21 10:20:20 -0800202 self.handle.sendline("")
203 self.handle.expect("\$")
andrew@onlab.usc400b112015-01-21 15:33:19 -0800204 handleMore = self.handle.before
andrewonlab95ce8322014-10-13 14:12:04 -0400205
kelvin-onlabd3b64892015-01-20 13:26:24 -0800206 main.log.info( "Cell call returned: " + handleBefore +
207 handleAfter + handleMore )
andrewonlab95ce8322014-10-13 14:12:04 -0400208
209 return main.TRUE
210
Jon Halld4d4b372015-01-28 16:02:41 -0800211 except TypeError:
212 main.log.exception( self.name + ": Object not as expected" )
213 return None
andrewonlab95ce8322014-10-13 14:12:04 -0400214 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -0800215 main.log.error( self.name + ": eof exception found" )
216 main.log.error( self.name + ": " + self.handle.before )
andrewonlab95ce8322014-10-13 14:12:04 -0400217 main.cleanup()
218 main.exit()
Jon Hallfebb1c72015-03-05 13:30:09 -0800219 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -0800220 main.log.exception( self.name + ": Uncaught exception!" )
andrewonlab95ce8322014-10-13 14:12:04 -0400221 main.cleanup()
222 main.exit()
kelvin8ec71442015-01-15 16:57:00 -0800223
pingping-lin57a56ce2015-05-20 16:43:48 -0700224 def startOnosCli( self, ONOSIp, karafTimeout="",
Jon Hallc6793552016-01-19 14:18:37 -0800225 commandlineTimeout=10, onosStartTimeout=60 ):
kelvin8ec71442015-01-15 16:57:00 -0800226 """
Jon Hallefbd9792015-03-05 16:11:36 -0800227 karafTimeout is an optional argument. karafTimeout value passed
kelvin-onlabd3b64892015-01-20 13:26:24 -0800228 by user would be used to set the current karaf shell idle timeout.
229 Note that when ever this property is modified the shell will exit and
Hari Krishnad7b9c202015-01-05 10:38:14 -0800230 the subsequent login would reflect new idle timeout.
kelvin-onlabd3b64892015-01-20 13:26:24 -0800231 Below is an example to start a session with 60 seconds idle timeout
232 ( input value is in milliseconds ):
kelvin8ec71442015-01-15 16:57:00 -0800233
Hari Krishna25d42f72015-01-05 15:08:28 -0800234 tValue = "60000"
kelvin-onlabd3b64892015-01-20 13:26:24 -0800235 main.ONOScli1.startOnosCli( ONOSIp, karafTimeout=tValue )
kelvin8ec71442015-01-15 16:57:00 -0800236
kelvin-onlabd3b64892015-01-20 13:26:24 -0800237 Note: karafTimeout is left as str so that this could be read
238 and passed to startOnosCli from PARAMS file as str.
kelvin8ec71442015-01-15 16:57:00 -0800239 """
You Wangf69ab392016-01-26 16:34:38 -0800240 self.onosIp = ONOSIp
andrewonlab95ce8322014-10-13 14:12:04 -0400241 try:
kelvin8ec71442015-01-15 16:57:00 -0800242 self.handle.sendline( "" )
243 x = self.handle.expect( [
pingping-lin57a56ce2015-05-20 16:43:48 -0700244 "\$", "onos>" ], commandlineTimeout)
andrewonlab48829f62014-11-17 13:49:01 -0500245
246 if x == 1:
kelvin8ec71442015-01-15 16:57:00 -0800247 main.log.info( "ONOS cli is already running" )
andrewonlab48829f62014-11-17 13:49:01 -0500248 return main.TRUE
andrewonlab95ce8322014-10-13 14:12:04 -0400249
kelvin8ec71442015-01-15 16:57:00 -0800250 # Wait for onos start ( -w ) and enter onos cli
kelvin-onlabd3b64892015-01-20 13:26:24 -0800251 self.handle.sendline( "onos -w " + str( ONOSIp ) )
kelvin8ec71442015-01-15 16:57:00 -0800252 i = self.handle.expect( [
253 "onos>",
pingping-lin57a56ce2015-05-20 16:43:48 -0700254 pexpect.TIMEOUT ], onosStartTimeout )
andrewonlab2a7ea9b2014-10-24 12:21:05 -0400255
256 if i == 0:
kelvin-onlabd3b64892015-01-20 13:26:24 -0800257 main.log.info( str( ONOSIp ) + " CLI Started successfully" )
Hari Krishnae36ef212015-01-04 14:09:13 -0800258 if karafTimeout:
kelvin8ec71442015-01-15 16:57:00 -0800259 self.handle.sendline(
Hari Krishnaac4e1782015-01-26 12:09:12 -0800260 "config:property-set -p org.apache.karaf.shell\
261 sshIdleTimeout " +
kelvin8ec71442015-01-15 16:57:00 -0800262 karafTimeout )
263 self.handle.expect( "\$" )
kelvin-onlabd3b64892015-01-20 13:26:24 -0800264 self.handle.sendline( "onos -w " + str( ONOSIp ) )
kelvin8ec71442015-01-15 16:57:00 -0800265 self.handle.expect( "onos>" )
andrewonlab2a7ea9b2014-10-24 12:21:05 -0400266 return main.TRUE
267 else:
kelvin8ec71442015-01-15 16:57:00 -0800268 # If failed, send ctrl+c to process and try again
269 main.log.info( "Starting CLI failed. Retrying..." )
270 self.handle.send( "\x03" )
kelvin-onlabd3b64892015-01-20 13:26:24 -0800271 self.handle.sendline( "onos -w " + str( ONOSIp ) )
kelvin8ec71442015-01-15 16:57:00 -0800272 i = self.handle.expect( [ "onos>", pexpect.TIMEOUT ],
273 timeout=30 )
andrewonlab3a7c3c72014-10-24 17:21:03 -0400274 if i == 0:
kelvin-onlabd3b64892015-01-20 13:26:24 -0800275 main.log.info( str( ONOSIp ) + " CLI Started " +
kelvin8ec71442015-01-15 16:57:00 -0800276 "successfully after retry attempt" )
Hari Krishnae36ef212015-01-04 14:09:13 -0800277 if karafTimeout:
kelvin8ec71442015-01-15 16:57:00 -0800278 self.handle.sendline(
kelvin-onlabd3b64892015-01-20 13:26:24 -0800279 "config:property-set -p org.apache.karaf.shell\
280 sshIdleTimeout " +
kelvin8ec71442015-01-15 16:57:00 -0800281 karafTimeout )
282 self.handle.expect( "\$" )
kelvin-onlabd3b64892015-01-20 13:26:24 -0800283 self.handle.sendline( "onos -w " + str( ONOSIp ) )
kelvin8ec71442015-01-15 16:57:00 -0800284 self.handle.expect( "onos>" )
andrewonlab3a7c3c72014-10-24 17:21:03 -0400285 return main.TRUE
286 else:
kelvin8ec71442015-01-15 16:57:00 -0800287 main.log.error( "Connection to CLI " +
kelvin-onlabd3b64892015-01-20 13:26:24 -0800288 str( ONOSIp ) + " timeout" )
andrewonlab3a7c3c72014-10-24 17:21:03 -0400289 return main.FALSE
andrewonlab95ce8322014-10-13 14:12:04 -0400290
Jon Halld4d4b372015-01-28 16:02:41 -0800291 except TypeError:
292 main.log.exception( self.name + ": Object not as expected" )
293 return None
andrewonlab95ce8322014-10-13 14:12:04 -0400294 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -0800295 main.log.error( self.name + ": EOF exception found" )
296 main.log.error( self.name + ": " + self.handle.before )
andrewonlab95ce8322014-10-13 14:12:04 -0400297 main.cleanup()
298 main.exit()
Jon Hallfebb1c72015-03-05 13:30:09 -0800299 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -0800300 main.log.exception( self.name + ": Uncaught exception!" )
andrewonlab95ce8322014-10-13 14:12:04 -0400301 main.cleanup()
302 main.exit()
303
Jon Hallefbd9792015-03-05 16:11:36 -0800304 def log( self, cmdStr, level="" ):
kelvin-onlab9f541032015-02-04 16:19:53 -0800305 """
306 log the commands in the onos CLI.
kelvin-onlab338f5512015-02-06 10:53:16 -0800307 returns main.TRUE on success
Jon Hallefbd9792015-03-05 16:11:36 -0800308 returns main.FALSE if Error occurred
kelvin-onlab338f5512015-02-06 10:53:16 -0800309 Available level: DEBUG, TRACE, INFO, WARN, ERROR
310 Level defaults to INFO
kelvin-onlab9f541032015-02-04 16:19:53 -0800311 """
312 try:
kelvin-onlab338f5512015-02-06 10:53:16 -0800313 lvlStr = ""
314 if level:
315 lvlStr = "--level=" + level
316
kelvin-onlab9f541032015-02-04 16:19:53 -0800317 self.handle.sendline( "" )
Jon Hallc6793552016-01-19 14:18:37 -0800318 i = self.handle.expect( [ "onos>", "\$", pexpect.TIMEOUT ] )
Jon Hall80daded2015-05-27 16:07:00 -0700319 if i == 1:
You Wangf69ab392016-01-26 16:34:38 -0800320 main.log.error( self.name + ": onos cli session closed. ")
321 if self.onosIp:
322 main.log.warn( "Trying to reconnect " + self.onosIp )
323 reconnectResult = self.startOnosCli( self.onosIp )
324 if reconnectResult:
325 main.log.info( self.name + ": onos cli session reconnected." )
326 else:
327 main.log.error( self.name + ": reconnection failed." )
328 main.cleanup()
329 main.exit()
330 else:
331 main.cleanup()
332 main.exit()
Jon Hallc9eabec2015-06-10 14:33:14 -0700333 if i == 2:
Jon Hall80daded2015-05-27 16:07:00 -0700334 self.handle.sendline( "" )
335 self.handle.expect( "onos>" )
kelvin-onlab338f5512015-02-06 10:53:16 -0800336 self.handle.sendline( "log:log " + lvlStr + " " + cmdStr )
Jon Hall390696c2015-05-05 17:13:41 -0700337 self.handle.expect( "log:log" )
kelvin-onlab9f541032015-02-04 16:19:53 -0800338 self.handle.expect( "onos>" )
kelvin-onlabfb521662015-02-27 09:52:40 -0800339
kelvin-onlab9f541032015-02-04 16:19:53 -0800340 response = self.handle.before
341 if re.search( "Error", response ):
342 return main.FALSE
343 return main.TRUE
Jon Hall80daded2015-05-27 16:07:00 -0700344 except pexpect.TIMEOUT:
345 main.log.exception( self.name + ": TIMEOUT exception found" )
346 main.cleanup()
347 main.exit()
kelvin-onlab9f541032015-02-04 16:19:53 -0800348 except pexpect.EOF:
349 main.log.error( self.name + ": EOF exception found" )
350 main.log.error( self.name + ": " + self.handle.before )
351 main.cleanup()
352 main.exit()
Jon Hallfebb1c72015-03-05 13:30:09 -0800353 except Exception:
kelvin-onlabfb521662015-02-27 09:52:40 -0800354 main.log.exception( self.name + ": Uncaught exception!" )
andrewonlab95ce8322014-10-13 14:12:04 -0400355 main.cleanup()
356 main.exit()
357
GlennRCed771242016-01-13 17:02:47 -0800358 def sendline( self, cmdStr, showResponse=False, debug=False, timeout=10 ):
kelvin8ec71442015-01-15 16:57:00 -0800359 """
Jon Halle3f39ff2015-01-13 11:50:53 -0800360 Send a completely user specified string to
361 the onos> prompt. Use this function if you have
andrewonlaba18f6bf2014-10-13 19:31:54 -0400362 a very specific command to send.
Jon Halle3f39ff2015-01-13 11:50:53 -0800363
andrewonlaba18f6bf2014-10-13 19:31:54 -0400364 Warning: There are no sanity checking to commands
365 sent using this method.
GlennRCed771242016-01-13 17:02:47 -0800366
kelvin8ec71442015-01-15 16:57:00 -0800367 """
andrewonlaba18f6bf2014-10-13 19:31:54 -0400368 try:
kelvin-onlab338f5512015-02-06 10:53:16 -0800369 logStr = "\"Sending CLI command: '" + cmdStr + "'\""
370 self.log( logStr )
kelvin-onlabd3b64892015-01-20 13:26:24 -0800371 self.handle.sendline( cmdStr )
GlennRCed771242016-01-13 17:02:47 -0800372 i = self.handle.expect( ["onos>", "\$"], timeout )
Jon Hall63604932015-02-26 17:09:50 -0800373 response = self.handle.before
Jon Hall63604932015-02-26 17:09:50 -0800374 # TODO: do something with i
Jon Hallc6793552016-01-19 14:18:37 -0800375 main.log.info( "Command '" + str( cmdStr ) + "' sent to "
376 + self.name + "." )
Jon Hallc6358dd2015-04-10 12:44:28 -0700377 if debug:
Jon Hall390696c2015-05-05 17:13:41 -0700378 main.log.debug( self.name + ": Raw output" )
379 main.log.debug( self.name + ": " + repr( response ) )
Jon Hallc6358dd2015-04-10 12:44:28 -0700380
381 # Remove ANSI color control strings from output
kelvin-onlabd3b64892015-01-20 13:26:24 -0800382 ansiEscape = re.compile( r'\x1b[^m]*m' )
Jon Hall63604932015-02-26 17:09:50 -0800383 response = ansiEscape.sub( '', response )
Jon Hallc6358dd2015-04-10 12:44:28 -0700384 if debug:
Jon Hall390696c2015-05-05 17:13:41 -0700385 main.log.debug( self.name + ": ansiEscape output" )
386 main.log.debug( self.name + ": " + repr( response ) )
Jon Hallc6358dd2015-04-10 12:44:28 -0700387
kelvin-onlabfb521662015-02-27 09:52:40 -0800388 # Remove extra return chars that get added
Jon Hall63604932015-02-26 17:09:50 -0800389 response = re.sub( r"\s\r", "", response )
Jon Hallc6358dd2015-04-10 12:44:28 -0700390 if debug:
Jon Hall390696c2015-05-05 17:13:41 -0700391 main.log.debug( self.name + ": Removed extra returns " +
392 "from output" )
393 main.log.debug( self.name + ": " + repr( response ) )
Jon Hallc6358dd2015-04-10 12:44:28 -0700394
395 # Strip excess whitespace
Jon Hall63604932015-02-26 17:09:50 -0800396 response = response.strip()
Jon Hallc6358dd2015-04-10 12:44:28 -0700397 if debug:
Jon Hall390696c2015-05-05 17:13:41 -0700398 main.log.debug( self.name + ": parsed and stripped output" )
399 main.log.debug( self.name + ": " + repr( response ) )
Jon Hallc6358dd2015-04-10 12:44:28 -0700400
Jon Hall63604932015-02-26 17:09:50 -0800401 # parse for just the output, remove the cmd from response
Jon Hallc6358dd2015-04-10 12:44:28 -0700402 output = response.split( cmdStr.strip(), 1 )
403 if debug:
Jon Hall390696c2015-05-05 17:13:41 -0700404 main.log.debug( self.name + ": split output" )
Jon Hallc6358dd2015-04-10 12:44:28 -0700405 for r in output:
Jon Hall390696c2015-05-05 17:13:41 -0700406 main.log.debug( self.name + ": " + repr( r ) )
GlennRC85870432015-11-23 11:45:51 -0800407 output = output[1].strip()
408 if showResponse:
GlennRCed771242016-01-13 17:02:47 -0800409 main.log.info( "Response from ONOS: {}".format( output ) )
GlennRC85870432015-11-23 11:45:51 -0800410 return output
GlennRCed771242016-01-13 17:02:47 -0800411 except pexpect.TIMEOUT:
412 main.log.error( self.name + ":ONOS timeout" )
413 if debug:
414 main.log.debug( self.handle.before )
415 return None
Jon Hallc6358dd2015-04-10 12:44:28 -0700416 except IndexError:
417 main.log.exception( self.name + ": Object not as expected" )
418 return None
Jon Halld4d4b372015-01-28 16:02:41 -0800419 except TypeError:
420 main.log.exception( self.name + ": Object not as expected" )
421 return None
andrewonlaba18f6bf2014-10-13 19:31:54 -0400422 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -0800423 main.log.error( self.name + ": EOF exception found" )
424 main.log.error( self.name + ": " + self.handle.before )
andrewonlaba18f6bf2014-10-13 19:31:54 -0400425 main.cleanup()
426 main.exit()
Jon Hallfebb1c72015-03-05 13:30:09 -0800427 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -0800428 main.log.exception( self.name + ": Uncaught exception!" )
andrewonlaba18f6bf2014-10-13 19:31:54 -0400429 main.cleanup()
430 main.exit()
431
kelvin8ec71442015-01-15 16:57:00 -0800432 # IMPORTANT NOTE:
433 # For all cli commands, naming convention should match
kelvin-onlabd3b64892015-01-20 13:26:24 -0800434 # the cli command changing 'a:b' with 'aB'.
435 # Ex ) onos:topology > onosTopology
436 # onos:links > onosLinks
437 # feature:list > featureList
Jon Halle3f39ff2015-01-13 11:50:53 -0800438
kelvin-onlabd3b64892015-01-20 13:26:24 -0800439 def addNode( self, nodeId, ONOSIp, tcpPort="" ):
kelvin8ec71442015-01-15 16:57:00 -0800440 """
andrewonlabc2d05aa2014-10-13 16:51:10 -0400441 Adds a new cluster node by ID and address information.
442 Required:
kelvin-onlabd3b64892015-01-20 13:26:24 -0800443 * nodeId
444 * ONOSIp
andrewonlabc2d05aa2014-10-13 16:51:10 -0400445 Optional:
kelvin-onlabd3b64892015-01-20 13:26:24 -0800446 * tcpPort
kelvin8ec71442015-01-15 16:57:00 -0800447 """
andrewonlabc2d05aa2014-10-13 16:51:10 -0400448 try:
kelvin-onlabd3b64892015-01-20 13:26:24 -0800449 cmdStr = "add-node " + str( nodeId ) + " " +\
450 str( ONOSIp ) + " " + str( tcpPort )
451 handle = self.sendline( cmdStr )
Jon Hallc6793552016-01-19 14:18:37 -0800452 assert "Command not found:" not in handle, handle
kelvin-onlab898a6c62015-01-16 14:13:53 -0800453 if re.search( "Error", handle ):
kelvin8ec71442015-01-15 16:57:00 -0800454 main.log.error( "Error in adding node" )
455 main.log.error( handle )
Jon Halle3f39ff2015-01-13 11:50:53 -0800456 return main.FALSE
andrewonlabc2d05aa2014-10-13 16:51:10 -0400457 else:
kelvin-onlabd3b64892015-01-20 13:26:24 -0800458 main.log.info( "Node " + str( ONOSIp ) + " added" )
andrewonlabc2d05aa2014-10-13 16:51:10 -0400459 return main.TRUE
Jon Hallc6793552016-01-19 14:18:37 -0800460 except AssertionError:
461 main.log.exception( "" )
462 return None
Jon Halld4d4b372015-01-28 16:02:41 -0800463 except TypeError:
464 main.log.exception( self.name + ": Object not as expected" )
465 return None
andrewonlabc2d05aa2014-10-13 16:51:10 -0400466 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -0800467 main.log.error( self.name + ": EOF exception found" )
468 main.log.error( self.name + ": " + self.handle.before )
andrewonlabc2d05aa2014-10-13 16:51:10 -0400469 main.cleanup()
470 main.exit()
Jon Hallfebb1c72015-03-05 13:30:09 -0800471 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -0800472 main.log.exception( self.name + ": Uncaught exception!" )
andrewonlabc2d05aa2014-10-13 16:51:10 -0400473 main.cleanup()
474 main.exit()
475
kelvin-onlabd3b64892015-01-20 13:26:24 -0800476 def removeNode( self, nodeId ):
kelvin8ec71442015-01-15 16:57:00 -0800477 """
andrewonlab86dc3082014-10-13 18:18:38 -0400478 Removes a cluster by ID
479 Issues command: 'remove-node [<node-id>]'
480 Required:
kelvin-onlabd3b64892015-01-20 13:26:24 -0800481 * nodeId
kelvin8ec71442015-01-15 16:57:00 -0800482 """
andrewonlab86dc3082014-10-13 18:18:38 -0400483 try:
andrewonlab86dc3082014-10-13 18:18:38 -0400484
kelvin-onlabd3b64892015-01-20 13:26:24 -0800485 cmdStr = "remove-node " + str( nodeId )
Jon Hall08f61bc2015-04-13 16:00:30 -0700486 handle = self.sendline( cmdStr )
Jon Hallc6793552016-01-19 14:18:37 -0800487 assert "Command not found:" not in handle, handle
Jon Hallc6358dd2015-04-10 12:44:28 -0700488 if re.search( "Error", handle ):
489 main.log.error( "Error in removing node" )
490 main.log.error( handle )
491 return main.FALSE
492 else:
493 return main.TRUE
Jon Hallc6793552016-01-19 14:18:37 -0800494 except AssertionError:
495 main.log.exception( "" )
496 return None
Jon Halld4d4b372015-01-28 16:02:41 -0800497 except TypeError:
498 main.log.exception( self.name + ": Object not as expected" )
499 return None
andrewonlab86dc3082014-10-13 18:18:38 -0400500 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -0800501 main.log.error( self.name + ": EOF exception found" )
502 main.log.error( self.name + ": " + self.handle.before )
andrewonlab86dc3082014-10-13 18:18:38 -0400503 main.cleanup()
504 main.exit()
Jon Hallfebb1c72015-03-05 13:30:09 -0800505 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -0800506 main.log.exception( self.name + ": Uncaught exception!" )
andrewonlab86dc3082014-10-13 18:18:38 -0400507 main.cleanup()
508 main.exit()
andrewonlabc2d05aa2014-10-13 16:51:10 -0400509
Jon Hall61282e32015-03-19 11:34:11 -0700510 def nodes( self, jsonFormat=True):
kelvin8ec71442015-01-15 16:57:00 -0800511 """
andrewonlab7c211572014-10-15 16:45:20 -0400512 List the nodes currently visible
513 Issues command: 'nodes'
Jon Hall61282e32015-03-19 11:34:11 -0700514 Optional argument:
515 * jsonFormat - boolean indicating if you want output in json
kelvin8ec71442015-01-15 16:57:00 -0800516 """
andrewonlab7c211572014-10-15 16:45:20 -0400517 try:
Jon Hallc6358dd2015-04-10 12:44:28 -0700518 cmdStr = "nodes"
Jon Hall61282e32015-03-19 11:34:11 -0700519 if jsonFormat:
Jon Hallc6358dd2015-04-10 12:44:28 -0700520 cmdStr += " -j"
521 output = self.sendline( cmdStr )
Jon Hallc6793552016-01-19 14:18:37 -0800522 assert "Command not found:" not in output, output
Jon Hallc6358dd2015-04-10 12:44:28 -0700523 return output
Jon Hallc6793552016-01-19 14:18:37 -0800524 except AssertionError:
525 main.log.exception( "" )
526 return None
Jon Halld4d4b372015-01-28 16:02:41 -0800527 except TypeError:
528 main.log.exception( self.name + ": Object not as expected" )
529 return None
andrewonlab7c211572014-10-15 16:45:20 -0400530 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -0800531 main.log.error( self.name + ": EOF exception found" )
532 main.log.error( self.name + ": " + self.handle.before )
andrewonlab7c211572014-10-15 16:45:20 -0400533 main.cleanup()
534 main.exit()
Jon Hallfebb1c72015-03-05 13:30:09 -0800535 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -0800536 main.log.exception( self.name + ": Uncaught exception!" )
andrewonlab7c211572014-10-15 16:45:20 -0400537 main.cleanup()
538 main.exit()
539
kelvin8ec71442015-01-15 16:57:00 -0800540 def topology( self ):
541 """
Hari Krishnaef1bd4e2015-03-12 16:55:30 -0700542 Definition:
Jon Hall390696c2015-05-05 17:13:41 -0700543 Returns the output of topology command.
Hari Krishnaef1bd4e2015-03-12 16:55:30 -0700544 Return:
545 topology = current ONOS topology
kelvin8ec71442015-01-15 16:57:00 -0800546 """
andrewonlab95ce8322014-10-13 14:12:04 -0400547 try:
Hari Krishnaef1bd4e2015-03-12 16:55:30 -0700548 cmdStr = "topology -j"
kelvin-onlabd3b64892015-01-20 13:26:24 -0800549 handle = self.sendline( cmdStr )
Jon Hallc6793552016-01-19 14:18:37 -0800550 assert "Command not found:" not in handle, handle
Jon Hallc6358dd2015-04-10 12:44:28 -0700551 main.log.info( cmdStr + " returned: " + str( handle ) )
andrewonlab95ce8322014-10-13 14:12:04 -0400552 return handle
Jon Hallc6793552016-01-19 14:18:37 -0800553 except AssertionError:
554 main.log.exception( "" )
Jon Halld4d4b372015-01-28 16:02:41 -0800555 return None
Jon Halld4d4b372015-01-28 16:02:41 -0800556 except TypeError:
557 main.log.exception( self.name + ": Object not as expected" )
558 return None
andrewonlabc2d05aa2014-10-13 16:51:10 -0400559 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -0800560 main.log.error( self.name + ": EOF exception found" )
561 main.log.error( self.name + ": " + self.handle.before )
andrewonlabc2d05aa2014-10-13 16:51:10 -0400562 main.cleanup()
563 main.exit()
Jon Hallfebb1c72015-03-05 13:30:09 -0800564 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -0800565 main.log.exception( self.name + ": Uncaught exception!" )
andrewonlabc2d05aa2014-10-13 16:51:10 -0400566 main.cleanup()
567 main.exit()
Jon Hallffb386d2014-11-21 13:43:38 -0800568
jenkins7ead5a82015-03-13 10:28:21 -0700569 def deviceRemove( self, deviceId ):
570 """
571 Removes particular device from storage
572
573 TODO: refactor this function
574 """
575 try:
Jon Hallc6358dd2015-04-10 12:44:28 -0700576 cmdStr = "device-remove " + str( deviceId )
577 handle = self.sendline( cmdStr )
Jon Hallc6793552016-01-19 14:18:37 -0800578 assert "Command not found:" not in handle, handle
Jon Hallc6358dd2015-04-10 12:44:28 -0700579 if re.search( "Error", handle ):
580 main.log.error( "Error in removing device" )
581 main.log.error( handle )
582 return main.FALSE
583 else:
584 return main.TRUE
Jon Hallc6793552016-01-19 14:18:37 -0800585 except AssertionError:
586 main.log.exception( "" )
587 return None
jenkins7ead5a82015-03-13 10:28:21 -0700588 except TypeError:
589 main.log.exception( self.name + ": Object not as expected" )
590 return None
591 except pexpect.EOF:
592 main.log.error( self.name + ": EOF exception found" )
593 main.log.error( self.name + ": " + self.handle.before )
594 main.cleanup()
595 main.exit()
596 except Exception:
597 main.log.exception( self.name + ": Uncaught exception!" )
598 main.cleanup()
599 main.exit()
jenkins7ead5a82015-03-13 10:28:21 -0700600
kelvin-onlabd3b64892015-01-20 13:26:24 -0800601 def devices( self, jsonFormat=True ):
kelvin8ec71442015-01-15 16:57:00 -0800602 """
Jon Hall7b02d952014-10-17 20:14:54 -0400603 Lists all infrastructure devices or switches
andrewonlab86dc3082014-10-13 18:18:38 -0400604 Optional argument:
kelvin-onlabd3b64892015-01-20 13:26:24 -0800605 * jsonFormat - boolean indicating if you want output in json
kelvin8ec71442015-01-15 16:57:00 -0800606 """
andrewonlab86dc3082014-10-13 18:18:38 -0400607 try:
Jon Hallc6358dd2015-04-10 12:44:28 -0700608 cmdStr = "devices"
kelvin-onlabd3b64892015-01-20 13:26:24 -0800609 if jsonFormat:
Jon Hallc6358dd2015-04-10 12:44:28 -0700610 cmdStr += " -j"
611 handle = self.sendline( cmdStr )
Jon Hallc6793552016-01-19 14:18:37 -0800612 assert "Command not found:" not in handle, handle
Jon Hallc6358dd2015-04-10 12:44:28 -0700613 return handle
Jon Hallc6793552016-01-19 14:18:37 -0800614 except AssertionError:
615 main.log.exception( "" )
616 return None
Jon Halld4d4b372015-01-28 16:02:41 -0800617 except TypeError:
618 main.log.exception( self.name + ": Object not as expected" )
619 return None
andrewonlab7c211572014-10-15 16:45:20 -0400620 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -0800621 main.log.error( self.name + ": EOF exception found" )
622 main.log.error( self.name + ": " + self.handle.before )
andrewonlab7c211572014-10-15 16:45:20 -0400623 main.cleanup()
624 main.exit()
Jon Hallfebb1c72015-03-05 13:30:09 -0800625 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -0800626 main.log.exception( self.name + ": Uncaught exception!" )
andrewonlab7c211572014-10-15 16:45:20 -0400627 main.cleanup()
628 main.exit()
629
kelvin-onlabd3b64892015-01-20 13:26:24 -0800630 def balanceMasters( self ):
kelvin8ec71442015-01-15 16:57:00 -0800631 """
Hari Krishnaa43d4e92014-12-19 13:22:40 -0800632 This balances the devices across all controllers
633 by issuing command: 'onos> onos:balance-masters'
634 If required this could be extended to return devices balanced output.
kelvin8ec71442015-01-15 16:57:00 -0800635 """
Hari Krishnaa43d4e92014-12-19 13:22:40 -0800636 try:
kelvin-onlabd3b64892015-01-20 13:26:24 -0800637 cmdStr = "onos:balance-masters"
Jon Hallc6358dd2015-04-10 12:44:28 -0700638 handle = self.sendline( cmdStr )
Jon Hallc6793552016-01-19 14:18:37 -0800639 assert "Command not found:" not in handle, handle
Jon Hallc6358dd2015-04-10 12:44:28 -0700640 if re.search( "Error", handle ):
641 main.log.error( "Error in balancing masters" )
642 main.log.error( handle )
643 return main.FALSE
644 else:
645 return main.TRUE
Jon Hallc6793552016-01-19 14:18:37 -0800646 except AssertionError:
647 main.log.exception( "" )
648 return None
Jon Halld4d4b372015-01-28 16:02:41 -0800649 except TypeError:
650 main.log.exception( self.name + ": Object not as expected" )
651 return None
Hari Krishnaa43d4e92014-12-19 13:22:40 -0800652 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -0800653 main.log.error( self.name + ": EOF exception found" )
654 main.log.error( self.name + ": " + self.handle.before )
Hari Krishnaa43d4e92014-12-19 13:22:40 -0800655 main.cleanup()
656 main.exit()
Jon Hallfebb1c72015-03-05 13:30:09 -0800657 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -0800658 main.log.exception( self.name + ": Uncaught exception!" )
Hari Krishnaa43d4e92014-12-19 13:22:40 -0800659 main.cleanup()
660 main.exit()
661
Jon Hallc6793552016-01-19 14:18:37 -0800662 def checkMasters( self, jsonFormat=True ):
acsmars24950022015-07-30 18:00:43 -0700663 """
664 Returns the output of the masters command.
665 Optional argument:
666 * jsonFormat - boolean indicating if you want output in json
667 """
668 try:
669 cmdStr = "onos:masters"
670 if jsonFormat:
671 cmdStr += " -j"
672 output = self.sendline( cmdStr )
Jon Hallc6793552016-01-19 14:18:37 -0800673 assert "Command not found:" not in output, output
acsmars24950022015-07-30 18:00:43 -0700674 return output
Jon Hallc6793552016-01-19 14:18:37 -0800675 except AssertionError:
676 main.log.exception( "" )
677 return None
acsmars24950022015-07-30 18:00:43 -0700678 except TypeError:
679 main.log.exception( self.name + ": Object not as expected" )
680 return None
681 except pexpect.EOF:
682 main.log.error( self.name + ": EOF exception found" )
683 main.log.error( self.name + ": " + self.handle.before )
684 main.cleanup()
685 main.exit()
686 except Exception:
687 main.log.exception( self.name + ": Uncaught exception!" )
688 main.cleanup()
689 main.exit()
690
Jon Hallc6793552016-01-19 14:18:37 -0800691 def checkBalanceMasters( self, jsonFormat=True ):
acsmars24950022015-07-30 18:00:43 -0700692 """
693 Uses the master command to check that the devices' leadership
694 is evenly divided
695
696 Dependencies: checkMasters() and summary()
697
698 Returns main.True if the devices are balanced
699 Returns main.False if the devices are unbalanced
700 Exits on Exception
701 Returns None on TypeError
702 """
703 try:
Jon Hallc6793552016-01-19 14:18:37 -0800704 summaryOutput = self.summary()
705 totalDevices = json.loads( summaryOutput )[ "devices" ]
706 except ( TypeError, ValueError ):
707 main.log.exception( "{}: Object not as expected: {!r}".format( self.name, summaryOutput ) )
708 return None
709 try:
acsmars24950022015-07-30 18:00:43 -0700710 totalOwnedDevices = 0
Jon Hallc6793552016-01-19 14:18:37 -0800711 mastersOutput = self.checkMasters()
712 masters = json.loads( mastersOutput )
acsmars24950022015-07-30 18:00:43 -0700713 first = masters[ 0 ][ "size" ]
714 for master in masters:
715 totalOwnedDevices += master[ "size" ]
716 if master[ "size" ] > first + 1 or master[ "size" ] < first - 1:
717 main.log.error( "Mastership not balanced" )
718 main.log.info( "\n" + self.checkMasters( False ) )
719 return main.FALSE
720 main.log.info( "Mastership balanced between " \
721 + str( len(masters) ) + " masters" )
722 return main.TRUE
Jon Hallc6793552016-01-19 14:18:37 -0800723 except ( TypeError, ValueError ):
724 main.log.exception( "{}: Object not as expected: {!r}".format( self.name, mastersOutput ) )
acsmars24950022015-07-30 18:00:43 -0700725 return None
726 except pexpect.EOF:
727 main.log.error( self.name + ": EOF exception found" )
728 main.log.error( self.name + ": " + self.handle.before )
729 main.cleanup()
730 main.exit()
731 except Exception:
732 main.log.exception( self.name + ": Uncaught exception!" )
733 main.cleanup()
734 main.exit()
735
kelvin-onlabd3b64892015-01-20 13:26:24 -0800736 def links( self, jsonFormat=True ):
kelvin8ec71442015-01-15 16:57:00 -0800737 """
Jon Halle8217482014-10-17 13:49:14 -0400738 Lists all core links
739 Optional argument:
kelvin-onlabd3b64892015-01-20 13:26:24 -0800740 * jsonFormat - boolean indicating if you want output in json
kelvin8ec71442015-01-15 16:57:00 -0800741 """
Jon Halle8217482014-10-17 13:49:14 -0400742 try:
Jon Hallc6358dd2015-04-10 12:44:28 -0700743 cmdStr = "links"
kelvin-onlabd3b64892015-01-20 13:26:24 -0800744 if jsonFormat:
Jon Hallc6358dd2015-04-10 12:44:28 -0700745 cmdStr += " -j"
746 handle = self.sendline( cmdStr )
Jon Hallc6793552016-01-19 14:18:37 -0800747 assert "Command not found:" not in handle, handle
Jon Hallc6358dd2015-04-10 12:44:28 -0700748 return handle
Jon Hallc6793552016-01-19 14:18:37 -0800749 except AssertionError:
750 main.log.exception( "" )
751 return None
Jon Halld4d4b372015-01-28 16:02:41 -0800752 except TypeError:
753 main.log.exception( self.name + ": Object not as expected" )
754 return None
Jon Halle8217482014-10-17 13:49:14 -0400755 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -0800756 main.log.error( self.name + ": EOF exception found" )
757 main.log.error( self.name + ": " + self.handle.before )
Jon Halle8217482014-10-17 13:49:14 -0400758 main.cleanup()
759 main.exit()
Jon Hallfebb1c72015-03-05 13:30:09 -0800760 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -0800761 main.log.exception( self.name + ": Uncaught exception!" )
Jon Halle8217482014-10-17 13:49:14 -0400762 main.cleanup()
763 main.exit()
764
kelvin-onlabd3b64892015-01-20 13:26:24 -0800765 def ports( self, jsonFormat=True ):
kelvin8ec71442015-01-15 16:57:00 -0800766 """
Jon Halle8217482014-10-17 13:49:14 -0400767 Lists all ports
768 Optional argument:
kelvin-onlabd3b64892015-01-20 13:26:24 -0800769 * jsonFormat - boolean indicating if you want output in json
kelvin8ec71442015-01-15 16:57:00 -0800770 """
Jon Halle8217482014-10-17 13:49:14 -0400771 try:
Jon Hallc6358dd2015-04-10 12:44:28 -0700772 cmdStr = "ports"
kelvin-onlabd3b64892015-01-20 13:26:24 -0800773 if jsonFormat:
Jon Hallc6358dd2015-04-10 12:44:28 -0700774 cmdStr += " -j"
775 handle = self.sendline( cmdStr )
Jon Hallc6793552016-01-19 14:18:37 -0800776 assert "Command not found:" not in handle, handle
Jon Hallc6358dd2015-04-10 12:44:28 -0700777 return handle
Jon Hallc6793552016-01-19 14:18:37 -0800778 except AssertionError:
779 main.log.exception( "" )
780 return None
Jon Halld4d4b372015-01-28 16:02:41 -0800781 except TypeError:
782 main.log.exception( self.name + ": Object not as expected" )
783 return None
Jon Halle8217482014-10-17 13:49:14 -0400784 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -0800785 main.log.error( self.name + ": EOF exception found" )
786 main.log.error( self.name + ": " + self.handle.before )
Jon Halle8217482014-10-17 13:49:14 -0400787 main.cleanup()
788 main.exit()
Jon Hallfebb1c72015-03-05 13:30:09 -0800789 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -0800790 main.log.exception( self.name + ": Uncaught exception!" )
Jon Halle8217482014-10-17 13:49:14 -0400791 main.cleanup()
792 main.exit()
793
kelvin-onlabd3b64892015-01-20 13:26:24 -0800794 def roles( self, jsonFormat=True ):
kelvin8ec71442015-01-15 16:57:00 -0800795 """
Jon Hall983a1702014-10-28 18:44:22 -0400796 Lists all devices and the controllers with roles assigned to them
797 Optional argument:
kelvin-onlabd3b64892015-01-20 13:26:24 -0800798 * jsonFormat - boolean indicating if you want output in json
kelvin8ec71442015-01-15 16:57:00 -0800799 """
andrewonlab7c211572014-10-15 16:45:20 -0400800 try:
Jon Hallc6358dd2015-04-10 12:44:28 -0700801 cmdStr = "roles"
kelvin-onlabd3b64892015-01-20 13:26:24 -0800802 if jsonFormat:
Jon Hallc6358dd2015-04-10 12:44:28 -0700803 cmdStr += " -j"
804 handle = self.sendline( cmdStr )
Jon Hallc6793552016-01-19 14:18:37 -0800805 assert "Command not found:" not in handle, handle
Jon Hallc6358dd2015-04-10 12:44:28 -0700806 return handle
Jon Hallc6793552016-01-19 14:18:37 -0800807 except AssertionError:
808 main.log.exception( "" )
809 return None
Jon Halld4d4b372015-01-28 16:02:41 -0800810 except TypeError:
811 main.log.exception( self.name + ": Object not as expected" )
812 return None
Jon Hall983a1702014-10-28 18:44:22 -0400813 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -0800814 main.log.error( self.name + ": EOF exception found" )
815 main.log.error( self.name + ": " + self.handle.before )
Jon Hall983a1702014-10-28 18:44:22 -0400816 main.cleanup()
817 main.exit()
Jon Hallfebb1c72015-03-05 13:30:09 -0800818 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -0800819 main.log.exception( self.name + ": Uncaught exception!" )
Jon Hall983a1702014-10-28 18:44:22 -0400820 main.cleanup()
821 main.exit()
822
kelvin-onlabd3b64892015-01-20 13:26:24 -0800823 def getRole( self, deviceId ):
kelvin-onlab898a6c62015-01-16 14:13:53 -0800824 """
Jon Halle3f39ff2015-01-13 11:50:53 -0800825 Given the a string containing the json representation of the "roles"
826 cli command and a partial or whole device id, returns a json object
827 containing the roles output for the first device whose id contains
828 "device_id"
Jon Hall983a1702014-10-28 18:44:22 -0400829
830 Returns:
Jon Halle3f39ff2015-01-13 11:50:53 -0800831 A dict of the role assignments for the given device or
832 None if no match
kelvin8ec71442015-01-15 16:57:00 -0800833 """
Jon Hall983a1702014-10-28 18:44:22 -0400834 try:
kelvin-onlabd3b64892015-01-20 13:26:24 -0800835 if deviceId is None:
Jon Hall983a1702014-10-28 18:44:22 -0400836 return None
837 else:
kelvin-onlabd3b64892015-01-20 13:26:24 -0800838 rawRoles = self.roles()
839 rolesJson = json.loads( rawRoles )
kelvin8ec71442015-01-15 16:57:00 -0800840 # search json for the device with id then return the device
kelvin-onlabd3b64892015-01-20 13:26:24 -0800841 for device in rolesJson:
kelvin8ec71442015-01-15 16:57:00 -0800842 # print device
kelvin-onlabd3b64892015-01-20 13:26:24 -0800843 if str( deviceId ) in device[ 'id' ]:
Jon Hall983a1702014-10-28 18:44:22 -0400844 return device
845 return None
Jon Hallc6793552016-01-19 14:18:37 -0800846 except ( TypeError, ValueError ):
847 main.log.exception( "{}: Object not as expected: {!r}".format( self.name, rawRoles ) )
Jon Halld4d4b372015-01-28 16:02:41 -0800848 return None
andrewonlab86dc3082014-10-13 18:18:38 -0400849 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -0800850 main.log.error( self.name + ": EOF exception found" )
851 main.log.error( self.name + ": " + self.handle.before )
andrewonlab86dc3082014-10-13 18:18:38 -0400852 main.cleanup()
853 main.exit()
Jon Hallfebb1c72015-03-05 13:30:09 -0800854 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -0800855 main.log.exception( self.name + ": Uncaught exception!" )
andrewonlab86dc3082014-10-13 18:18:38 -0400856 main.cleanup()
857 main.exit()
Jon Hall94fd0472014-12-08 11:52:42 -0800858
kelvin-onlabd3b64892015-01-20 13:26:24 -0800859 def rolesNotNull( self ):
kelvin8ec71442015-01-15 16:57:00 -0800860 """
Jon Hall94fd0472014-12-08 11:52:42 -0800861 Iterates through each device and checks if there is a master assigned
862 Returns: main.TRUE if each device has a master
863 main.FALSE any device has no master
kelvin8ec71442015-01-15 16:57:00 -0800864 """
Jon Hall94fd0472014-12-08 11:52:42 -0800865 try:
kelvin-onlabd3b64892015-01-20 13:26:24 -0800866 rawRoles = self.roles()
867 rolesJson = json.loads( rawRoles )
kelvin8ec71442015-01-15 16:57:00 -0800868 # search json for the device with id then return the device
kelvin-onlabd3b64892015-01-20 13:26:24 -0800869 for device in rolesJson:
kelvin8ec71442015-01-15 16:57:00 -0800870 # print device
871 if device[ 'master' ] == "none":
872 main.log.warn( "Device has no master: " + str( device ) )
Jon Hall94fd0472014-12-08 11:52:42 -0800873 return main.FALSE
874 return main.TRUE
Jon Hallc6793552016-01-19 14:18:37 -0800875 except ( TypeError, ValueError ):
876 main.log.exception( "{}: Object not as expected: {!r}".format( self.name, rawRoles ) )
Jon Halld4d4b372015-01-28 16:02:41 -0800877 return None
Jon Hall94fd0472014-12-08 11:52:42 -0800878 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -0800879 main.log.error( self.name + ": EOF exception found" )
880 main.log.error( self.name + ": " + self.handle.before )
Jon Hall94fd0472014-12-08 11:52:42 -0800881 main.cleanup()
882 main.exit()
Jon Hallfebb1c72015-03-05 13:30:09 -0800883 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -0800884 main.log.exception( self.name + ": Uncaught exception!" )
Jon Hall94fd0472014-12-08 11:52:42 -0800885 main.cleanup()
886 main.exit()
887
kelvin-onlabd3b64892015-01-20 13:26:24 -0800888 def paths( self, srcId, dstId ):
kelvin8ec71442015-01-15 16:57:00 -0800889 """
andrewonlab3e15ead2014-10-15 14:21:34 -0400890 Returns string of paths, and the cost.
891 Issues command: onos:paths <src> <dst>
kelvin8ec71442015-01-15 16:57:00 -0800892 """
andrewonlab3e15ead2014-10-15 14:21:34 -0400893 try:
kelvin-onlabd3b64892015-01-20 13:26:24 -0800894 cmdStr = "onos:paths " + str( srcId ) + " " + str( dstId )
895 handle = self.sendline( cmdStr )
Jon Hallc6793552016-01-19 14:18:37 -0800896 assert "Command not found:" not in handle, handle
Jon Halle3f39ff2015-01-13 11:50:53 -0800897 if re.search( "Error", handle ):
kelvin8ec71442015-01-15 16:57:00 -0800898 main.log.error( "Error in getting paths" )
899 return ( handle, "Error" )
andrewonlab3e15ead2014-10-15 14:21:34 -0400900 else:
kelvin8ec71442015-01-15 16:57:00 -0800901 path = handle.split( ";" )[ 0 ]
902 cost = handle.split( ";" )[ 1 ]
903 return ( path, cost )
Jon Hallc6793552016-01-19 14:18:37 -0800904 except AssertionError:
905 main.log.exception( "" )
906 return ( handle, "Error" )
Jon Halld4d4b372015-01-28 16:02:41 -0800907 except TypeError:
908 main.log.exception( self.name + ": Object not as expected" )
909 return ( handle, "Error" )
andrewonlab3e15ead2014-10-15 14:21:34 -0400910 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -0800911 main.log.error( self.name + ": EOF exception found" )
912 main.log.error( self.name + ": " + self.handle.before )
andrewonlab3e15ead2014-10-15 14:21:34 -0400913 main.cleanup()
914 main.exit()
Jon Hallfebb1c72015-03-05 13:30:09 -0800915 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -0800916 main.log.exception( self.name + ": Uncaught exception!" )
andrewonlab3e15ead2014-10-15 14:21:34 -0400917 main.cleanup()
918 main.exit()
Jon Hallffb386d2014-11-21 13:43:38 -0800919
kelvin-onlabd3b64892015-01-20 13:26:24 -0800920 def hosts( self, jsonFormat=True ):
kelvin8ec71442015-01-15 16:57:00 -0800921 """
Jon Hallffb386d2014-11-21 13:43:38 -0800922 Lists all discovered hosts
Jon Hall42db6dc2014-10-24 19:03:48 -0400923 Optional argument:
kelvin-onlabd3b64892015-01-20 13:26:24 -0800924 * jsonFormat - boolean indicating if you want output in json
kelvin8ec71442015-01-15 16:57:00 -0800925 """
Jon Hall42db6dc2014-10-24 19:03:48 -0400926 try:
Jon Hallc6358dd2015-04-10 12:44:28 -0700927 cmdStr = "hosts"
kelvin-onlabd3b64892015-01-20 13:26:24 -0800928 if jsonFormat:
Jon Hallc6358dd2015-04-10 12:44:28 -0700929 cmdStr += " -j"
930 handle = self.sendline( cmdStr )
Jeremyd9e4eb12016-04-13 12:09:06 -0700931 if handle:
932 assert "Command not found:" not in handle, handle
Jon Hallbaf53162015-12-17 17:04:34 -0800933 # TODO: Maybe make this less hardcoded
934 # ConsistentMap Exceptions
935 assert "org.onosproject.store.service" not in handle
936 # Node not leader
937 assert "java.lang.IllegalStateException" not in handle
Jon Hallbaf53162015-12-17 17:04:34 -0800938 main.log.error( "Error in processing '" + cmdStr + "' " +
939 "command: " + str( handle ) )
Jon Hallc6358dd2015-04-10 12:44:28 -0700940 return handle
Jon Hallc6793552016-01-19 14:18:37 -0800941 except AssertionError:
Jeremyd9e4eb12016-04-13 12:09:06 -0700942 main.log.exception( "Error in processing '" + cmdStr + "' " +
943 "command: " + str( handle ) )
Jon Hallc6793552016-01-19 14:18:37 -0800944 return None
Jon Halld4d4b372015-01-28 16:02:41 -0800945 except TypeError:
946 main.log.exception( self.name + ": Object not as expected" )
947 return None
Jon Hall42db6dc2014-10-24 19:03:48 -0400948 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -0800949 main.log.error( self.name + ": EOF exception found" )
950 main.log.error( self.name + ": " + self.handle.before )
Jon Hall42db6dc2014-10-24 19:03:48 -0400951 main.cleanup()
952 main.exit()
Jon Hallfebb1c72015-03-05 13:30:09 -0800953 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -0800954 main.log.exception( self.name + ": Uncaught exception!" )
Jon Hall42db6dc2014-10-24 19:03:48 -0400955 main.cleanup()
956 main.exit()
957
kelvin-onlabd3b64892015-01-20 13:26:24 -0800958 def getHost( self, mac ):
kelvin8ec71442015-01-15 16:57:00 -0800959 """
Jon Hall42db6dc2014-10-24 19:03:48 -0400960 Return the first host from the hosts api whose 'id' contains 'mac'
Jon Halle3f39ff2015-01-13 11:50:53 -0800961
Jon Hallefbd9792015-03-05 16:11:36 -0800962 Note: mac must be a colon separated mac address, but could be a
Jon Halle3f39ff2015-01-13 11:50:53 -0800963 partial mac address
964
Jon Hall42db6dc2014-10-24 19:03:48 -0400965 Return None if there is no match
kelvin8ec71442015-01-15 16:57:00 -0800966 """
Jon Hall42db6dc2014-10-24 19:03:48 -0400967 try:
kelvin8ec71442015-01-15 16:57:00 -0800968 if mac is None:
Jon Hall42db6dc2014-10-24 19:03:48 -0400969 return None
970 else:
971 mac = mac
kelvin-onlabd3b64892015-01-20 13:26:24 -0800972 rawHosts = self.hosts()
973 hostsJson = json.loads( rawHosts )
kelvin8ec71442015-01-15 16:57:00 -0800974 # search json for the host with mac then return the device
kelvin-onlabd3b64892015-01-20 13:26:24 -0800975 for host in hostsJson:
kelvin8ec71442015-01-15 16:57:00 -0800976 # print "%s in %s?" % ( mac, host[ 'id' ] )
Jon Halld4d4b372015-01-28 16:02:41 -0800977 if not host:
978 pass
979 elif mac in host[ 'id' ]:
Jon Hall42db6dc2014-10-24 19:03:48 -0400980 return host
981 return None
Jon Hallc6793552016-01-19 14:18:37 -0800982 except ( TypeError, ValueError ):
983 main.log.exception( "{}: Object not as expected: {!r}".format( self.name, rawHosts ) )
Jon Halld4d4b372015-01-28 16:02:41 -0800984 return None
Jon Hall42db6dc2014-10-24 19:03:48 -0400985 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -0800986 main.log.error( self.name + ": EOF exception found" )
987 main.log.error( self.name + ": " + self.handle.before )
Jon Hall42db6dc2014-10-24 19:03:48 -0400988 main.cleanup()
989 main.exit()
Jon Hallfebb1c72015-03-05 13:30:09 -0800990 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -0800991 main.log.exception( self.name + ": Uncaught exception!" )
Jon Hall42db6dc2014-10-24 19:03:48 -0400992 main.cleanup()
993 main.exit()
994
kelvin-onlabd3b64892015-01-20 13:26:24 -0800995 def getHostsId( self, hostList ):
kelvin8ec71442015-01-15 16:57:00 -0800996 """
997 Obtain list of hosts
andrewonlab3f0a4af2014-10-17 12:25:14 -0400998 Issues command: 'onos> hosts'
kelvin8ec71442015-01-15 16:57:00 -0800999
andrewonlab3f0a4af2014-10-17 12:25:14 -04001000 Required:
kelvin-onlabd3b64892015-01-20 13:26:24 -08001001 * hostList: List of hosts obtained by Mininet
andrewonlab3f0a4af2014-10-17 12:25:14 -04001002 IMPORTANT:
1003 This function assumes that you started your
kelvin8ec71442015-01-15 16:57:00 -08001004 topology with the option '--mac'.
andrewonlab3f0a4af2014-10-17 12:25:14 -04001005 Furthermore, it assumes that value of VLAN is '-1'
1006 Description:
kelvin8ec71442015-01-15 16:57:00 -08001007 Converts mininet hosts ( h1, h2, h3... ) into
1008 ONOS format ( 00:00:00:00:00:01/-1 , ... )
1009 """
andrewonlab3f0a4af2014-10-17 12:25:14 -04001010 try:
kelvin-onlabd3b64892015-01-20 13:26:24 -08001011 onosHostList = []
andrewonlab3f0a4af2014-10-17 12:25:14 -04001012
kelvin-onlabd3b64892015-01-20 13:26:24 -08001013 for host in hostList:
kelvin8ec71442015-01-15 16:57:00 -08001014 host = host.replace( "h", "" )
kelvin-onlabd3b64892015-01-20 13:26:24 -08001015 hostHex = hex( int( host ) ).zfill( 12 )
1016 hostHex = str( hostHex ).replace( 'x', '0' )
1017 i = iter( str( hostHex ) )
1018 hostHex = ":".join( a + b for a, b in zip( i, i ) )
1019 hostHex = hostHex + "/-1"
1020 onosHostList.append( hostHex )
andrewonlab3f0a4af2014-10-17 12:25:14 -04001021
kelvin-onlabd3b64892015-01-20 13:26:24 -08001022 return onosHostList
andrewonlab3f0a4af2014-10-17 12:25:14 -04001023
Jon Halld4d4b372015-01-28 16:02:41 -08001024 except TypeError:
1025 main.log.exception( self.name + ": Object not as expected" )
1026 return None
andrewonlab3f0a4af2014-10-17 12:25:14 -04001027 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08001028 main.log.error( self.name + ": EOF exception found" )
1029 main.log.error( self.name + ": " + self.handle.before )
andrewonlab3f0a4af2014-10-17 12:25:14 -04001030 main.cleanup()
1031 main.exit()
Jon Hallfebb1c72015-03-05 13:30:09 -08001032 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -08001033 main.log.exception( self.name + ": Uncaught exception!" )
andrewonlab3f0a4af2014-10-17 12:25:14 -04001034 main.cleanup()
1035 main.exit()
andrewonlab3e15ead2014-10-15 14:21:34 -04001036
kelvin-onlabd3b64892015-01-20 13:26:24 -08001037 def addHostIntent( self, hostIdOne, hostIdTwo ):
kelvin8ec71442015-01-15 16:57:00 -08001038 """
andrewonlabe6745342014-10-17 14:29:13 -04001039 Required:
kelvin-onlabd3b64892015-01-20 13:26:24 -08001040 * hostIdOne: ONOS host id for host1
1041 * hostIdTwo: ONOS host id for host2
andrewonlabe6745342014-10-17 14:29:13 -04001042 Description:
Jon Hallefbd9792015-03-05 16:11:36 -08001043 Adds a host-to-host intent ( bidirectional ) by
Jon Hallb1290e82014-11-18 16:17:48 -05001044 specifying the two hosts.
kelvin-onlabfb521662015-02-27 09:52:40 -08001045 Returns:
1046 A string of the intent id or None on Error
kelvin8ec71442015-01-15 16:57:00 -08001047 """
andrewonlabe6745342014-10-17 14:29:13 -04001048 try:
kelvin-onlabd3b64892015-01-20 13:26:24 -08001049 cmdStr = "add-host-intent " + str( hostIdOne ) +\
1050 " " + str( hostIdTwo )
1051 handle = self.sendline( cmdStr )
Jon Hallc6793552016-01-19 14:18:37 -08001052 assert "Command not found:" not in handle, handle
Hari Krishnaac4e1782015-01-26 12:09:12 -08001053 if re.search( "Error", handle ):
1054 main.log.error( "Error in adding Host intent" )
Jon Hall61282e32015-03-19 11:34:11 -07001055 main.log.debug( "Response from ONOS was: " + repr( handle ) )
kelvin-onlabfb521662015-02-27 09:52:40 -08001056 return None
Hari Krishnaac4e1782015-01-26 12:09:12 -08001057 else:
1058 main.log.info( "Host intent installed between " +
kelvin-onlabfb521662015-02-27 09:52:40 -08001059 str( hostIdOne ) + " and " + str( hostIdTwo ) )
1060 match = re.search('id=0x([\da-f]+),', handle)
1061 if match:
1062 return match.group()[3:-1]
1063 else:
1064 main.log.error( "Error, intent ID not found" )
Jon Hall61282e32015-03-19 11:34:11 -07001065 main.log.debug( "Response from ONOS was: " +
1066 repr( handle ) )
kelvin-onlabfb521662015-02-27 09:52:40 -08001067 return None
Jon Hallc6793552016-01-19 14:18:37 -08001068 except AssertionError:
1069 main.log.exception( "" )
1070 return None
Jon Halld4d4b372015-01-28 16:02:41 -08001071 except TypeError:
1072 main.log.exception( self.name + ": Object not as expected" )
1073 return None
andrewonlabe6745342014-10-17 14:29:13 -04001074 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08001075 main.log.error( self.name + ": EOF exception found" )
1076 main.log.error( self.name + ": " + self.handle.before )
andrewonlabe6745342014-10-17 14:29:13 -04001077 main.cleanup()
1078 main.exit()
Jon Hallfebb1c72015-03-05 13:30:09 -08001079 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -08001080 main.log.exception( self.name + ": Uncaught exception!" )
andrewonlabe6745342014-10-17 14:29:13 -04001081 main.cleanup()
1082 main.exit()
1083
kelvin-onlabd3b64892015-01-20 13:26:24 -08001084 def addOpticalIntent( self, ingressDevice, egressDevice ):
kelvin8ec71442015-01-15 16:57:00 -08001085 """
andrewonlab7b31d232014-10-24 13:31:47 -04001086 Required:
kelvin-onlabd3b64892015-01-20 13:26:24 -08001087 * ingressDevice: device id of ingress device
1088 * egressDevice: device id of egress device
andrewonlab7b31d232014-10-24 13:31:47 -04001089 Optional:
1090 TODO: Still needs to be implemented via dev side
kelvin-onlabfb521662015-02-27 09:52:40 -08001091 Description:
1092 Adds an optical intent by specifying an ingress and egress device
1093 Returns:
1094 A string of the intent id or None on error
kelvin-onlab898a6c62015-01-16 14:13:53 -08001095 """
andrewonlab7b31d232014-10-24 13:31:47 -04001096 try:
kelvin-onlabd3b64892015-01-20 13:26:24 -08001097 cmdStr = "add-optical-intent " + str( ingressDevice ) +\
1098 " " + str( egressDevice )
1099 handle = self.sendline( cmdStr )
Jon Hallc6793552016-01-19 14:18:37 -08001100 assert "Command not found:" not in handle, handle
kelvin-onlab898a6c62015-01-16 14:13:53 -08001101 # If error, return error message
Jon Halle3f39ff2015-01-13 11:50:53 -08001102 if re.search( "Error", handle ):
kelvin-onlabfb521662015-02-27 09:52:40 -08001103 main.log.error( "Error in adding Optical intent" )
1104 return None
andrewonlab7b31d232014-10-24 13:31:47 -04001105 else:
kelvin-onlabfb521662015-02-27 09:52:40 -08001106 main.log.info( "Optical intent installed between " +
1107 str( ingressDevice ) + " and " +
1108 str( egressDevice ) )
1109 match = re.search('id=0x([\da-f]+),', handle)
1110 if match:
1111 return match.group()[3:-1]
1112 else:
1113 main.log.error( "Error, intent ID not found" )
1114 return None
Jon Hallc6793552016-01-19 14:18:37 -08001115 except AssertionError:
1116 main.log.exception( "" )
1117 return None
Jon Halld4d4b372015-01-28 16:02:41 -08001118 except TypeError:
1119 main.log.exception( self.name + ": Object not as expected" )
1120 return None
andrewonlab7b31d232014-10-24 13:31:47 -04001121 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08001122 main.log.error( self.name + ": EOF exception found" )
1123 main.log.error( self.name + ": " + self.handle.before )
andrewonlab7b31d232014-10-24 13:31:47 -04001124 main.cleanup()
1125 main.exit()
Jon Hallfebb1c72015-03-05 13:30:09 -08001126 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -08001127 main.log.exception( self.name + ": Uncaught exception!" )
andrewonlab7b31d232014-10-24 13:31:47 -04001128 main.cleanup()
1129 main.exit()
1130
kelvin-onlabd3b64892015-01-20 13:26:24 -08001131 def addPointIntent(
kelvin-onlab898a6c62015-01-16 14:13:53 -08001132 self,
kelvin-onlabd3b64892015-01-20 13:26:24 -08001133 ingressDevice,
1134 egressDevice,
1135 portIngress="",
1136 portEgress="",
kelvin-onlab898a6c62015-01-16 14:13:53 -08001137 ethType="",
1138 ethSrc="",
1139 ethDst="",
1140 bandwidth="",
kelvin-onlabd3b64892015-01-20 13:26:24 -08001141 lambdaAlloc=False,
kelvin-onlab898a6c62015-01-16 14:13:53 -08001142 ipProto="",
1143 ipSrc="",
1144 ipDst="",
1145 tcpSrc="",
1146 tcpDst="" ):
kelvin8ec71442015-01-15 16:57:00 -08001147 """
andrewonlab4dbb4d82014-10-17 18:22:31 -04001148 Required:
kelvin-onlabd3b64892015-01-20 13:26:24 -08001149 * ingressDevice: device id of ingress device
1150 * egressDevice: device id of egress device
andrewonlab289e4b72014-10-21 21:24:18 -04001151 Optional:
1152 * ethType: specify ethType
kelvin8ec71442015-01-15 16:57:00 -08001153 * ethSrc: specify ethSrc ( i.e. src mac addr )
1154 * ethDst: specify ethDst ( i.e. dst mac addr )
andrewonlab0dbb6ec2014-11-06 13:46:55 -05001155 * bandwidth: specify bandwidth capacity of link
kelvin-onlabd3b64892015-01-20 13:26:24 -08001156 * lambdaAlloc: if True, intent will allocate lambda
andrewonlab40ccd8b2014-11-06 16:23:34 -05001157 for the specified intent
Jon Halle3f39ff2015-01-13 11:50:53 -08001158 * ipProto: specify ip protocol
andrewonlabf77e0cb2014-11-11 17:17:59 -05001159 * ipSrc: specify ip source address
1160 * ipDst: specify ip destination address
1161 * tcpSrc: specify tcp source port
1162 * tcpDst: specify tcp destination port
andrewonlab4dbb4d82014-10-17 18:22:31 -04001163 Description:
kelvin8ec71442015-01-15 16:57:00 -08001164 Adds a point-to-point intent ( uni-directional ) by
andrewonlab289e4b72014-10-21 21:24:18 -04001165 specifying device id's and optional fields
kelvin-onlabfb521662015-02-27 09:52:40 -08001166 Returns:
1167 A string of the intent id or None on error
andrewonlab289e4b72014-10-21 21:24:18 -04001168
Jon Halle3f39ff2015-01-13 11:50:53 -08001169 NOTE: This function may change depending on the
andrewonlab4dbb4d82014-10-17 18:22:31 -04001170 options developers provide for point-to-point
1171 intent via cli
kelvin8ec71442015-01-15 16:57:00 -08001172 """
andrewonlab4dbb4d82014-10-17 18:22:31 -04001173 try:
kelvin8ec71442015-01-15 16:57:00 -08001174 # If there are no optional arguments
andrewonlab0dbb6ec2014-11-06 13:46:55 -05001175 if not ethType and not ethSrc and not ethDst\
kelvin-onlabd3b64892015-01-20 13:26:24 -08001176 and not bandwidth and not lambdaAlloc \
andrewonlabfa4ff502014-11-11 16:41:30 -05001177 and not ipProto and not ipSrc and not ipDst \
1178 and not tcpSrc and not tcpDst:
andrewonlab36af3822014-11-18 17:48:18 -05001179 cmd = "add-point-intent"
andrewonlab36af3822014-11-18 17:48:18 -05001180
andrewonlab289e4b72014-10-21 21:24:18 -04001181 else:
andrewonlab36af3822014-11-18 17:48:18 -05001182 cmd = "add-point-intent"
Jon Halle3f39ff2015-01-13 11:50:53 -08001183
andrewonlab0c0a6772014-10-22 12:31:18 -04001184 if ethType:
kelvin8ec71442015-01-15 16:57:00 -08001185 cmd += " --ethType " + str( ethType )
andrewonlab289e4b72014-10-21 21:24:18 -04001186 if ethSrc:
kelvin8ec71442015-01-15 16:57:00 -08001187 cmd += " --ethSrc " + str( ethSrc )
1188 if ethDst:
1189 cmd += " --ethDst " + str( ethDst )
andrewonlab0dbb6ec2014-11-06 13:46:55 -05001190 if bandwidth:
kelvin8ec71442015-01-15 16:57:00 -08001191 cmd += " --bandwidth " + str( bandwidth )
kelvin-onlabd3b64892015-01-20 13:26:24 -08001192 if lambdaAlloc:
andrewonlabfa4ff502014-11-11 16:41:30 -05001193 cmd += " --lambda "
1194 if ipProto:
kelvin8ec71442015-01-15 16:57:00 -08001195 cmd += " --ipProto " + str( ipProto )
andrewonlabfa4ff502014-11-11 16:41:30 -05001196 if ipSrc:
kelvin8ec71442015-01-15 16:57:00 -08001197 cmd += " --ipSrc " + str( ipSrc )
andrewonlabfa4ff502014-11-11 16:41:30 -05001198 if ipDst:
kelvin8ec71442015-01-15 16:57:00 -08001199 cmd += " --ipDst " + str( ipDst )
andrewonlabfa4ff502014-11-11 16:41:30 -05001200 if tcpSrc:
kelvin8ec71442015-01-15 16:57:00 -08001201 cmd += " --tcpSrc " + str( tcpSrc )
andrewonlabfa4ff502014-11-11 16:41:30 -05001202 if tcpDst:
kelvin8ec71442015-01-15 16:57:00 -08001203 cmd += " --tcpDst " + str( tcpDst )
andrewonlab289e4b72014-10-21 21:24:18 -04001204
kelvin8ec71442015-01-15 16:57:00 -08001205 # Check whether the user appended the port
1206 # or provided it as an input
kelvin-onlabd3b64892015-01-20 13:26:24 -08001207 if "/" in ingressDevice:
1208 cmd += " " + str( ingressDevice )
andrewonlab36af3822014-11-18 17:48:18 -05001209 else:
kelvin-onlabd3b64892015-01-20 13:26:24 -08001210 if not portIngress:
kelvin-onlabfb521662015-02-27 09:52:40 -08001211 main.log.error( "You must specify the ingress port" )
kelvin8ec71442015-01-15 16:57:00 -08001212 # TODO: perhaps more meaningful return
kelvin-onlabfb521662015-02-27 09:52:40 -08001213 # Would it make sense to throw an exception and exit
1214 # the test?
1215 return None
andrewonlab36af3822014-11-18 17:48:18 -05001216
kelvin8ec71442015-01-15 16:57:00 -08001217 cmd += " " + \
kelvin-onlabd3b64892015-01-20 13:26:24 -08001218 str( ingressDevice ) + "/" +\
1219 str( portIngress ) + " "
andrewonlab36af3822014-11-18 17:48:18 -05001220
kelvin-onlabd3b64892015-01-20 13:26:24 -08001221 if "/" in egressDevice:
1222 cmd += " " + str( egressDevice )
andrewonlab36af3822014-11-18 17:48:18 -05001223 else:
kelvin-onlabd3b64892015-01-20 13:26:24 -08001224 if not portEgress:
kelvin-onlabfb521662015-02-27 09:52:40 -08001225 main.log.error( "You must specify the egress port" )
1226 return None
Jon Halle3f39ff2015-01-13 11:50:53 -08001227
kelvin8ec71442015-01-15 16:57:00 -08001228 cmd += " " +\
kelvin-onlabd3b64892015-01-20 13:26:24 -08001229 str( egressDevice ) + "/" +\
1230 str( portEgress )
kelvin8ec71442015-01-15 16:57:00 -08001231
kelvin-onlab898a6c62015-01-16 14:13:53 -08001232 handle = self.sendline( cmd )
Jon Hallc6793552016-01-19 14:18:37 -08001233 assert "Command not found:" not in handle, handle
kelvin-onlabfb521662015-02-27 09:52:40 -08001234 # If error, return error message
kelvin-onlab898a6c62015-01-16 14:13:53 -08001235 if re.search( "Error", handle ):
kelvin8ec71442015-01-15 16:57:00 -08001236 main.log.error( "Error in adding point-to-point intent" )
kelvin-onlabfb521662015-02-27 09:52:40 -08001237 return None
andrewonlab4dbb4d82014-10-17 18:22:31 -04001238 else:
kelvin-onlabfb521662015-02-27 09:52:40 -08001239 # TODO: print out all the options in this message?
1240 main.log.info( "Point-to-point intent installed between " +
1241 str( ingressDevice ) + " and " +
1242 str( egressDevice ) )
1243 match = re.search('id=0x([\da-f]+),', handle)
1244 if match:
1245 return match.group()[3:-1]
1246 else:
1247 main.log.error( "Error, intent ID not found" )
1248 return None
Jon Hallc6793552016-01-19 14:18:37 -08001249 except AssertionError:
1250 main.log.exception( "" )
1251 return None
Jon Halld4d4b372015-01-28 16:02:41 -08001252 except TypeError:
1253 main.log.exception( self.name + ": Object not as expected" )
1254 return None
andrewonlab4dbb4d82014-10-17 18:22:31 -04001255 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08001256 main.log.error( self.name + ": EOF exception found" )
1257 main.log.error( self.name + ": " + self.handle.before )
andrewonlab4dbb4d82014-10-17 18:22:31 -04001258 main.cleanup()
1259 main.exit()
Jon Hallfebb1c72015-03-05 13:30:09 -08001260 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -08001261 main.log.exception( self.name + ": Uncaught exception!" )
andrewonlab4dbb4d82014-10-17 18:22:31 -04001262 main.cleanup()
1263 main.exit()
1264
kelvin-onlabd3b64892015-01-20 13:26:24 -08001265 def addMultipointToSinglepointIntent(
kelvin-onlab898a6c62015-01-16 14:13:53 -08001266 self,
shahshreyac2f97072015-03-19 17:04:29 -07001267 ingressDeviceList,
kelvin-onlabd3b64892015-01-20 13:26:24 -08001268 egressDevice,
shahshreyac2f97072015-03-19 17:04:29 -07001269 portIngressList=None,
kelvin-onlabd3b64892015-01-20 13:26:24 -08001270 portEgress="",
kelvin-onlab898a6c62015-01-16 14:13:53 -08001271 ethType="",
1272 ethSrc="",
1273 ethDst="",
1274 bandwidth="",
kelvin-onlabd3b64892015-01-20 13:26:24 -08001275 lambdaAlloc=False,
kelvin-onlab898a6c62015-01-16 14:13:53 -08001276 ipProto="",
1277 ipSrc="",
1278 ipDst="",
1279 tcpSrc="",
1280 tcpDst="",
1281 setEthSrc="",
1282 setEthDst="" ):
kelvin8ec71442015-01-15 16:57:00 -08001283 """
shahshreyad0c80432014-12-04 16:56:05 -08001284 Note:
shahshreya70622b12015-03-19 17:19:00 -07001285 This function assumes the format of all ingress devices
Jon Hallbe379602015-03-24 13:39:32 -07001286 is same. That is, all ingress devices include port numbers
1287 with a "/" or all ingress devices could specify device
1288 ids and port numbers seperately.
shahshreyad0c80432014-12-04 16:56:05 -08001289 Required:
Jon Hallbe379602015-03-24 13:39:32 -07001290 * ingressDeviceList: List of device ids of ingress device
shahshreyac2f97072015-03-19 17:04:29 -07001291 ( Atleast 2 ingress devices required in the list )
kelvin-onlabd3b64892015-01-20 13:26:24 -08001292 * egressDevice: device id of egress device
shahshreyad0c80432014-12-04 16:56:05 -08001293 Optional:
1294 * ethType: specify ethType
kelvin8ec71442015-01-15 16:57:00 -08001295 * ethSrc: specify ethSrc ( i.e. src mac addr )
1296 * ethDst: specify ethDst ( i.e. dst mac addr )
shahshreyad0c80432014-12-04 16:56:05 -08001297 * bandwidth: specify bandwidth capacity of link
kelvin-onlabd3b64892015-01-20 13:26:24 -08001298 * lambdaAlloc: if True, intent will allocate lambda
shahshreyad0c80432014-12-04 16:56:05 -08001299 for the specified intent
Jon Halle3f39ff2015-01-13 11:50:53 -08001300 * ipProto: specify ip protocol
shahshreyad0c80432014-12-04 16:56:05 -08001301 * ipSrc: specify ip source address
1302 * ipDst: specify ip destination address
1303 * tcpSrc: specify tcp source port
1304 * tcpDst: specify tcp destination port
1305 * setEthSrc: action to Rewrite Source MAC Address
1306 * setEthDst: action to Rewrite Destination MAC Address
1307 Description:
kelvin8ec71442015-01-15 16:57:00 -08001308 Adds a multipoint-to-singlepoint intent ( uni-directional ) by
shahshreyad0c80432014-12-04 16:56:05 -08001309 specifying device id's and optional fields
kelvin-onlabfb521662015-02-27 09:52:40 -08001310 Returns:
1311 A string of the intent id or None on error
shahshreyad0c80432014-12-04 16:56:05 -08001312
Jon Halle3f39ff2015-01-13 11:50:53 -08001313 NOTE: This function may change depending on the
Jon Hallefbd9792015-03-05 16:11:36 -08001314 options developers provide for multipoint-to-singlepoint
shahshreyad0c80432014-12-04 16:56:05 -08001315 intent via cli
kelvin8ec71442015-01-15 16:57:00 -08001316 """
shahshreyad0c80432014-12-04 16:56:05 -08001317 try:
kelvin8ec71442015-01-15 16:57:00 -08001318 # If there are no optional arguments
shahshreyad0c80432014-12-04 16:56:05 -08001319 if not ethType and not ethSrc and not ethDst\
kelvin-onlabd3b64892015-01-20 13:26:24 -08001320 and not bandwidth and not lambdaAlloc\
Jon Halle3f39ff2015-01-13 11:50:53 -08001321 and not ipProto and not ipSrc and not ipDst\
1322 and not tcpSrc and not tcpDst and not setEthSrc\
1323 and not setEthDst:
shahshreyad0c80432014-12-04 16:56:05 -08001324 cmd = "add-multi-to-single-intent"
shahshreyad0c80432014-12-04 16:56:05 -08001325
1326 else:
1327 cmd = "add-multi-to-single-intent"
Jon Halle3f39ff2015-01-13 11:50:53 -08001328
shahshreyad0c80432014-12-04 16:56:05 -08001329 if ethType:
kelvin8ec71442015-01-15 16:57:00 -08001330 cmd += " --ethType " + str( ethType )
shahshreyad0c80432014-12-04 16:56:05 -08001331 if ethSrc:
kelvin8ec71442015-01-15 16:57:00 -08001332 cmd += " --ethSrc " + str( ethSrc )
1333 if ethDst:
1334 cmd += " --ethDst " + str( ethDst )
shahshreyad0c80432014-12-04 16:56:05 -08001335 if bandwidth:
kelvin8ec71442015-01-15 16:57:00 -08001336 cmd += " --bandwidth " + str( bandwidth )
kelvin-onlabd3b64892015-01-20 13:26:24 -08001337 if lambdaAlloc:
shahshreyad0c80432014-12-04 16:56:05 -08001338 cmd += " --lambda "
1339 if ipProto:
kelvin8ec71442015-01-15 16:57:00 -08001340 cmd += " --ipProto " + str( ipProto )
shahshreyad0c80432014-12-04 16:56:05 -08001341 if ipSrc:
kelvin8ec71442015-01-15 16:57:00 -08001342 cmd += " --ipSrc " + str( ipSrc )
shahshreyad0c80432014-12-04 16:56:05 -08001343 if ipDst:
kelvin8ec71442015-01-15 16:57:00 -08001344 cmd += " --ipDst " + str( ipDst )
shahshreyad0c80432014-12-04 16:56:05 -08001345 if tcpSrc:
kelvin8ec71442015-01-15 16:57:00 -08001346 cmd += " --tcpSrc " + str( tcpSrc )
shahshreyad0c80432014-12-04 16:56:05 -08001347 if tcpDst:
kelvin8ec71442015-01-15 16:57:00 -08001348 cmd += " --tcpDst " + str( tcpDst )
shahshreyad0c80432014-12-04 16:56:05 -08001349 if setEthSrc:
kelvin8ec71442015-01-15 16:57:00 -08001350 cmd += " --setEthSrc " + str( setEthSrc )
shahshreyad0c80432014-12-04 16:56:05 -08001351 if setEthDst:
kelvin8ec71442015-01-15 16:57:00 -08001352 cmd += " --setEthDst " + str( setEthDst )
shahshreyad0c80432014-12-04 16:56:05 -08001353
kelvin8ec71442015-01-15 16:57:00 -08001354 # Check whether the user appended the port
1355 # or provided it as an input
shahshreyac2f97072015-03-19 17:04:29 -07001356
1357 if portIngressList is None:
1358 for ingressDevice in ingressDeviceList:
1359 if "/" in ingressDevice:
1360 cmd += " " + str( ingressDevice )
1361 else:
1362 main.log.error( "You must specify " +
Jon Hallbe379602015-03-24 13:39:32 -07001363 "the ingress port" )
shahshreyac2f97072015-03-19 17:04:29 -07001364 # TODO: perhaps more meaningful return
1365 return main.FALSE
shahshreyad0c80432014-12-04 16:56:05 -08001366 else:
Jon Hall71ce4e72015-03-23 14:05:58 -07001367 if len( ingressDeviceList ) == len( portIngressList ):
Jon Hall08f61bc2015-04-13 16:00:30 -07001368 for ingressDevice, portIngress in zip( ingressDeviceList,
1369 portIngressList ):
shahshreya70622b12015-03-19 17:19:00 -07001370 cmd += " " + \
1371 str( ingressDevice ) + "/" +\
1372 str( portIngress ) + " "
kelvin-onlab38143812015-04-01 15:03:01 -07001373 else:
Jon Hall08f61bc2015-04-13 16:00:30 -07001374 main.log.error( "Device list and port list does not " +
1375 "have the same length" )
kelvin-onlab38143812015-04-01 15:03:01 -07001376 return main.FALSE
kelvin-onlabd3b64892015-01-20 13:26:24 -08001377 if "/" in egressDevice:
1378 cmd += " " + str( egressDevice )
shahshreyad0c80432014-12-04 16:56:05 -08001379 else:
kelvin-onlabd3b64892015-01-20 13:26:24 -08001380 if not portEgress:
kelvin8ec71442015-01-15 16:57:00 -08001381 main.log.error( "You must specify " +
1382 "the egress port" )
shahshreyad0c80432014-12-04 16:56:05 -08001383 return main.FALSE
Jon Halle3f39ff2015-01-13 11:50:53 -08001384
kelvin8ec71442015-01-15 16:57:00 -08001385 cmd += " " +\
kelvin-onlabd3b64892015-01-20 13:26:24 -08001386 str( egressDevice ) + "/" +\
1387 str( portEgress )
kelvin-onlab898a6c62015-01-16 14:13:53 -08001388 handle = self.sendline( cmd )
Jon Hallc6793552016-01-19 14:18:37 -08001389 assert "Command not found:" not in handle, handle
kelvin-onlabfb521662015-02-27 09:52:40 -08001390 # If error, return error message
kelvin-onlab898a6c62015-01-16 14:13:53 -08001391 if re.search( "Error", handle ):
kelvin-onlabfb521662015-02-27 09:52:40 -08001392 main.log.error( "Error in adding multipoint-to-singlepoint " +
1393 "intent" )
1394 return None
shahshreyad0c80432014-12-04 16:56:05 -08001395 else:
kelvin-onlabb9408212015-04-01 13:34:04 -07001396 match = re.search('id=0x([\da-f]+),', handle)
1397 if match:
1398 return match.group()[3:-1]
1399 else:
1400 main.log.error( "Error, intent ID not found" )
1401 return None
Jon Hallc6793552016-01-19 14:18:37 -08001402 except AssertionError:
1403 main.log.exception( "" )
1404 return None
kelvin-onlabb9408212015-04-01 13:34:04 -07001405 except TypeError:
1406 main.log.exception( self.name + ": Object not as expected" )
1407 return None
1408 except pexpect.EOF:
1409 main.log.error( self.name + ": EOF exception found" )
1410 main.log.error( self.name + ": " + self.handle.before )
1411 main.cleanup()
1412 main.exit()
1413 except Exception:
1414 main.log.exception( self.name + ": Uncaught exception!" )
1415 main.cleanup()
1416 main.exit()
1417
1418 def addSinglepointToMultipointIntent(
1419 self,
1420 ingressDevice,
1421 egressDeviceList,
1422 portIngress="",
1423 portEgressList=None,
1424 ethType="",
1425 ethSrc="",
1426 ethDst="",
1427 bandwidth="",
1428 lambdaAlloc=False,
1429 ipProto="",
1430 ipSrc="",
1431 ipDst="",
1432 tcpSrc="",
1433 tcpDst="",
1434 setEthSrc="",
1435 setEthDst="" ):
1436 """
1437 Note:
1438 This function assumes the format of all egress devices
1439 is same. That is, all egress devices include port numbers
1440 with a "/" or all egress devices could specify device
1441 ids and port numbers seperately.
1442 Required:
1443 * EgressDeviceList: List of device ids of egress device
1444 ( Atleast 2 eress devices required in the list )
1445 * ingressDevice: device id of ingress device
1446 Optional:
1447 * ethType: specify ethType
1448 * ethSrc: specify ethSrc ( i.e. src mac addr )
1449 * ethDst: specify ethDst ( i.e. dst mac addr )
1450 * bandwidth: specify bandwidth capacity of link
1451 * lambdaAlloc: if True, intent will allocate lambda
1452 for the specified intent
1453 * ipProto: specify ip protocol
1454 * ipSrc: specify ip source address
1455 * ipDst: specify ip destination address
1456 * tcpSrc: specify tcp source port
1457 * tcpDst: specify tcp destination port
1458 * setEthSrc: action to Rewrite Source MAC Address
1459 * setEthDst: action to Rewrite Destination MAC Address
1460 Description:
1461 Adds a singlepoint-to-multipoint intent ( uni-directional ) by
1462 specifying device id's and optional fields
1463 Returns:
1464 A string of the intent id or None on error
1465
1466 NOTE: This function may change depending on the
1467 options developers provide for singlepoint-to-multipoint
1468 intent via cli
1469 """
1470 try:
1471 # If there are no optional arguments
1472 if not ethType and not ethSrc and not ethDst\
1473 and not bandwidth and not lambdaAlloc\
1474 and not ipProto and not ipSrc and not ipDst\
1475 and not tcpSrc and not tcpDst and not setEthSrc\
1476 and not setEthDst:
1477 cmd = "add-single-to-multi-intent"
1478
1479 else:
1480 cmd = "add-single-to-multi-intent"
1481
1482 if ethType:
1483 cmd += " --ethType " + str( ethType )
1484 if ethSrc:
1485 cmd += " --ethSrc " + str( ethSrc )
1486 if ethDst:
1487 cmd += " --ethDst " + str( ethDst )
1488 if bandwidth:
1489 cmd += " --bandwidth " + str( bandwidth )
1490 if lambdaAlloc:
1491 cmd += " --lambda "
1492 if ipProto:
1493 cmd += " --ipProto " + str( ipProto )
1494 if ipSrc:
1495 cmd += " --ipSrc " + str( ipSrc )
1496 if ipDst:
1497 cmd += " --ipDst " + str( ipDst )
1498 if tcpSrc:
1499 cmd += " --tcpSrc " + str( tcpSrc )
1500 if tcpDst:
1501 cmd += " --tcpDst " + str( tcpDst )
1502 if setEthSrc:
1503 cmd += " --setEthSrc " + str( setEthSrc )
1504 if setEthDst:
1505 cmd += " --setEthDst " + str( setEthDst )
1506
1507 # Check whether the user appended the port
1508 # or provided it as an input
Jon Hall08f61bc2015-04-13 16:00:30 -07001509
kelvin-onlabb9408212015-04-01 13:34:04 -07001510 if "/" in ingressDevice:
1511 cmd += " " + str( ingressDevice )
1512 else:
1513 if not portIngress:
1514 main.log.error( "You must specify " +
1515 "the Ingress port" )
1516 return main.FALSE
1517
1518 cmd += " " +\
1519 str( ingressDevice ) + "/" +\
1520 str( portIngress )
1521
1522 if portEgressList is None:
1523 for egressDevice in egressDeviceList:
1524 if "/" in egressDevice:
1525 cmd += " " + str( egressDevice )
1526 else:
1527 main.log.error( "You must specify " +
1528 "the egress port" )
1529 # TODO: perhaps more meaningful return
1530 return main.FALSE
1531 else:
1532 if len( egressDeviceList ) == len( portEgressList ):
Jon Hall08f61bc2015-04-13 16:00:30 -07001533 for egressDevice, portEgress in zip( egressDeviceList,
1534 portEgressList ):
kelvin-onlabb9408212015-04-01 13:34:04 -07001535 cmd += " " + \
1536 str( egressDevice ) + "/" +\
1537 str( portEgress )
kelvin-onlab38143812015-04-01 15:03:01 -07001538 else:
Jon Hall08f61bc2015-04-13 16:00:30 -07001539 main.log.error( "Device list and port list does not " +
1540 "have the same length" )
kelvin-onlab38143812015-04-01 15:03:01 -07001541 return main.FALSE
kelvin-onlabb9408212015-04-01 13:34:04 -07001542 handle = self.sendline( cmd )
Jon Hallc6793552016-01-19 14:18:37 -08001543 assert "Command not found:" not in handle, handle
kelvin-onlabb9408212015-04-01 13:34:04 -07001544 # If error, return error message
1545 if re.search( "Error", handle ):
1546 main.log.error( "Error in adding singlepoint-to-multipoint " +
1547 "intent" )
shahshreyac2f97072015-03-19 17:04:29 -07001548 return None
kelvin-onlabb9408212015-04-01 13:34:04 -07001549 else:
1550 match = re.search('id=0x([\da-f]+),', handle)
1551 if match:
1552 return match.group()[3:-1]
1553 else:
1554 main.log.error( "Error, intent ID not found" )
1555 return None
Jon Hallc6793552016-01-19 14:18:37 -08001556 except AssertionError:
1557 main.log.exception( "" )
1558 return None
Jon Halld4d4b372015-01-28 16:02:41 -08001559 except TypeError:
1560 main.log.exception( self.name + ": Object not as expected" )
1561 return None
shahshreyad0c80432014-12-04 16:56:05 -08001562 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08001563 main.log.error( self.name + ": EOF exception found" )
1564 main.log.error( self.name + ": " + self.handle.before )
shahshreyad0c80432014-12-04 16:56:05 -08001565 main.cleanup()
1566 main.exit()
Jon Hallfebb1c72015-03-05 13:30:09 -08001567 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -08001568 main.log.exception( self.name + ": Uncaught exception!" )
shahshreyad0c80432014-12-04 16:56:05 -08001569 main.cleanup()
1570 main.exit()
1571
Hari Krishna9e232602015-04-13 17:29:08 -07001572 def addMplsIntent(
1573 self,
1574 ingressDevice,
1575 egressDevice,
Hari Krishna87a17f12015-04-13 17:42:23 -07001576 ingressPort="",
1577 egressPort="",
Hari Krishna9e232602015-04-13 17:29:08 -07001578 ethType="",
1579 ethSrc="",
1580 ethDst="",
1581 bandwidth="",
1582 lambdaAlloc=False,
1583 ipProto="",
1584 ipSrc="",
1585 ipDst="",
1586 tcpSrc="",
1587 tcpDst="",
Hari Krishna87a17f12015-04-13 17:42:23 -07001588 ingressLabel="",
Hari Krishnadfff6672015-04-13 17:53:27 -07001589 egressLabel="",
Hari Krishna9e232602015-04-13 17:29:08 -07001590 priority=""):
1591 """
1592 Required:
1593 * ingressDevice: device id of ingress device
1594 * egressDevice: device id of egress device
1595 Optional:
1596 * ethType: specify ethType
1597 * ethSrc: specify ethSrc ( i.e. src mac addr )
1598 * ethDst: specify ethDst ( i.e. dst mac addr )
1599 * bandwidth: specify bandwidth capacity of link
1600 * lambdaAlloc: if True, intent will allocate lambda
1601 for the specified intent
1602 * ipProto: specify ip protocol
1603 * ipSrc: specify ip source address
1604 * ipDst: specify ip destination address
1605 * tcpSrc: specify tcp source port
1606 * tcpDst: specify tcp destination port
1607 * ingressLabel: Ingress MPLS label
1608 * egressLabel: Egress MPLS label
1609 Description:
1610 Adds MPLS intent by
1611 specifying device id's and optional fields
1612 Returns:
1613 A string of the intent id or None on error
1614
1615 NOTE: This function may change depending on the
1616 options developers provide for MPLS
1617 intent via cli
1618 """
1619 try:
1620 # If there are no optional arguments
1621 if not ethType and not ethSrc and not ethDst\
1622 and not bandwidth and not lambdaAlloc \
1623 and not ipProto and not ipSrc and not ipDst \
1624 and not tcpSrc and not tcpDst and not ingressLabel \
1625 and not egressLabel:
1626 cmd = "add-mpls-intent"
1627
1628 else:
1629 cmd = "add-mpls-intent"
1630
1631 if ethType:
1632 cmd += " --ethType " + str( ethType )
1633 if ethSrc:
1634 cmd += " --ethSrc " + str( ethSrc )
1635 if ethDst:
1636 cmd += " --ethDst " + str( ethDst )
1637 if bandwidth:
1638 cmd += " --bandwidth " + str( bandwidth )
1639 if lambdaAlloc:
1640 cmd += " --lambda "
1641 if ipProto:
1642 cmd += " --ipProto " + str( ipProto )
1643 if ipSrc:
1644 cmd += " --ipSrc " + str( ipSrc )
1645 if ipDst:
1646 cmd += " --ipDst " + str( ipDst )
1647 if tcpSrc:
1648 cmd += " --tcpSrc " + str( tcpSrc )
1649 if tcpDst:
1650 cmd += " --tcpDst " + str( tcpDst )
1651 if ingressLabel:
1652 cmd += " --ingressLabel " + str( ingressLabel )
1653 if egressLabel:
1654 cmd += " --egressLabel " + str( egressLabel )
1655 if priority:
1656 cmd += " --priority " + str( priority )
1657
1658 # Check whether the user appended the port
1659 # or provided it as an input
1660 if "/" in ingressDevice:
1661 cmd += " " + str( ingressDevice )
1662 else:
Hari Krishna87a17f12015-04-13 17:42:23 -07001663 if not ingressPort:
Hari Krishna9e232602015-04-13 17:29:08 -07001664 main.log.error( "You must specify the ingress port" )
1665 return None
1666
1667 cmd += " " + \
1668 str( ingressDevice ) + "/" +\
Hari Krishna87a17f12015-04-13 17:42:23 -07001669 str( ingressPort ) + " "
Hari Krishna9e232602015-04-13 17:29:08 -07001670
1671 if "/" in egressDevice:
1672 cmd += " " + str( egressDevice )
1673 else:
Hari Krishna87a17f12015-04-13 17:42:23 -07001674 if not egressPort:
Hari Krishna9e232602015-04-13 17:29:08 -07001675 main.log.error( "You must specify the egress port" )
1676 return None
1677
1678 cmd += " " +\
1679 str( egressDevice ) + "/" +\
Hari Krishna87a17f12015-04-13 17:42:23 -07001680 str( egressPort )
Hari Krishna9e232602015-04-13 17:29:08 -07001681
1682 handle = self.sendline( cmd )
Jon Hallc6793552016-01-19 14:18:37 -08001683 assert "Command not found:" not in handle, handle
Hari Krishna9e232602015-04-13 17:29:08 -07001684 # If error, return error message
1685 if re.search( "Error", handle ):
1686 main.log.error( "Error in adding mpls intent" )
1687 return None
1688 else:
1689 # TODO: print out all the options in this message?
1690 main.log.info( "MPLS intent installed between " +
1691 str( ingressDevice ) + " and " +
1692 str( egressDevice ) )
1693 match = re.search('id=0x([\da-f]+),', handle)
1694 if match:
1695 return match.group()[3:-1]
1696 else:
1697 main.log.error( "Error, intent ID not found" )
1698 return None
Jon Hallc6793552016-01-19 14:18:37 -08001699 except AssertionError:
1700 main.log.exception( "" )
1701 return None
Hari Krishna9e232602015-04-13 17:29:08 -07001702 except TypeError:
1703 main.log.exception( self.name + ": Object not as expected" )
1704 return None
1705 except pexpect.EOF:
1706 main.log.error( self.name + ": EOF exception found" )
1707 main.log.error( self.name + ": " + self.handle.before )
1708 main.cleanup()
1709 main.exit()
1710 except Exception:
1711 main.log.exception( self.name + ": Uncaught exception!" )
1712 main.cleanup()
1713 main.exit()
1714
Jon Hallefbd9792015-03-05 16:11:36 -08001715 def removeIntent( self, intentId, app='org.onosproject.cli',
1716 purge=False, sync=False ):
kelvin-onlab898a6c62015-01-16 14:13:53 -08001717 """
shahshreya1c818fc2015-02-26 13:44:08 -08001718 Remove intent for specified application id and intent id
Jon Hall61282e32015-03-19 11:34:11 -07001719 Optional args:-
shahshreya1c818fc2015-02-26 13:44:08 -08001720 -s or --sync: Waits for the removal before returning
Jon Hall61282e32015-03-19 11:34:11 -07001721 -p or --purge: Purge the intent from the store after removal
1722
Jon Halle3f39ff2015-01-13 11:50:53 -08001723 Returns:
1724 main.False on error and
1725 cli output otherwise
kelvin-onlab898a6c62015-01-16 14:13:53 -08001726 """
andrewonlab9a50dfe2014-10-17 17:22:31 -04001727 try:
Jon Hallc6358dd2015-04-10 12:44:28 -07001728 cmdStr = "remove-intent"
shahshreya1c818fc2015-02-26 13:44:08 -08001729 if purge:
1730 cmdStr += " -p"
1731 if sync:
1732 cmdStr += " -s"
1733
1734 cmdStr += " " + app + " " + str( intentId )
kelvin-onlabd3b64892015-01-20 13:26:24 -08001735 handle = self.sendline( cmdStr )
Jon Hallc6793552016-01-19 14:18:37 -08001736 assert "Command not found:" not in handle, handle
Jon Halle3f39ff2015-01-13 11:50:53 -08001737 if re.search( "Error", handle ):
kelvin-onlab898a6c62015-01-16 14:13:53 -08001738 main.log.error( "Error in removing intent" )
Jon Halle3f39ff2015-01-13 11:50:53 -08001739 return main.FALSE
andrewonlab9a50dfe2014-10-17 17:22:31 -04001740 else:
Jon Halle3f39ff2015-01-13 11:50:53 -08001741 # TODO: Should this be main.TRUE
1742 return handle
Jon Hallc6793552016-01-19 14:18:37 -08001743 except AssertionError:
1744 main.log.exception( "" )
1745 return None
Jon Halld4d4b372015-01-28 16:02:41 -08001746 except TypeError:
1747 main.log.exception( self.name + ": Object not as expected" )
1748 return None
andrewonlab9a50dfe2014-10-17 17:22:31 -04001749 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08001750 main.log.error( self.name + ": EOF exception found" )
1751 main.log.error( self.name + ": " + self.handle.before )
andrewonlab9a50dfe2014-10-17 17:22:31 -04001752 main.cleanup()
1753 main.exit()
Jon Hallfebb1c72015-03-05 13:30:09 -08001754 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -08001755 main.log.exception( self.name + ": Uncaught exception!" )
andrewonlab9a50dfe2014-10-17 17:22:31 -04001756 main.cleanup()
1757 main.exit()
1758
Jeremy42df2e72016-02-23 16:37:46 -08001759 def removeAllIntents( self, purge=False, sync=False, app='org.onosproject.cli' ):
1760 """
1761 Description:
1762 Remove all the intents
1763 Optional args:-
1764 -s or --sync: Waits for the removal before returning
1765 -p or --purge: Purge the intent from the store after removal
1766 Returns:
1767 Returns main.TRUE if all intents are removed, otherwise returns
1768 main.FALSE; Returns None for exception
1769 """
1770 try:
1771 cmdStr = "remove-intent"
1772 if purge:
1773 cmdStr += " -p"
1774 if sync:
1775 cmdStr += " -s"
1776
1777 cmdStr += " " + app
1778 handle = self.sendline( cmdStr )
1779 assert "Command not found:" not in handle, handle
1780 if re.search( "Error", handle ):
1781 main.log.error( "Error in removing intent" )
1782 return main.FALSE
1783 else:
1784 return main.TRUE
1785 except AssertionError:
1786 main.log.exception( "" )
1787 return None
1788 except TypeError:
1789 main.log.exception( self.name + ": Object not as expected" )
1790 return None
1791 except pexpect.EOF:
1792 main.log.error( self.name + ": EOF exception found" )
1793 main.log.error( self.name + ": " + self.handle.before )
1794 main.cleanup()
1795 main.exit()
1796 except Exception:
1797 main.log.exception( self.name + ": Uncaught exception!" )
1798 main.cleanup()
1799 main.exit()
1800
Hari Krishnaacabd5a2015-07-01 17:10:19 -07001801 def purgeWithdrawnIntents( self ):
Hari Krishna0ce0e152015-06-23 09:55:29 -07001802 """
1803 Purges all WITHDRAWN Intents
1804 """
1805 try:
1806 cmdStr = "purge-intents"
1807 handle = self.sendline( cmdStr )
Jon Hallc6793552016-01-19 14:18:37 -08001808 assert "Command not found:" not in handle, handle
Hari Krishna0ce0e152015-06-23 09:55:29 -07001809 if re.search( "Error", handle ):
1810 main.log.error( "Error in purging intents" )
1811 return main.FALSE
1812 else:
1813 return main.TRUE
Jon Hallc6793552016-01-19 14:18:37 -08001814 except AssertionError:
1815 main.log.exception( "" )
1816 return None
Hari Krishna0ce0e152015-06-23 09:55:29 -07001817 except TypeError:
1818 main.log.exception( self.name + ": Object not as expected" )
1819 return None
1820 except pexpect.EOF:
1821 main.log.error( self.name + ": EOF exception found" )
1822 main.log.error( self.name + ": " + self.handle.before )
1823 main.cleanup()
1824 main.exit()
1825 except Exception:
1826 main.log.exception( self.name + ": Uncaught exception!" )
1827 main.cleanup()
1828 main.exit()
1829
kelvin-onlabd3b64892015-01-20 13:26:24 -08001830 def routes( self, jsonFormat=False ):
kelvin8ec71442015-01-15 16:57:00 -08001831 """
kelvin-onlab898a6c62015-01-16 14:13:53 -08001832 NOTE: This method should be used after installing application:
1833 onos-app-sdnip
pingping-lin8b306ac2014-11-17 18:13:51 -08001834 Optional:
kelvin-onlabd3b64892015-01-20 13:26:24 -08001835 * jsonFormat: enable output formatting in json
pingping-lin8b306ac2014-11-17 18:13:51 -08001836 Description:
1837 Obtain all routes in the system
kelvin8ec71442015-01-15 16:57:00 -08001838 """
pingping-lin8b306ac2014-11-17 18:13:51 -08001839 try:
Jon Hallc6358dd2015-04-10 12:44:28 -07001840 cmdStr = "routes"
kelvin-onlabd3b64892015-01-20 13:26:24 -08001841 if jsonFormat:
Jon Hallc6358dd2015-04-10 12:44:28 -07001842 cmdStr += " -j"
1843 handle = self.sendline( cmdStr )
Jon Hallc6793552016-01-19 14:18:37 -08001844 assert "Command not found:" not in handle, handle
pingping-lin8b306ac2014-11-17 18:13:51 -08001845 return handle
Jon Hallc6793552016-01-19 14:18:37 -08001846 except AssertionError:
1847 main.log.exception( "" )
1848 return None
Jon Halld4d4b372015-01-28 16:02:41 -08001849 except TypeError:
1850 main.log.exception( self.name + ": Object not as expected" )
1851 return None
pingping-lin8b306ac2014-11-17 18:13:51 -08001852 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08001853 main.log.error( self.name + ": EOF exception found" )
1854 main.log.error( self.name + ": " + self.handle.before )
pingping-lin8b306ac2014-11-17 18:13:51 -08001855 main.cleanup()
1856 main.exit()
Jon Hallfebb1c72015-03-05 13:30:09 -08001857 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -08001858 main.log.exception( self.name + ": Uncaught exception!" )
pingping-lin8b306ac2014-11-17 18:13:51 -08001859 main.cleanup()
1860 main.exit()
1861
pingping-lin54b03372015-08-13 14:43:10 -07001862 def ipv4RouteNumber( self ):
1863 """
1864 NOTE: This method should be used after installing application:
1865 onos-app-sdnip
1866 Description:
1867 Obtain the total IPv4 routes number in the system
1868 """
1869 try:
1870 cmdStr = "routes -s -j"
1871 handle = self.sendline( cmdStr )
Jon Hallc6793552016-01-19 14:18:37 -08001872 assert "Command not found:" not in handle, handle
pingping-lin54b03372015-08-13 14:43:10 -07001873 jsonResult = json.loads( handle )
1874 return jsonResult['totalRoutes4']
Jon Hallc6793552016-01-19 14:18:37 -08001875 except AssertionError:
1876 main.log.exception( "" )
1877 return None
1878 except ( TypeError, ValueError ):
1879 main.log.exception( "{}: Object not as expected: {!r}".format( self.name, handle ) )
pingping-lin54b03372015-08-13 14:43:10 -07001880 return None
1881 except pexpect.EOF:
1882 main.log.error( self.name + ": EOF exception found" )
1883 main.log.error( self.name + ": " + self.handle.before )
1884 main.cleanup()
1885 main.exit()
1886 except Exception:
1887 main.log.exception( self.name + ": Uncaught exception!" )
1888 main.cleanup()
1889 main.exit()
1890
pingping-lin8244a3b2015-09-16 13:36:56 -07001891 def intents( self, jsonFormat = True, summary = False, **intentargs):
kelvin8ec71442015-01-15 16:57:00 -08001892 """
andrewonlabe6745342014-10-17 14:29:13 -04001893 Description:
Jon Hallff566d52016-01-15 14:45:36 -08001894 Obtain intents from the ONOS cli.
1895 Optional:
1896 * jsonFormat: Enable output formatting in json, default to True
1897 * summary: Whether only output the intent summary, defaults to False
1898 * type: Only output a certain type of intent. This options is valid
1899 only when jsonFormat is True and summary is True.
kelvin-onlab898a6c62015-01-16 14:13:53 -08001900 """
andrewonlabe6745342014-10-17 14:29:13 -04001901 try:
Jon Hallc6358dd2015-04-10 12:44:28 -07001902 cmdStr = "intents"
pingping-lin8244a3b2015-09-16 13:36:56 -07001903 if summary:
1904 cmdStr += " -s"
kelvin-onlabd3b64892015-01-20 13:26:24 -08001905 if jsonFormat:
Jon Hallc6358dd2015-04-10 12:44:28 -07001906 cmdStr += " -j"
1907 handle = self.sendline( cmdStr )
Jon Hallc6793552016-01-19 14:18:37 -08001908 assert "Command not found:" not in handle, handle
pingping-lin8244a3b2015-09-16 13:36:56 -07001909 args = utilities.parse_args( [ "TYPE" ], **intentargs )
acsmars5b5fbaf2015-09-18 10:38:20 -07001910 if "TYPE" in args.keys():
Jon Hallff566d52016-01-15 14:45:36 -08001911 intentType = args[ "TYPE" ]
acsmars5b5fbaf2015-09-18 10:38:20 -07001912 else:
Jon Hallff566d52016-01-15 14:45:36 -08001913 intentType = ""
1914 # IF we want the summary of a specific intent type
1915 if jsonFormat and summary and ( intentType != "" ):
pingping-lin8244a3b2015-09-16 13:36:56 -07001916 jsonResult = json.loads( handle )
Jon Hallff566d52016-01-15 14:45:36 -08001917 if intentType in jsonResult.keys():
1918 return jsonResult[ intentType ]
pingping-lin8244a3b2015-09-16 13:36:56 -07001919 else:
Jon Hallff566d52016-01-15 14:45:36 -08001920 main.log.error( "unknown TYPE, returning all types of intents" )
pingping-lin8244a3b2015-09-16 13:36:56 -07001921 return handle
1922 else:
1923 return handle
Jon Hallc6793552016-01-19 14:18:37 -08001924 except AssertionError:
1925 main.log.exception( "" )
1926 return None
1927 except ( TypeError, ValueError ):
1928 main.log.exception( "{}: Object not as expected: {!r}".format( self.name, handle ) )
pingping-lin54b03372015-08-13 14:43:10 -07001929 return None
1930 except pexpect.EOF:
1931 main.log.error( self.name + ": EOF exception found" )
1932 main.log.error( self.name + ": " + self.handle.before )
1933 main.cleanup()
1934 main.exit()
1935 except Exception:
1936 main.log.exception( self.name + ": Uncaught exception!" )
1937 main.cleanup()
1938 main.exit()
1939
kelvin-onlab54400a92015-02-26 18:05:51 -08001940 def getIntentState(self, intentsId, intentsJson=None):
1941 """
kelvin-onlab54400a92015-02-26 18:05:51 -08001942 Check intent state.
1943 Accepts a single intent ID (string type) or a list of intent IDs.
1944 Returns the state(string type) of the id if a single intent ID is
1945 accepted.
Jon Hallefbd9792015-03-05 16:11:36 -08001946 Returns a dictionary with intent IDs as the key and its
1947 corresponding states as the values
kelvin-onlabfb521662015-02-27 09:52:40 -08001948 Parameters:
kelvin-onlab54400a92015-02-26 18:05:51 -08001949 intentId: intent ID (string type)
1950 intentsJson: parsed json object from the onos:intents api
1951 Returns:
1952 state = An intent's state- INSTALL,WITHDRAWN etc.
1953 stateDict = Dictionary of intent's state. intent ID as the keys and
1954 state as the values.
1955 """
kelvin-onlab54400a92015-02-26 18:05:51 -08001956 try:
1957 state = "State is Undefined"
1958 if not intentsJson:
Jon Hallc6793552016-01-19 14:18:37 -08001959 rawJson = self.intents()
kelvin-onlab54400a92015-02-26 18:05:51 -08001960 else:
Jon Hallc6793552016-01-19 14:18:37 -08001961 rawJson = intentsJson
1962 parsedIntentsJson = json.loads( rawJson )
Jon Hallefbd9792015-03-05 16:11:36 -08001963 if isinstance( intentsId, types.StringType ):
Jon Hallc6793552016-01-19 14:18:37 -08001964 for intent in parsedIntentsJson:
kelvin-onlabc2dcd3f2015-04-09 16:40:02 -07001965 if intentsId == intent[ 'id' ]:
1966 state = intent[ 'state' ]
kelvin-onlab54400a92015-02-26 18:05:51 -08001967 return state
Jon Hallefbd9792015-03-05 16:11:36 -08001968 main.log.info( "Cannot find intent ID" + str( intentsId ) +
1969 " on the list" )
kelvin-onlab54400a92015-02-26 18:05:51 -08001970 return state
Jon Hallefbd9792015-03-05 16:11:36 -08001971 elif isinstance( intentsId, types.ListType ):
kelvin-onlab07dbd012015-03-04 16:29:39 -08001972 dictList = []
kelvin-onlabc2dcd3f2015-04-09 16:40:02 -07001973 for i in xrange( len( intentsId ) ):
kelvin-onlab07dbd012015-03-04 16:29:39 -08001974 stateDict = {}
Jon Hallc6793552016-01-19 14:18:37 -08001975 for intents in parsedIntentsJson:
kelvin-onlabc2dcd3f2015-04-09 16:40:02 -07001976 if intentsId[ i ] == intents[ 'id' ]:
1977 stateDict[ 'state' ] = intents[ 'state' ]
1978 stateDict[ 'id' ] = intentsId[ i ]
Jon Hallefbd9792015-03-05 16:11:36 -08001979 dictList.append( stateDict )
kelvin-onlab54400a92015-02-26 18:05:51 -08001980 break
Jon Hallefbd9792015-03-05 16:11:36 -08001981 if len( intentsId ) != len( dictList ):
1982 main.log.info( "Cannot find some of the intent ID state" )
kelvin-onlab07dbd012015-03-04 16:29:39 -08001983 return dictList
kelvin-onlab54400a92015-02-26 18:05:51 -08001984 else:
kelvin-onlabc2dcd3f2015-04-09 16:40:02 -07001985 main.log.info( "Invalid intents ID entry" )
kelvin-onlab54400a92015-02-26 18:05:51 -08001986 return None
Jon Hallc6793552016-01-19 14:18:37 -08001987 except ( TypeError, ValueError ):
1988 main.log.exception( "{}: Object not as expected: {!r}".format( self.name, rawJson ) )
kelvin-onlab54400a92015-02-26 18:05:51 -08001989 return None
1990 except pexpect.EOF:
1991 main.log.error( self.name + ": EOF exception found" )
1992 main.log.error( self.name + ": " + self.handle.before )
1993 main.cleanup()
1994 main.exit()
Jon Hallfebb1c72015-03-05 13:30:09 -08001995 except Exception:
kelvin-onlab54400a92015-02-26 18:05:51 -08001996 main.log.exception( self.name + ": Uncaught exception!" )
andrewonlabe6745342014-10-17 14:29:13 -04001997 main.cleanup()
1998 main.exit()
Jon Hall390696c2015-05-05 17:13:41 -07001999
kelvin-onlabf512e942015-06-08 19:42:59 -07002000 def checkIntentState( self, intentsId, expectedState='INSTALLED' ):
kelvin-onlabc2dcd3f2015-04-09 16:40:02 -07002001 """
2002 Description:
2003 Check intents state
2004 Required:
2005 intentsId - List of intents ID to be checked
2006 Optional:
kelvin-onlabf512e942015-06-08 19:42:59 -07002007 expectedState - Check the expected state(s) of each intents
2008 state in the list.
2009 *NOTE: You can pass in a list of expected state,
2010 Eg: expectedState = [ 'INSTALLED' , 'INSTALLING' ]
kelvin-onlabc2dcd3f2015-04-09 16:40:02 -07002011 Return:
kelvin-onlabf512e942015-06-08 19:42:59 -07002012 Returns main.TRUE only if all intent are the same as expected states
2013 , otherwise, returns main.FALSE.
kelvin-onlabc2dcd3f2015-04-09 16:40:02 -07002014 """
2015 try:
2016 # Generating a dictionary: intent id as a key and state as value
kelvin-onlabf512e942015-06-08 19:42:59 -07002017 returnValue = main.TRUE
kelvin-onlabc2dcd3f2015-04-09 16:40:02 -07002018 intentsDict = self.getIntentState( intentsId )
kelvin-onlabc2dcd3f2015-04-09 16:40:02 -07002019 if len( intentsId ) != len( intentsDict ):
Jon Hallae04e622016-01-27 10:38:05 -08002020 main.log.info( self.name + ": There is something wrong " +
kelvin-onlabc2dcd3f2015-04-09 16:40:02 -07002021 "getting intents state" )
2022 return main.FALSE
kelvin-onlabf512e942015-06-08 19:42:59 -07002023
2024 if isinstance( expectedState, types.StringType ):
2025 for intents in intentsDict:
2026 if intents.get( 'state' ) != expectedState:
kelvin-onlaba297c4d2015-06-01 13:53:55 -07002027 main.log.debug( self.name + " : Intent ID - " +
2028 intents.get( 'id' ) +
kelvin-onlabf512e942015-06-08 19:42:59 -07002029 " actual state = " +
2030 intents.get( 'state' )
2031 + " does not equal expected state = "
2032 + expectedState )
kelvin-onlaba297c4d2015-06-01 13:53:55 -07002033 returnValue = main.FALSE
kelvin-onlabf512e942015-06-08 19:42:59 -07002034
2035 elif isinstance( expectedState, types.ListType ):
2036 for intents in intentsDict:
2037 if not any( state == intents.get( 'state' ) for state in
2038 expectedState ):
2039 main.log.debug( self.name + " : Intent ID - " +
2040 intents.get( 'id' ) +
2041 " actual state = " +
2042 intents.get( 'state' ) +
2043 " does not equal expected states = "
2044 + str( expectedState ) )
2045 returnValue = main.FALSE
2046
kelvin-onlabc2dcd3f2015-04-09 16:40:02 -07002047 if returnValue == main.TRUE:
2048 main.log.info( self.name + ": All " +
2049 str( len( intentsDict ) ) +
kelvin-onlabf512e942015-06-08 19:42:59 -07002050 " intents are in " + str( expectedState ) +
2051 " state" )
kelvin-onlabc2dcd3f2015-04-09 16:40:02 -07002052 return returnValue
2053 except TypeError:
2054 main.log.exception( self.name + ": Object not as expected" )
2055 return None
2056 except pexpect.EOF:
2057 main.log.error( self.name + ": EOF exception found" )
2058 main.log.error( self.name + ": " + self.handle.before )
2059 main.cleanup()
2060 main.exit()
2061 except Exception:
2062 main.log.exception( self.name + ": Uncaught exception!" )
2063 main.cleanup()
2064 main.exit()
andrewonlabe6745342014-10-17 14:29:13 -04002065
GlennRCed771242016-01-13 17:02:47 -08002066 def checkIntentSummary( self, timeout=60 ):
2067 """
2068 Description:
2069 Check the number of installed intents.
2070 Optional:
2071 timeout - the timeout for pexcept
2072 Return:
2073 Returns main.TRUE only if the number of all installed intents are the same as total intents number
2074 , otherwise, returns main.FALSE.
2075 """
2076
2077 try:
2078 cmd = "intents -s -j"
2079
2080 # Check response if something wrong
2081 response = self.sendline( cmd, timeout=timeout )
2082 if response == None:
2083 return main.False
2084 response = json.loads( response )
2085
2086 # get total and installed number, see if they are match
2087 allState = response.get( 'all' )
2088 if allState.get('total') == allState.get('installed'):
YPZhangb5d3f832016-01-23 22:54:26 -08002089 main.log.info( 'Total Intents: {} Installed Intents: {}'.format( allState.get('total'), allState.get('installed') ) )
GlennRCed771242016-01-13 17:02:47 -08002090 return main.TRUE
YPZhangb5d3f832016-01-23 22:54:26 -08002091 main.log.info( 'Verified Intents failed Excepte intetnes: {} installed intents: {}'.format( allState.get('total'), allState.get('installed') ) )
GlennRCed771242016-01-13 17:02:47 -08002092 return main.FALSE
2093
Jon Hallc6793552016-01-19 14:18:37 -08002094 except ( TypeError, ValueError ):
2095 main.log.exception( "{}: Object not as expected: {!r}".format( self.name, response ) )
GlennRCed771242016-01-13 17:02:47 -08002096 return None
2097 except pexpect.EOF:
2098 main.log.error( self.name + ": EOF exception found" )
2099 main.log.error( self.name + ": " + self.handle.before )
2100 main.cleanup()
2101 main.exit()
2102 except Exception:
2103 main.log.exception( self.name + ": Uncaught exception!" )
2104 main.cleanup()
2105 main.exit()
2106
2107 def flows( self, state="", jsonFormat=True, timeout=60 ):
kelvin8ec71442015-01-15 16:57:00 -08002108 """
Shreya Shah0f01c812014-10-26 20:15:28 -04002109 Optional:
kelvin-onlabd3b64892015-01-20 13:26:24 -08002110 * jsonFormat: enable output formatting in json
Shreya Shah0f01c812014-10-26 20:15:28 -04002111 Description:
Jon Halle3f39ff2015-01-13 11:50:53 -08002112 Obtain flows currently installed
kelvin-onlab898a6c62015-01-16 14:13:53 -08002113 """
Shreya Shah0f01c812014-10-26 20:15:28 -04002114 try:
Jon Hallc6358dd2015-04-10 12:44:28 -07002115 cmdStr = "flows"
kelvin-onlabd3b64892015-01-20 13:26:24 -08002116 if jsonFormat:
GlennRCed771242016-01-13 17:02:47 -08002117 cmdStr += " -j "
2118 cmdStr += state
Jon Hallc6793552016-01-19 14:18:37 -08002119 handle = self.sendline( cmdStr, timeout=timeout )
2120 assert "Command not found:" not in handle, handle
2121 if re.search( "Error:", handle ):
2122 main.log.error( self.name + ": flows() response: " +
2123 str( handle ) )
2124 return handle
2125 except AssertionError:
2126 main.log.exception( "" )
GlennRCed771242016-01-13 17:02:47 -08002127 return None
Jon Halld4d4b372015-01-28 16:02:41 -08002128 except TypeError:
2129 main.log.exception( self.name + ": Object not as expected" )
2130 return None
Jon Hallc6793552016-01-19 14:18:37 -08002131 except pexpect.TIMEOUT:
2132 main.log.error( self.name + ": ONOS timeout" )
2133 return None
Shreya Shah0f01c812014-10-26 20:15:28 -04002134 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08002135 main.log.error( self.name + ": EOF exception found" )
2136 main.log.error( self.name + ": " + self.handle.before )
Shreya Shah0f01c812014-10-26 20:15:28 -04002137 main.cleanup()
2138 main.exit()
Jon Hallfebb1c72015-03-05 13:30:09 -08002139 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -08002140 main.log.exception( self.name + ": Uncaught exception!" )
Shreya Shah0f01c812014-10-26 20:15:28 -04002141 main.cleanup()
2142 main.exit()
2143
GlennRCed771242016-01-13 17:02:47 -08002144
Jon Hallc6793552016-01-19 14:18:37 -08002145 def checkFlowsState( self, isPENDING=True, timeout=60 ):
kelvin-onlab4df89f22015-04-13 18:10:23 -07002146 """
2147 Description:
GlennRCed771242016-01-13 17:02:47 -08002148 Check the if all the current flows are in ADDED state
Jon Hallc6793552016-01-19 14:18:37 -08002149 We check PENDING_ADD, PENDING_REMOVE, REMOVED, and FAILED flows,
2150 if the count of those states is 0, which means all current flows
2151 are in ADDED state, and return main.TRUE otherwise return main.FALSE
pingping-linbab7f8a2015-09-21 17:33:36 -07002152 Optional:
GlennRCed771242016-01-13 17:02:47 -08002153 * isPENDING: whether the PENDING_ADD is also a correct status
kelvin-onlab4df89f22015-04-13 18:10:23 -07002154 Return:
2155 returnValue - Returns main.TRUE only if all flows are in
Jon Hallc6793552016-01-19 14:18:37 -08002156 ADDED state or PENDING_ADD if the isPENDING
pingping-linbab7f8a2015-09-21 17:33:36 -07002157 parameter is set true, return main.FALSE otherwise.
kelvin-onlab4df89f22015-04-13 18:10:23 -07002158 """
2159 try:
GlennRCed771242016-01-13 17:02:47 -08002160 states = ["PENDING_ADD", "PENDING_REMOVE", "REMOVED", "FAILED"]
2161 checkedStates = []
2162 statesCount = [0, 0, 0, 0]
2163 for s in states:
Jon Hallc6793552016-01-19 14:18:37 -08002164 rawFlows = self.flows( state=s, timeout = timeout )
2165 checkedStates.append( json.loads( rawFlows ) )
2166 for i in range( len( states ) ):
GlennRCed771242016-01-13 17:02:47 -08002167 for c in checkedStates[i]:
Jon Hallc6793552016-01-19 14:18:37 -08002168 try:
2169 statesCount[i] += int( c.get( "flowCount" ) )
2170 except TypeError:
2171 main.log.exception( "Json object not as expected" )
2172 main.log.info( states[i] + " flows: " + str( statesCount[i] ) )
kelvin-onlabf2ec6e02015-05-27 14:15:28 -07002173
GlennRCed771242016-01-13 17:02:47 -08002174 # We want to count PENDING_ADD if isPENDING is true
2175 if isPENDING:
2176 if statesCount[1] + statesCount[2] + statesCount[3] > 0:
2177 return main.FALSE
pingping-linbab7f8a2015-09-21 17:33:36 -07002178 else:
GlennRCed771242016-01-13 17:02:47 -08002179 if statesCount[0] + statesCount[1] + statesCount[2] + statesCount[3] > 0:
2180 return main.FALSE
GlennRCed771242016-01-13 17:02:47 -08002181 return main.TRUE
Jon Hallc6793552016-01-19 14:18:37 -08002182 except ( TypeError, ValueError ):
2183 main.log.exception( "{}: Object not as expected: {!r}".format( self.name, rawFlows ) )
kelvin-onlab4df89f22015-04-13 18:10:23 -07002184 return None
2185 except pexpect.EOF:
2186 main.log.error( self.name + ": EOF exception found" )
2187 main.log.error( self.name + ": " + self.handle.before )
2188 main.cleanup()
2189 main.exit()
2190 except Exception:
2191 main.log.exception( self.name + ": Uncaught exception!" )
2192 main.cleanup()
2193 main.exit()
2194
GlennRCed771242016-01-13 17:02:47 -08002195 def pushTestIntents( self, ingress, egress, batchSize, offset="",
2196 options="", timeout=10, background = False ):
kelvin8ec71442015-01-15 16:57:00 -08002197 """
andrewonlab87852b02014-11-19 18:44:19 -05002198 Description:
Jon Halle3f39ff2015-01-13 11:50:53 -08002199 Push a number of intents in a batch format to
andrewonlab87852b02014-11-19 18:44:19 -05002200 a specific point-to-point intent definition
2201 Required:
GlennRCed771242016-01-13 17:02:47 -08002202 * ingress: specify source dpid
2203 * egress: specify destination dpid
2204 * batchSize: specify number of intents to push
andrewonlab87852b02014-11-19 18:44:19 -05002205 Optional:
GlennRCed771242016-01-13 17:02:47 -08002206 * offset: the keyOffset is where the next batch of intents
2207 will be installed
2208 Returns: If failed to push test intents, it will returen None,
2209 if successful, return true.
2210 Timeout expection will return None,
2211 TypeError will return false
2212 other expections will exit()
kelvin8ec71442015-01-15 16:57:00 -08002213 """
andrewonlab87852b02014-11-19 18:44:19 -05002214 try:
GlennRCed771242016-01-13 17:02:47 -08002215 if background:
2216 back = "&"
andrewonlab87852b02014-11-19 18:44:19 -05002217 else:
GlennRCed771242016-01-13 17:02:47 -08002218 back = ""
2219 cmd = "push-test-intents {} {} {} {} {} {}".format( options,
Jon Hallc6793552016-01-19 14:18:37 -08002220 ingress,
2221 egress,
2222 batchSize,
2223 offset,
2224 back )
GlennRCed771242016-01-13 17:02:47 -08002225 response = self.sendline( cmd, timeout=timeout )
Jon Hallc6793552016-01-19 14:18:37 -08002226 assert "Command not found:" not in response, response
GlennRCed771242016-01-13 17:02:47 -08002227 main.log.info( response )
2228 if response == None:
2229 return None
2230
2231 # TODO: We should handle if there is failure in installation
2232 return main.TRUE
2233
Jon Hallc6793552016-01-19 14:18:37 -08002234 except AssertionError:
2235 main.log.exception( "" )
2236 return None
GlennRCed771242016-01-13 17:02:47 -08002237 except pexpect.TIMEOUT:
2238 main.log.error( self.name + ": ONOS timeout" )
Jon Halld4d4b372015-01-28 16:02:41 -08002239 return None
andrewonlab87852b02014-11-19 18:44:19 -05002240 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08002241 main.log.error( self.name + ": EOF exception found" )
2242 main.log.error( self.name + ": " + self.handle.before )
andrewonlab87852b02014-11-19 18:44:19 -05002243 main.cleanup()
2244 main.exit()
GlennRCed771242016-01-13 17:02:47 -08002245 except TypeError:
2246 main.log.exception( self.name + ": Object not as expected" )
Jon Hallc6793552016-01-19 14:18:37 -08002247 return None
Jon Hallfebb1c72015-03-05 13:30:09 -08002248 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -08002249 main.log.exception( self.name + ": Uncaught exception!" )
andrewonlab87852b02014-11-19 18:44:19 -05002250 main.cleanup()
2251 main.exit()
2252
YPZhangf6f14a02016-01-28 15:17:31 -08002253 def getTotalFlowsNum( self, timeout=60 ):
YPZhangb5d3f832016-01-23 22:54:26 -08002254 """
2255 Description:
YPZhangf6f14a02016-01-28 15:17:31 -08002256 Get the number of ADDED flows.
YPZhangb5d3f832016-01-23 22:54:26 -08002257 Return:
YPZhangf6f14a02016-01-28 15:17:31 -08002258 The number of ADDED flows
YPZhangb5d3f832016-01-23 22:54:26 -08002259 """
YPZhange3109a72016-02-02 11:25:37 -08002260
YPZhangb5d3f832016-01-23 22:54:26 -08002261 try:
YPZhange3109a72016-02-02 11:25:37 -08002262 # get total added flows number
YPZhangf6f14a02016-01-28 15:17:31 -08002263 cmd = "flows -s|grep ADDED|wc -l"
YPZhange3109a72016-02-02 11:25:37 -08002264 totalFlows = self.sendline( cmd, timeout=timeout )
2265
2266 if totalFlows == None:
2267 # if timeout, we will get total number of all flows, and subtract other states
2268 states = ["PENDING_ADD", "PENDING_REMOVE", "REMOVED", "FAILED"]
2269 checkedStates = []
2270 totalFlows = 0
2271 statesCount = [0, 0, 0, 0]
2272
2273 # get total flows from summary
2274 response = json.loads( self.sendline( "summary -j", timeout=timeout ) )
2275 totalFlows = int( response.get("flows") )
2276
2277 for s in states:
2278 rawFlows = self.flows( state=s, timeout = timeout )
2279 if rawFlows == None:
2280 # if timeout, return the total flows number from summary command
2281 return totalFlows
2282 checkedStates.append( json.loads( rawFlows ) )
2283
2284 # Calculate ADDED flows number, equal total subtracts others
2285 for i in range( len( states ) ):
2286 for c in checkedStates[i]:
2287 try:
2288 statesCount[i] += int( c.get( "flowCount" ) )
2289 except TypeError:
2290 main.log.exception( "Json object not as expected" )
2291 totalFlows = totalFlows - int( statesCount[i] )
2292 main.log.info( states[i] + " flows: " + str( statesCount[i] ) )
2293
2294 return totalFlows
2295
2296 return totalFlows
2297
YPZhangb5d3f832016-01-23 22:54:26 -08002298 except TypeError:
2299 main.log.exception( self.name + ": Object not as expected" )
2300 return None
2301 except pexpect.EOF:
2302 main.log.error( self.name + ": EOF exception found" )
2303 main.log.error( self.name + ": " + self.handle.before )
2304 main.cleanup()
2305 main.exit()
2306 except Exception:
2307 main.log.exception( self.name + ": Uncaught exception!" )
2308 main.cleanup()
2309 main.exit()
2310
2311 def getTotalIntentsNum( self ):
2312 """
2313 Description:
2314 Get the total number of intents, include every states.
2315 Return:
2316 The number of intents
2317 """
2318 try:
2319 cmd = "summary -j"
2320 response = self.sendline( cmd )
2321 if response == None:
2322 return -1
2323 response = json.loads( response )
2324 return int( response.get("intents") )
2325 except TypeError:
2326 main.log.exception( self.name + ": Object not as expected" )
2327 return None
2328 except pexpect.EOF:
2329 main.log.error( self.name + ": EOF exception found" )
2330 main.log.error( self.name + ": " + self.handle.before )
2331 main.cleanup()
2332 main.exit()
2333 except Exception:
2334 main.log.exception( self.name + ": Uncaught exception!" )
2335 main.cleanup()
2336 main.exit()
2337
kelvin-onlabd3b64892015-01-20 13:26:24 -08002338 def intentsEventsMetrics( self, jsonFormat=True ):
kelvin8ec71442015-01-15 16:57:00 -08002339 """
Jon Halle3f39ff2015-01-13 11:50:53 -08002340 Description:Returns topology metrics
andrewonlab0dbb6ec2014-11-06 13:46:55 -05002341 Optional:
kelvin-onlabd3b64892015-01-20 13:26:24 -08002342 * jsonFormat: enable json formatting of output
kelvin8ec71442015-01-15 16:57:00 -08002343 """
andrewonlab0dbb6ec2014-11-06 13:46:55 -05002344 try:
Jon Hallc6358dd2015-04-10 12:44:28 -07002345 cmdStr = "intents-events-metrics"
kelvin-onlabd3b64892015-01-20 13:26:24 -08002346 if jsonFormat:
Jon Hallc6358dd2015-04-10 12:44:28 -07002347 cmdStr += " -j"
2348 handle = self.sendline( cmdStr )
Jon Hallc6793552016-01-19 14:18:37 -08002349 assert "Command not found:" not in handle, handle
andrewonlab0dbb6ec2014-11-06 13:46:55 -05002350 return handle
Jon Hallc6793552016-01-19 14:18:37 -08002351 except AssertionError:
2352 main.log.exception( "" )
2353 return None
Jon Halld4d4b372015-01-28 16:02:41 -08002354 except TypeError:
2355 main.log.exception( self.name + ": Object not as expected" )
2356 return None
andrewonlab0dbb6ec2014-11-06 13:46:55 -05002357 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08002358 main.log.error( self.name + ": EOF exception found" )
2359 main.log.error( self.name + ": " + self.handle.before )
andrewonlab0dbb6ec2014-11-06 13:46:55 -05002360 main.cleanup()
2361 main.exit()
Jon Hallfebb1c72015-03-05 13:30:09 -08002362 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -08002363 main.log.exception( self.name + ": Uncaught exception!" )
andrewonlab0dbb6ec2014-11-06 13:46:55 -05002364 main.cleanup()
2365 main.exit()
Shreya Shah0f01c812014-10-26 20:15:28 -04002366
kelvin-onlabd3b64892015-01-20 13:26:24 -08002367 def topologyEventsMetrics( self, jsonFormat=True ):
kelvin8ec71442015-01-15 16:57:00 -08002368 """
2369 Description:Returns topology metrics
andrewonlab867212a2014-10-22 20:13:38 -04002370 Optional:
kelvin-onlabd3b64892015-01-20 13:26:24 -08002371 * jsonFormat: enable json formatting of output
kelvin8ec71442015-01-15 16:57:00 -08002372 """
andrewonlab867212a2014-10-22 20:13:38 -04002373 try:
Jon Hallc6358dd2015-04-10 12:44:28 -07002374 cmdStr = "topology-events-metrics"
kelvin-onlabd3b64892015-01-20 13:26:24 -08002375 if jsonFormat:
Jon Hallc6358dd2015-04-10 12:44:28 -07002376 cmdStr += " -j"
2377 handle = self.sendline( cmdStr )
Jon Hallc6793552016-01-19 14:18:37 -08002378 assert "Command not found:" not in handle, handle
jenkins7ead5a82015-03-13 10:28:21 -07002379 if handle:
2380 return handle
Jon Hallc6358dd2015-04-10 12:44:28 -07002381 elif jsonFormat:
Jon Hallbe379602015-03-24 13:39:32 -07002382 # Return empty json
jenkins7ead5a82015-03-13 10:28:21 -07002383 return '{}'
Jon Hallc6358dd2015-04-10 12:44:28 -07002384 else:
2385 return handle
Jon Hallc6793552016-01-19 14:18:37 -08002386 except AssertionError:
2387 main.log.exception( "" )
2388 return None
Jon Halld4d4b372015-01-28 16:02:41 -08002389 except TypeError:
2390 main.log.exception( self.name + ": Object not as expected" )
2391 return None
andrewonlab867212a2014-10-22 20:13:38 -04002392 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08002393 main.log.error( self.name + ": EOF exception found" )
2394 main.log.error( self.name + ": " + self.handle.before )
andrewonlab867212a2014-10-22 20:13:38 -04002395 main.cleanup()
2396 main.exit()
Jon Hallfebb1c72015-03-05 13:30:09 -08002397 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -08002398 main.log.exception( self.name + ": Uncaught exception!" )
andrewonlab867212a2014-10-22 20:13:38 -04002399 main.cleanup()
2400 main.exit()
2401
kelvin8ec71442015-01-15 16:57:00 -08002402 # Wrapper functions ****************
2403 # Wrapper functions use existing driver
2404 # functions and extends their use case.
2405 # For example, we may use the output of
2406 # a normal driver function, and parse it
2407 # using a wrapper function
andrewonlabc2d05aa2014-10-13 16:51:10 -04002408
kelvin-onlabd3b64892015-01-20 13:26:24 -08002409 def getAllIntentsId( self ):
kelvin8ec71442015-01-15 16:57:00 -08002410 """
andrewonlab9a50dfe2014-10-17 17:22:31 -04002411 Description:
2412 Obtain all intent id's in a list
kelvin8ec71442015-01-15 16:57:00 -08002413 """
andrewonlab9a50dfe2014-10-17 17:22:31 -04002414 try:
kelvin8ec71442015-01-15 16:57:00 -08002415 # Obtain output of intents function
kelvin-onlabfb521662015-02-27 09:52:40 -08002416 intentsStr = self.intents(jsonFormat=False)
kelvin-onlabd3b64892015-01-20 13:26:24 -08002417 intentIdList = []
andrewonlab9a50dfe2014-10-17 17:22:31 -04002418
kelvin8ec71442015-01-15 16:57:00 -08002419 # Parse the intents output for ID's
kelvin-onlabd3b64892015-01-20 13:26:24 -08002420 intentsList = [ s.strip() for s in intentsStr.splitlines() ]
2421 for intents in intentsList:
kelvin-onlabfb521662015-02-27 09:52:40 -08002422 match = re.search('id=0x([\da-f]+),', intents)
2423 if match:
2424 tmpId = match.group()[3:-1]
2425 intentIdList.append( tmpId )
kelvin-onlabd3b64892015-01-20 13:26:24 -08002426 return intentIdList
andrewonlab9a50dfe2014-10-17 17:22:31 -04002427
Jon Halld4d4b372015-01-28 16:02:41 -08002428 except TypeError:
2429 main.log.exception( self.name + ": Object not as expected" )
2430 return None
andrewonlab9a50dfe2014-10-17 17:22:31 -04002431 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08002432 main.log.error( self.name + ": EOF exception found" )
2433 main.log.error( self.name + ": " + self.handle.before )
andrewonlab9a50dfe2014-10-17 17:22:31 -04002434 main.cleanup()
2435 main.exit()
Jon Hallfebb1c72015-03-05 13:30:09 -08002436 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -08002437 main.log.exception( self.name + ": Uncaught exception!" )
andrewonlab9a50dfe2014-10-17 17:22:31 -04002438 main.cleanup()
2439 main.exit()
2440
Jon Hall30b82fa2015-03-04 17:15:43 -08002441 def FlowAddedCount( self, deviceId ):
2442 """
2443 Determine the number of flow rules for the given device id that are
2444 in the added state
2445 """
2446 try:
2447 cmdStr = "flows any " + str( deviceId ) + " | " +\
2448 "grep 'state=ADDED' | wc -l"
2449 handle = self.sendline( cmdStr )
Jon Hallc6793552016-01-19 14:18:37 -08002450 assert "Command not found:" not in handle, handle
Jon Hall30b82fa2015-03-04 17:15:43 -08002451 return handle
Jon Hallc6793552016-01-19 14:18:37 -08002452 except AssertionError:
2453 main.log.exception( "" )
2454 return None
Jon Hall30b82fa2015-03-04 17:15:43 -08002455 except pexpect.EOF:
2456 main.log.error( self.name + ": EOF exception found" )
2457 main.log.error( self.name + ": " + self.handle.before )
2458 main.cleanup()
2459 main.exit()
Jon Hallfebb1c72015-03-05 13:30:09 -08002460 except Exception:
Jon Hall30b82fa2015-03-04 17:15:43 -08002461 main.log.exception( self.name + ": Uncaught exception!" )
andrewonlab95ce8322014-10-13 14:12:04 -04002462 main.cleanup()
2463 main.exit()
2464
kelvin-onlabd3b64892015-01-20 13:26:24 -08002465 def getAllDevicesId( self ):
kelvin8ec71442015-01-15 16:57:00 -08002466 """
andrewonlab7e4d2d32014-10-15 13:23:21 -04002467 Use 'devices' function to obtain list of all devices
2468 and parse the result to obtain a list of all device
2469 id's. Returns this list. Returns empty list if no
2470 devices exist
kelvin8ec71442015-01-15 16:57:00 -08002471 List is ordered sequentially
2472
andrewonlab3e15ead2014-10-15 14:21:34 -04002473 This function may be useful if you are not sure of the
kelvin8ec71442015-01-15 16:57:00 -08002474 device id, and wish to execute other commands using
andrewonlab3e15ead2014-10-15 14:21:34 -04002475 the ids. By obtaining the list of device ids on the fly,
2476 you can iterate through the list to get mastership, etc.
kelvin8ec71442015-01-15 16:57:00 -08002477 """
andrewonlab7e4d2d32014-10-15 13:23:21 -04002478 try:
kelvin8ec71442015-01-15 16:57:00 -08002479 # Call devices and store result string
kelvin-onlabd3b64892015-01-20 13:26:24 -08002480 devicesStr = self.devices( jsonFormat=False )
2481 idList = []
kelvin8ec71442015-01-15 16:57:00 -08002482
kelvin-onlabd3b64892015-01-20 13:26:24 -08002483 if not devicesStr:
kelvin8ec71442015-01-15 16:57:00 -08002484 main.log.info( "There are no devices to get id from" )
kelvin-onlabd3b64892015-01-20 13:26:24 -08002485 return idList
kelvin8ec71442015-01-15 16:57:00 -08002486
2487 # Split the string into list by comma
kelvin-onlabd3b64892015-01-20 13:26:24 -08002488 deviceList = devicesStr.split( "," )
kelvin8ec71442015-01-15 16:57:00 -08002489 # Get temporary list of all arguments with string 'id='
kelvin-onlabd3b64892015-01-20 13:26:24 -08002490 tempList = [ dev for dev in deviceList if "id=" in dev ]
kelvin8ec71442015-01-15 16:57:00 -08002491 # Split list further into arguments before and after string
2492 # 'id='. Get the latter portion ( the actual device id ) and
kelvin-onlabd3b64892015-01-20 13:26:24 -08002493 # append to idList
2494 for arg in tempList:
2495 idList.append( arg.split( "id=" )[ 1 ] )
2496 return idList
andrewonlab7e4d2d32014-10-15 13:23:21 -04002497
Jon Halld4d4b372015-01-28 16:02:41 -08002498 except TypeError:
2499 main.log.exception( self.name + ": Object not as expected" )
2500 return None
andrewonlab7e4d2d32014-10-15 13:23:21 -04002501 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08002502 main.log.error( self.name + ": EOF exception found" )
2503 main.log.error( self.name + ": " + self.handle.before )
andrewonlab7e4d2d32014-10-15 13:23:21 -04002504 main.cleanup()
2505 main.exit()
Jon Hallfebb1c72015-03-05 13:30:09 -08002506 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -08002507 main.log.exception( self.name + ": Uncaught exception!" )
andrewonlab7e4d2d32014-10-15 13:23:21 -04002508 main.cleanup()
2509 main.exit()
2510
kelvin-onlabd3b64892015-01-20 13:26:24 -08002511 def getAllNodesId( self ):
kelvin8ec71442015-01-15 16:57:00 -08002512 """
andrewonlab7c211572014-10-15 16:45:20 -04002513 Uses 'nodes' function to obtain list of all nodes
2514 and parse the result of nodes to obtain just the
kelvin8ec71442015-01-15 16:57:00 -08002515 node id's.
andrewonlab7c211572014-10-15 16:45:20 -04002516 Returns:
2517 list of node id's
kelvin8ec71442015-01-15 16:57:00 -08002518 """
andrewonlab7c211572014-10-15 16:45:20 -04002519 try:
Jon Hall5aa168b2015-03-23 14:23:09 -07002520 nodesStr = self.nodes( jsonFormat=True )
kelvin-onlabd3b64892015-01-20 13:26:24 -08002521 idList = []
Jon Hall5aa168b2015-03-23 14:23:09 -07002522 # Sample nodesStr output
Jon Hallbd182782016-03-28 16:42:22 -07002523 # id=local, address=127.0.0.1:9876, state=READY *
kelvin-onlabd3b64892015-01-20 13:26:24 -08002524 if not nodesStr:
kelvin8ec71442015-01-15 16:57:00 -08002525 main.log.info( "There are no nodes to get id from" )
kelvin-onlabd3b64892015-01-20 13:26:24 -08002526 return idList
Jon Hall5aa168b2015-03-23 14:23:09 -07002527 nodesJson = json.loads( nodesStr )
2528 idList = [ node.get('id') for node in nodesJson ]
kelvin-onlabd3b64892015-01-20 13:26:24 -08002529 return idList
Jon Hallc6793552016-01-19 14:18:37 -08002530 except ( TypeError, ValueError ):
2531 main.log.exception( "{}: Object not as expected: {!r}".format( self.name, nodesStr ) )
Jon Halld4d4b372015-01-28 16:02:41 -08002532 return None
andrewonlab7c211572014-10-15 16:45:20 -04002533 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08002534 main.log.error( self.name + ": EOF exception found" )
2535 main.log.error( self.name + ": " + self.handle.before )
andrewonlab7c211572014-10-15 16:45:20 -04002536 main.cleanup()
2537 main.exit()
Jon Hallfebb1c72015-03-05 13:30:09 -08002538 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -08002539 main.log.exception( self.name + ": Uncaught exception!" )
andrewonlab7c211572014-10-15 16:45:20 -04002540 main.cleanup()
2541 main.exit()
andrewonlab7e4d2d32014-10-15 13:23:21 -04002542
kelvin-onlabd3b64892015-01-20 13:26:24 -08002543 def getDevice( self, dpid=None ):
kelvin8ec71442015-01-15 16:57:00 -08002544 """
Jon Halla91c4dc2014-10-22 12:57:04 -04002545 Return the first device from the devices api whose 'id' contains 'dpid'
2546 Return None if there is no match
kelvin8ec71442015-01-15 16:57:00 -08002547 """
Jon Halla91c4dc2014-10-22 12:57:04 -04002548 try:
kelvin8ec71442015-01-15 16:57:00 -08002549 if dpid is None:
Jon Halla91c4dc2014-10-22 12:57:04 -04002550 return None
2551 else:
kelvin8ec71442015-01-15 16:57:00 -08002552 dpid = dpid.replace( ':', '' )
kelvin-onlabd3b64892015-01-20 13:26:24 -08002553 rawDevices = self.devices()
2554 devicesJson = json.loads( rawDevices )
kelvin8ec71442015-01-15 16:57:00 -08002555 # search json for the device with dpid then return the device
kelvin-onlabd3b64892015-01-20 13:26:24 -08002556 for device in devicesJson:
kelvin8ec71442015-01-15 16:57:00 -08002557 # print "%s in %s?" % ( dpid, device[ 'id' ] )
2558 if dpid in device[ 'id' ]:
Jon Halla91c4dc2014-10-22 12:57:04 -04002559 return device
2560 return None
Jon Hallc6793552016-01-19 14:18:37 -08002561 except ( TypeError, ValueError ):
2562 main.log.exception( "{}: Object not as expected: {!r}".format( self.name, rawDevices ) )
Jon Halld4d4b372015-01-28 16:02:41 -08002563 return None
Jon Halla91c4dc2014-10-22 12:57:04 -04002564 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08002565 main.log.error( self.name + ": EOF exception found" )
2566 main.log.error( self.name + ": " + self.handle.before )
Jon Halla91c4dc2014-10-22 12:57:04 -04002567 main.cleanup()
2568 main.exit()
Jon Hallfebb1c72015-03-05 13:30:09 -08002569 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -08002570 main.log.exception( self.name + ": Uncaught exception!" )
Jon Halla91c4dc2014-10-22 12:57:04 -04002571 main.cleanup()
2572 main.exit()
2573
kelvin-onlabd3b64892015-01-20 13:26:24 -08002574 def checkStatus( self, ip, numoswitch, numolink, logLevel="info" ):
kelvin8ec71442015-01-15 16:57:00 -08002575 """
Jon Hallefbd9792015-03-05 16:11:36 -08002576 Checks the number of switches & links that ONOS sees against the
kelvin8ec71442015-01-15 16:57:00 -08002577 supplied values. By default this will report to main.log, but the
Jon Hallefbd9792015-03-05 16:11:36 -08002578 log level can be specified.
kelvin8ec71442015-01-15 16:57:00 -08002579
Jon Hall42db6dc2014-10-24 19:03:48 -04002580 Params: ip = ip used for the onos cli
2581 numoswitch = expected number of switches
Jon Hallefbd9792015-03-05 16:11:36 -08002582 numolink = expected number of links
kelvin-onlabd3b64892015-01-20 13:26:24 -08002583 logLevel = level to log to. Currently accepts
2584 'info', 'warn' and 'report'
Jon Hall42db6dc2014-10-24 19:03:48 -04002585
2586
kelvin-onlabd3b64892015-01-20 13:26:24 -08002587 logLevel can
Jon Hall42db6dc2014-10-24 19:03:48 -04002588
Jon Hallefbd9792015-03-05 16:11:36 -08002589 Returns: main.TRUE if the number of switches and links are correct,
2590 main.FALSE if the number of switches and links is incorrect,
Jon Hall42db6dc2014-10-24 19:03:48 -04002591 and main.ERROR otherwise
kelvin8ec71442015-01-15 16:57:00 -08002592 """
Jon Hall42db6dc2014-10-24 19:03:48 -04002593 try:
kelvin-onlabd3b64892015-01-20 13:26:24 -08002594 topology = self.getTopology( ip )
Jon Hall42db6dc2014-10-24 19:03:48 -04002595 if topology == {}:
2596 return main.ERROR
2597 output = ""
kelvin8ec71442015-01-15 16:57:00 -08002598 # Is the number of switches is what we expected
2599 devices = topology.get( 'devices', False )
2600 links = topology.get( 'links', False )
kelvin-onlabfb521662015-02-27 09:52:40 -08002601 if devices is False or links is False:
Jon Hall42db6dc2014-10-24 19:03:48 -04002602 return main.ERROR
kelvin-onlabd3b64892015-01-20 13:26:24 -08002603 switchCheck = ( int( devices ) == int( numoswitch ) )
kelvin8ec71442015-01-15 16:57:00 -08002604 # Is the number of links is what we expected
kelvin-onlabd3b64892015-01-20 13:26:24 -08002605 linkCheck = ( int( links ) == int( numolink ) )
2606 if ( switchCheck and linkCheck ):
kelvin8ec71442015-01-15 16:57:00 -08002607 # We expected the correct numbers
Jon Hallefbd9792015-03-05 16:11:36 -08002608 output += "The number of links and switches match " +\
2609 "what was expected"
Jon Hall42db6dc2014-10-24 19:03:48 -04002610 result = main.TRUE
2611 else:
Jon Hallefbd9792015-03-05 16:11:36 -08002612 output += "The number of links and switches does not match " +\
2613 "what was expected"
Jon Hall42db6dc2014-10-24 19:03:48 -04002614 result = main.FALSE
kelvin-onlabd3b64892015-01-20 13:26:24 -08002615 output = output + "\n ONOS sees %i devices (%i expected) \
2616 and %i links (%i expected)" % (
2617 int( devices ), int( numoswitch ), int( links ),
2618 int( numolink ) )
2619 if logLevel == "report":
kelvin8ec71442015-01-15 16:57:00 -08002620 main.log.report( output )
kelvin-onlabd3b64892015-01-20 13:26:24 -08002621 elif logLevel == "warn":
kelvin8ec71442015-01-15 16:57:00 -08002622 main.log.warn( output )
Jon Hall42db6dc2014-10-24 19:03:48 -04002623 else:
Jon Hall390696c2015-05-05 17:13:41 -07002624 main.log.info( self.name + ": " + output )
kelvin8ec71442015-01-15 16:57:00 -08002625 return result
Jon Halld4d4b372015-01-28 16:02:41 -08002626 except TypeError:
2627 main.log.exception( self.name + ": Object not as expected" )
2628 return None
Jon Hall42db6dc2014-10-24 19:03:48 -04002629 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08002630 main.log.error( self.name + ": EOF exception found" )
2631 main.log.error( self.name + ": " + self.handle.before )
Jon Hall42db6dc2014-10-24 19:03:48 -04002632 main.cleanup()
2633 main.exit()
Jon Hallfebb1c72015-03-05 13:30:09 -08002634 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -08002635 main.log.exception( self.name + ": Uncaught exception!" )
Jon Hall42db6dc2014-10-24 19:03:48 -04002636 main.cleanup()
2637 main.exit()
Jon Hall1c9e8732014-10-27 19:29:27 -04002638
kelvin-onlabd3b64892015-01-20 13:26:24 -08002639 def deviceRole( self, deviceId, onosNode, role="master" ):
kelvin8ec71442015-01-15 16:57:00 -08002640 """
Jon Hall1c9e8732014-10-27 19:29:27 -04002641 Calls the device-role cli command.
kelvin-onlabd3b64892015-01-20 13:26:24 -08002642 deviceId must be the id of a device as seen in the onos devices command
2643 onosNode is the ip of one of the onos nodes in the cluster
Jon Hall1c9e8732014-10-27 19:29:27 -04002644 role must be either master, standby, or none
2645
Jon Halle3f39ff2015-01-13 11:50:53 -08002646 Returns:
2647 main.TRUE or main.FALSE based on argument verification and
2648 main.ERROR if command returns and error
kelvin-onlab898a6c62015-01-16 14:13:53 -08002649 """
Jon Hall1c9e8732014-10-27 19:29:27 -04002650 try:
Jon Halle3f39ff2015-01-13 11:50:53 -08002651 if role.lower() == "master" or role.lower() == "standby" or\
Jon Hall1c9e8732014-10-27 19:29:27 -04002652 role.lower() == "none":
kelvin-onlabd3b64892015-01-20 13:26:24 -08002653 cmdStr = "device-role " +\
2654 str( deviceId ) + " " +\
2655 str( onosNode ) + " " +\
kelvin-onlab898a6c62015-01-16 14:13:53 -08002656 str( role )
kelvin-onlabd3b64892015-01-20 13:26:24 -08002657 handle = self.sendline( cmdStr )
Jon Hallc6793552016-01-19 14:18:37 -08002658 assert "Command not found:" not in handle, handle
kelvin-onlab898a6c62015-01-16 14:13:53 -08002659 if re.search( "Error", handle ):
2660 # end color output to escape any colours
2661 # from the cli
kelvin8ec71442015-01-15 16:57:00 -08002662 main.log.error( self.name + ": " +
kelvin-onlab898a6c62015-01-16 14:13:53 -08002663 handle + '\033[0m' )
kelvin8ec71442015-01-15 16:57:00 -08002664 return main.ERROR
kelvin8ec71442015-01-15 16:57:00 -08002665 return main.TRUE
Jon Hall1c9e8732014-10-27 19:29:27 -04002666 else:
kelvin-onlab898a6c62015-01-16 14:13:53 -08002667 main.log.error( "Invalid 'role' given to device_role(). " +
2668 "Value was '" + str(role) + "'." )
Jon Hall1c9e8732014-10-27 19:29:27 -04002669 return main.FALSE
Jon Hallc6793552016-01-19 14:18:37 -08002670 except AssertionError:
2671 main.log.exception( "" )
2672 return None
Jon Halld4d4b372015-01-28 16:02:41 -08002673 except TypeError:
2674 main.log.exception( self.name + ": Object not as expected" )
2675 return None
Jon Hall1c9e8732014-10-27 19:29:27 -04002676 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08002677 main.log.error( self.name + ": EOF exception found" )
2678 main.log.error( self.name + ": " + self.handle.before )
Jon Hall1c9e8732014-10-27 19:29:27 -04002679 main.cleanup()
2680 main.exit()
Jon Hallfebb1c72015-03-05 13:30:09 -08002681 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -08002682 main.log.exception( self.name + ": Uncaught exception!" )
Jon Hall1c9e8732014-10-27 19:29:27 -04002683 main.cleanup()
2684 main.exit()
2685
kelvin-onlabd3b64892015-01-20 13:26:24 -08002686 def clusters( self, jsonFormat=True ):
kelvin8ec71442015-01-15 16:57:00 -08002687 """
Jon Hall73cf9cc2014-11-20 22:28:38 -08002688 Lists all clusters
Jon Hallffb386d2014-11-21 13:43:38 -08002689 Optional argument:
kelvin-onlabd3b64892015-01-20 13:26:24 -08002690 * jsonFormat - boolean indicating if you want output in json
kelvin8ec71442015-01-15 16:57:00 -08002691 """
Jon Hall73cf9cc2014-11-20 22:28:38 -08002692 try:
Jon Hallc6358dd2015-04-10 12:44:28 -07002693 cmdStr = "clusters"
kelvin-onlabd3b64892015-01-20 13:26:24 -08002694 if jsonFormat:
Jon Hallc6358dd2015-04-10 12:44:28 -07002695 cmdStr += " -j"
2696 handle = self.sendline( cmdStr )
Jon Hallc6793552016-01-19 14:18:37 -08002697 assert "Command not found:" not in handle, handle
Jon Hallc6358dd2015-04-10 12:44:28 -07002698 return handle
Jon Hallc6793552016-01-19 14:18:37 -08002699 except AssertionError:
2700 main.log.exception( "" )
2701 return None
Jon Halld4d4b372015-01-28 16:02:41 -08002702 except TypeError:
2703 main.log.exception( self.name + ": Object not as expected" )
2704 return None
Jon Hall73cf9cc2014-11-20 22:28:38 -08002705 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08002706 main.log.error( self.name + ": EOF exception found" )
2707 main.log.error( self.name + ": " + self.handle.before )
Jon Hall73cf9cc2014-11-20 22:28:38 -08002708 main.cleanup()
2709 main.exit()
Jon Hallfebb1c72015-03-05 13:30:09 -08002710 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -08002711 main.log.exception( self.name + ": Uncaught exception!" )
Jon Hall73cf9cc2014-11-20 22:28:38 -08002712 main.cleanup()
2713 main.exit()
2714
kelvin-onlabd3b64892015-01-20 13:26:24 -08002715 def electionTestLeader( self ):
kelvin-onlab898a6c62015-01-16 14:13:53 -08002716 """
Jon Halle3f39ff2015-01-13 11:50:53 -08002717 CLI command to get the current leader for the Election test application
2718 NOTE: Requires installation of the onos-app-election feature
2719 Returns: Node IP of the leader if one exists
2720 None if none exists
2721 Main.FALSE on error
kelvin-onlab898a6c62015-01-16 14:13:53 -08002722 """
Jon Hall94fd0472014-12-08 11:52:42 -08002723 try:
kelvin-onlabd3b64892015-01-20 13:26:24 -08002724 cmdStr = "election-test-leader"
2725 response = self.sendline( cmdStr )
Jon Hallc6793552016-01-19 14:18:37 -08002726 assert "Command not found:" not in response, response
Jon Halle3f39ff2015-01-13 11:50:53 -08002727 # Leader
2728 leaderPattern = "The\scurrent\sleader\sfor\sthe\sElection\s" +\
kelvin-onlab898a6c62015-01-16 14:13:53 -08002729 "app\sis\s(?P<node>.+)\."
kelvin-onlabd3b64892015-01-20 13:26:24 -08002730 nodeSearch = re.search( leaderPattern, response )
2731 if nodeSearch:
2732 node = nodeSearch.group( 'node' )
Jon Halle3f39ff2015-01-13 11:50:53 -08002733 main.log.info( "Election-test-leader on " + str( self.name ) +
kelvin-onlab898a6c62015-01-16 14:13:53 -08002734 " found " + node + " as the leader" )
Jon Hall94fd0472014-12-08 11:52:42 -08002735 return node
Jon Halle3f39ff2015-01-13 11:50:53 -08002736 # no leader
2737 nullPattern = "There\sis\scurrently\sno\sleader\selected\sfor\s" +\
kelvin-onlab898a6c62015-01-16 14:13:53 -08002738 "the\sElection\sapp"
kelvin-onlabd3b64892015-01-20 13:26:24 -08002739 nullSearch = re.search( nullPattern, response )
2740 if nullSearch:
Jon Halle3f39ff2015-01-13 11:50:53 -08002741 main.log.info( "Election-test-leader found no leader on " +
kelvin-onlab898a6c62015-01-16 14:13:53 -08002742 self.name )
Jon Hall94fd0472014-12-08 11:52:42 -08002743 return None
kelvin-onlab898a6c62015-01-16 14:13:53 -08002744 # error
Jon Halle3f39ff2015-01-13 11:50:53 -08002745 errorPattern = "Command\snot\sfound"
kelvin-onlab898a6c62015-01-16 14:13:53 -08002746 if re.search( errorPattern, response ):
2747 main.log.error( "Election app is not loaded on " + self.name )
Jon Halle3f39ff2015-01-13 11:50:53 -08002748 # TODO: Should this be main.ERROR?
Jon Hall669173b2014-12-17 11:36:30 -08002749 return main.FALSE
2750 else:
Jon Hall390696c2015-05-05 17:13:41 -07002751 main.log.error( "Error in electionTestLeader on " + self.name +
2752 ": " + "unexpected response" )
kelvin8ec71442015-01-15 16:57:00 -08002753 main.log.error( repr( response ) )
Jon Hall669173b2014-12-17 11:36:30 -08002754 return main.FALSE
Jon Hallc6793552016-01-19 14:18:37 -08002755 except AssertionError:
2756 main.log.exception( "" )
2757 return None
Jon Halld4d4b372015-01-28 16:02:41 -08002758 except TypeError:
2759 main.log.exception( self.name + ": Object not as expected" )
2760 return main.FALSE
Jon Hall94fd0472014-12-08 11:52:42 -08002761 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08002762 main.log.error( self.name + ": EOF exception found" )
2763 main.log.error( self.name + ": " + self.handle.before )
Jon Hall94fd0472014-12-08 11:52:42 -08002764 main.cleanup()
2765 main.exit()
Jon Hallfebb1c72015-03-05 13:30:09 -08002766 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -08002767 main.log.exception( self.name + ": Uncaught exception!" )
Jon Hall94fd0472014-12-08 11:52:42 -08002768 main.cleanup()
2769 main.exit()
2770
kelvin-onlabd3b64892015-01-20 13:26:24 -08002771 def electionTestRun( self ):
kelvin-onlab898a6c62015-01-16 14:13:53 -08002772 """
Jon Halle3f39ff2015-01-13 11:50:53 -08002773 CLI command to run for leadership of the Election test application.
2774 NOTE: Requires installation of the onos-app-election feature
2775 Returns: Main.TRUE on success
2776 Main.FALSE on error
kelvin-onlab898a6c62015-01-16 14:13:53 -08002777 """
Jon Hall94fd0472014-12-08 11:52:42 -08002778 try:
kelvin-onlabd3b64892015-01-20 13:26:24 -08002779 cmdStr = "election-test-run"
2780 response = self.sendline( cmdStr )
Jon Hallc6793552016-01-19 14:18:37 -08002781 assert "Command not found:" not in response, response
kelvin-onlab898a6c62015-01-16 14:13:53 -08002782 # success
Jon Halle3f39ff2015-01-13 11:50:53 -08002783 successPattern = "Entering\sleadership\selections\sfor\sthe\s" +\
kelvin-onlab898a6c62015-01-16 14:13:53 -08002784 "Election\sapp."
Jon Halle3f39ff2015-01-13 11:50:53 -08002785 search = re.search( successPattern, response )
Jon Hall94fd0472014-12-08 11:52:42 -08002786 if search:
Jon Halle3f39ff2015-01-13 11:50:53 -08002787 main.log.info( self.name + " entering leadership elections " +
kelvin-onlab898a6c62015-01-16 14:13:53 -08002788 "for the Election app." )
Jon Hall94fd0472014-12-08 11:52:42 -08002789 return main.TRUE
kelvin-onlab898a6c62015-01-16 14:13:53 -08002790 # error
Jon Halle3f39ff2015-01-13 11:50:53 -08002791 errorPattern = "Command\snot\sfound"
2792 if re.search( errorPattern, response ):
2793 main.log.error( "Election app is not loaded on " + self.name )
Jon Hall669173b2014-12-17 11:36:30 -08002794 return main.FALSE
2795 else:
Jon Hall390696c2015-05-05 17:13:41 -07002796 main.log.error( "Error in electionTestRun on " + self.name +
2797 ": " + "unexpected response" )
Jon Halle3f39ff2015-01-13 11:50:53 -08002798 main.log.error( repr( response ) )
Jon Hall669173b2014-12-17 11:36:30 -08002799 return main.FALSE
Jon Hallc6793552016-01-19 14:18:37 -08002800 except AssertionError:
2801 main.log.exception( "" )
2802 return None
Jon Halld4d4b372015-01-28 16:02:41 -08002803 except TypeError:
2804 main.log.exception( self.name + ": Object not as expected" )
2805 return main.FALSE
Jon Hall94fd0472014-12-08 11:52:42 -08002806 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08002807 main.log.error( self.name + ": EOF exception found" )
2808 main.log.error( self.name + ": " + self.handle.before )
Jon Hall94fd0472014-12-08 11:52:42 -08002809 main.cleanup()
2810 main.exit()
Jon Hallfebb1c72015-03-05 13:30:09 -08002811 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -08002812 main.log.exception( self.name + ": Uncaught exception!" )
Jon Hall94fd0472014-12-08 11:52:42 -08002813 main.cleanup()
2814 main.exit()
2815
kelvin-onlabd3b64892015-01-20 13:26:24 -08002816 def electionTestWithdraw( self ):
kelvin8ec71442015-01-15 16:57:00 -08002817 """
Jon Hall94fd0472014-12-08 11:52:42 -08002818 * CLI command to withdraw the local node from leadership election for
2819 * the Election test application.
2820 #NOTE: Requires installation of the onos-app-election feature
2821 Returns: Main.TRUE on success
2822 Main.FALSE on error
kelvin8ec71442015-01-15 16:57:00 -08002823 """
Jon Hall94fd0472014-12-08 11:52:42 -08002824 try:
kelvin-onlabd3b64892015-01-20 13:26:24 -08002825 cmdStr = "election-test-withdraw"
2826 response = self.sendline( cmdStr )
Jon Hallc6793552016-01-19 14:18:37 -08002827 assert "Command not found:" not in response, response
kelvin-onlab898a6c62015-01-16 14:13:53 -08002828 # success
Jon Halle3f39ff2015-01-13 11:50:53 -08002829 successPattern = "Withdrawing\sfrom\sleadership\selections\sfor" +\
kelvin-onlab898a6c62015-01-16 14:13:53 -08002830 "\sthe\sElection\sapp."
Jon Halle3f39ff2015-01-13 11:50:53 -08002831 if re.search( successPattern, response ):
2832 main.log.info( self.name + " withdrawing from leadership " +
kelvin-onlab898a6c62015-01-16 14:13:53 -08002833 "elections for the Election app." )
Jon Hall94fd0472014-12-08 11:52:42 -08002834 return main.TRUE
kelvin-onlab898a6c62015-01-16 14:13:53 -08002835 # error
Jon Halle3f39ff2015-01-13 11:50:53 -08002836 errorPattern = "Command\snot\sfound"
2837 if re.search( errorPattern, response ):
2838 main.log.error( "Election app is not loaded on " + self.name )
Jon Hall669173b2014-12-17 11:36:30 -08002839 return main.FALSE
2840 else:
Jon Hall390696c2015-05-05 17:13:41 -07002841 main.log.error( "Error in electionTestWithdraw on " +
2842 self.name + ": " + "unexpected response" )
Jon Halle3f39ff2015-01-13 11:50:53 -08002843 main.log.error( repr( response ) )
Jon Hall669173b2014-12-17 11:36:30 -08002844 return main.FALSE
Jon Hallc6793552016-01-19 14:18:37 -08002845 except AssertionError:
2846 main.log.exception( "" )
2847 return None
Jon Halld4d4b372015-01-28 16:02:41 -08002848 except TypeError:
2849 main.log.exception( self.name + ": Object not as expected" )
2850 return main.FALSE
Jon Hall94fd0472014-12-08 11:52:42 -08002851 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08002852 main.log.error( self.name + ": EOF exception found" )
2853 main.log.error( self.name + ": " + self.handle.before )
Jon Hall94fd0472014-12-08 11:52:42 -08002854 main.cleanup()
2855 main.exit()
Jon Hallfebb1c72015-03-05 13:30:09 -08002856 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -08002857 main.log.exception( self.name + ": Uncaught exception!" )
Jon Hall94fd0472014-12-08 11:52:42 -08002858 main.cleanup()
2859 main.exit()
Jon Hall1c9e8732014-10-27 19:29:27 -04002860
kelvin8ec71442015-01-15 16:57:00 -08002861 def getDevicePortsEnabledCount( self, dpid ):
2862 """
Hari Krishnaa43d4e92014-12-19 13:22:40 -08002863 Get the count of all enabled ports on a particular device/switch
kelvin8ec71442015-01-15 16:57:00 -08002864 """
Hari Krishnaa43d4e92014-12-19 13:22:40 -08002865 try:
Jon Halle3f39ff2015-01-13 11:50:53 -08002866 dpid = str( dpid )
kelvin-onlabd3b64892015-01-20 13:26:24 -08002867 cmdStr = "onos:ports -e " + dpid + " | wc -l"
2868 output = self.sendline( cmdStr )
Jon Hallc6793552016-01-19 14:18:37 -08002869 assert "Command not found:" not in output, output
Jon Halle3f39ff2015-01-13 11:50:53 -08002870 if re.search( "No such device", output ):
2871 main.log.error( "Error in getting ports" )
2872 return ( output, "Error" )
Hari Krishnaa43d4e92014-12-19 13:22:40 -08002873 else:
Jon Halle3f39ff2015-01-13 11:50:53 -08002874 return output
Jon Hallc6793552016-01-19 14:18:37 -08002875 except AssertionError:
2876 main.log.exception( "" )
2877 return None
Jon Halld4d4b372015-01-28 16:02:41 -08002878 except TypeError:
2879 main.log.exception( self.name + ": Object not as expected" )
2880 return ( output, "Error" )
Hari Krishnaa43d4e92014-12-19 13:22:40 -08002881 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08002882 main.log.error( self.name + ": EOF exception found" )
2883 main.log.error( self.name + ": " + self.handle.before )
Hari Krishnaa43d4e92014-12-19 13:22:40 -08002884 main.cleanup()
2885 main.exit()
Jon Hallfebb1c72015-03-05 13:30:09 -08002886 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -08002887 main.log.exception( self.name + ": Uncaught exception!" )
Hari Krishnaa43d4e92014-12-19 13:22:40 -08002888 main.cleanup()
2889 main.exit()
2890
kelvin8ec71442015-01-15 16:57:00 -08002891 def getDeviceLinksActiveCount( self, dpid ):
2892 """
Hari Krishnaa43d4e92014-12-19 13:22:40 -08002893 Get the count of all enabled ports on a particular device/switch
kelvin8ec71442015-01-15 16:57:00 -08002894 """
Hari Krishnaa43d4e92014-12-19 13:22:40 -08002895 try:
kelvin-onlab898a6c62015-01-16 14:13:53 -08002896 dpid = str( dpid )
kelvin-onlabd3b64892015-01-20 13:26:24 -08002897 cmdStr = "onos:links " + dpid + " | grep ACTIVE | wc -l"
2898 output = self.sendline( cmdStr )
Jon Hallc6793552016-01-19 14:18:37 -08002899 assert "Command not found:" not in output, output
Jon Halle3f39ff2015-01-13 11:50:53 -08002900 if re.search( "No such device", output ):
kelvin-onlab898a6c62015-01-16 14:13:53 -08002901 main.log.error( "Error in getting ports " )
2902 return ( output, "Error " )
Hari Krishnaa43d4e92014-12-19 13:22:40 -08002903 else:
Jon Halle3f39ff2015-01-13 11:50:53 -08002904 return output
Jon Hallc6793552016-01-19 14:18:37 -08002905 except AssertionError:
2906 main.log.exception( "" )
2907 return None
Jon Halld4d4b372015-01-28 16:02:41 -08002908 except TypeError:
2909 main.log.exception( self.name + ": Object not as expected" )
2910 return ( output, "Error " )
Hari Krishnaa43d4e92014-12-19 13:22:40 -08002911 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08002912 main.log.error( self.name + ": EOF exception found" )
2913 main.log.error( self.name + ": " + self.handle.before )
Hari Krishnaa43d4e92014-12-19 13:22:40 -08002914 main.cleanup()
2915 main.exit()
Jon Hallfebb1c72015-03-05 13:30:09 -08002916 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -08002917 main.log.exception( self.name + ": Uncaught exception!" )
Hari Krishnaa43d4e92014-12-19 13:22:40 -08002918 main.cleanup()
2919 main.exit()
2920
kelvin8ec71442015-01-15 16:57:00 -08002921 def getAllIntentIds( self ):
2922 """
Hari Krishnaa43d4e92014-12-19 13:22:40 -08002923 Return a list of all Intent IDs
kelvin8ec71442015-01-15 16:57:00 -08002924 """
Hari Krishnaa43d4e92014-12-19 13:22:40 -08002925 try:
kelvin-onlabd3b64892015-01-20 13:26:24 -08002926 cmdStr = "onos:intents | grep id="
2927 output = self.sendline( cmdStr )
Jon Hallc6793552016-01-19 14:18:37 -08002928 assert "Command not found:" not in output, output
Jon Halle3f39ff2015-01-13 11:50:53 -08002929 if re.search( "Error", output ):
2930 main.log.error( "Error in getting ports" )
2931 return ( output, "Error" )
Hari Krishnaa43d4e92014-12-19 13:22:40 -08002932 else:
Jon Halle3f39ff2015-01-13 11:50:53 -08002933 return output
Jon Hallc6793552016-01-19 14:18:37 -08002934 except AssertionError:
2935 main.log.exception( "" )
2936 return None
Jon Halld4d4b372015-01-28 16:02:41 -08002937 except TypeError:
2938 main.log.exception( self.name + ": Object not as expected" )
2939 return ( output, "Error" )
Hari Krishnaa43d4e92014-12-19 13:22:40 -08002940 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08002941 main.log.error( self.name + ": EOF exception found" )
2942 main.log.error( self.name + ": " + self.handle.before )
Hari Krishnaa43d4e92014-12-19 13:22:40 -08002943 main.cleanup()
2944 main.exit()
Jon Hallfebb1c72015-03-05 13:30:09 -08002945 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -08002946 main.log.exception( self.name + ": Uncaught exception!" )
2947 main.cleanup()
2948 main.exit()
2949
Jon Hall73509952015-02-24 16:42:56 -08002950 def intentSummary( self ):
2951 """
Jon Hallefbd9792015-03-05 16:11:36 -08002952 Returns a dictionary containing the current intent states and the count
Jon Hall73509952015-02-24 16:42:56 -08002953 """
2954 try:
2955 intents = self.intents( )
Jon Hall08f61bc2015-04-13 16:00:30 -07002956 states = []
Jon Hall5aa168b2015-03-23 14:23:09 -07002957 for intent in json.loads( intents ):
Jon Hall08f61bc2015-04-13 16:00:30 -07002958 states.append( intent.get( 'state', None ) )
2959 out = [ ( i, states.count( i ) ) for i in set( states ) ]
Jon Hall63604932015-02-26 17:09:50 -08002960 main.log.info( dict( out ) )
Jon Hall73509952015-02-24 16:42:56 -08002961 return dict( out )
Jon Hallc6793552016-01-19 14:18:37 -08002962 except ( TypeError, ValueError ):
2963 main.log.exception( "{}: Object not as expected: {!r}".format( self.name, intents ) )
Jon Hall73509952015-02-24 16:42:56 -08002964 return None
2965 except pexpect.EOF:
2966 main.log.error( self.name + ": EOF exception found" )
2967 main.log.error( self.name + ": " + self.handle.before )
2968 main.cleanup()
2969 main.exit()
Jon Hallfebb1c72015-03-05 13:30:09 -08002970 except Exception:
Jon Hall73509952015-02-24 16:42:56 -08002971 main.log.exception( self.name + ": Uncaught exception!" )
2972 main.cleanup()
2973 main.exit()
Jon Hall63604932015-02-26 17:09:50 -08002974
Jon Hall61282e32015-03-19 11:34:11 -07002975 def leaders( self, jsonFormat=True ):
Jon Hall63604932015-02-26 17:09:50 -08002976 """
2977 Returns the output of the leaders command.
Jon Hall61282e32015-03-19 11:34:11 -07002978 Optional argument:
2979 * jsonFormat - boolean indicating if you want output in json
Jon Hall63604932015-02-26 17:09:50 -08002980 """
Jon Hall63604932015-02-26 17:09:50 -08002981 try:
Jon Hallc6358dd2015-04-10 12:44:28 -07002982 cmdStr = "onos:leaders"
Jon Hall61282e32015-03-19 11:34:11 -07002983 if jsonFormat:
Jon Hallc6358dd2015-04-10 12:44:28 -07002984 cmdStr += " -j"
2985 output = self.sendline( cmdStr )
Jon Hallc6793552016-01-19 14:18:37 -08002986 assert "Command not found:" not in output, output
Jon Hallc6358dd2015-04-10 12:44:28 -07002987 return output
Jon Hallc6793552016-01-19 14:18:37 -08002988 except AssertionError:
2989 main.log.exception( "" )
2990 return None
Jon Hall63604932015-02-26 17:09:50 -08002991 except TypeError:
2992 main.log.exception( self.name + ": Object not as expected" )
2993 return None
Hari Krishnaa43d4e92014-12-19 13:22:40 -08002994 except pexpect.EOF:
2995 main.log.error( self.name + ": EOF exception found" )
2996 main.log.error( self.name + ": " + self.handle.before )
2997 main.cleanup()
2998 main.exit()
Jon Hall77ba41c2015-04-06 10:25:40 -07002999 except Exception:
Jon Hall63604932015-02-26 17:09:50 -08003000 main.log.exception( self.name + ": Uncaught exception!" )
Hari Krishnaa43d4e92014-12-19 13:22:40 -08003001 main.cleanup()
3002 main.exit()
Jon Hall63604932015-02-26 17:09:50 -08003003
acsmarsa4a4d1e2015-07-10 16:01:24 -07003004 def leaderCandidates( self, jsonFormat=True ):
3005 """
3006 Returns the output of the leaders -c command.
3007 Optional argument:
3008 * jsonFormat - boolean indicating if you want output in json
3009 """
3010 try:
3011 cmdStr = "onos:leaders -c"
3012 if jsonFormat:
3013 cmdStr += " -j"
3014 output = self.sendline( cmdStr )
Jon Hallc6793552016-01-19 14:18:37 -08003015 assert "Command not found:" not in output, output
acsmarsa4a4d1e2015-07-10 16:01:24 -07003016 return output
Jon Hallc6793552016-01-19 14:18:37 -08003017 except AssertionError:
3018 main.log.exception( "" )
3019 return None
acsmarsa4a4d1e2015-07-10 16:01:24 -07003020 except TypeError:
3021 main.log.exception( self.name + ": Object not as expected" )
3022 return None
3023 except pexpect.EOF:
3024 main.log.error( self.name + ": EOF exception found" )
3025 main.log.error( self.name + ": " + self.handle.before )
3026 main.cleanup()
3027 main.exit()
3028 except Exception:
3029 main.log.exception( self.name + ": Uncaught exception!" )
3030 main.cleanup()
3031 main.exit()
3032
Jon Hallc6793552016-01-19 14:18:37 -08003033 def specificLeaderCandidate( self, topic ):
acsmarsa4a4d1e2015-07-10 16:01:24 -07003034 """
3035 Returns a list in format [leader,candidate1,candidate2,...] for a given
3036 topic parameter and an empty list if the topic doesn't exist
3037 If no leader is elected leader in the returned list will be "none"
3038 Returns None if there is a type error processing the json object
3039 """
3040 try:
Jon Hall6e709752016-02-01 13:38:46 -08003041 cmdStr = "onos:leaders -j"
Jon Hallc6793552016-01-19 14:18:37 -08003042 rawOutput = self.sendline( cmdStr )
3043 assert "Command not found:" not in rawOutput, rawOutput
3044 output = json.loads( rawOutput )
acsmarsa4a4d1e2015-07-10 16:01:24 -07003045 results = []
3046 for dict in output:
3047 if dict["topic"] == topic:
3048 leader = dict["leader"]
Jon Hallc6793552016-01-19 14:18:37 -08003049 candidates = re.split( ", ", dict["candidates"][1:-1] )
3050 results.append( leader )
3051 results.extend( candidates )
acsmarsa4a4d1e2015-07-10 16:01:24 -07003052 return results
Jon Hallc6793552016-01-19 14:18:37 -08003053 except AssertionError:
3054 main.log.exception( "" )
3055 return None
3056 except ( TypeError, ValueError ):
3057 main.log.exception( "{}: Object not as expected: {!r}".format( self.name, rawOutput ) )
acsmarsa4a4d1e2015-07-10 16:01:24 -07003058 return None
3059 except pexpect.EOF:
3060 main.log.error( self.name + ": EOF exception found" )
3061 main.log.error( self.name + ": " + self.handle.before )
3062 main.cleanup()
3063 main.exit()
3064 except Exception:
3065 main.log.exception( self.name + ": Uncaught exception!" )
3066 main.cleanup()
3067 main.exit()
3068
Jon Hall61282e32015-03-19 11:34:11 -07003069 def pendingMap( self, jsonFormat=True ):
Jon Hall63604932015-02-26 17:09:50 -08003070 """
3071 Returns the output of the intent Pending map.
3072 """
Jon Hall63604932015-02-26 17:09:50 -08003073 try:
Jon Hallc6358dd2015-04-10 12:44:28 -07003074 cmdStr = "onos:intents -p"
Jon Hall61282e32015-03-19 11:34:11 -07003075 if jsonFormat:
Jon Hallc6358dd2015-04-10 12:44:28 -07003076 cmdStr += " -j"
3077 output = self.sendline( cmdStr )
Jon Hallc6793552016-01-19 14:18:37 -08003078 assert "Command not found:" not in output, output
Jon Hallc6358dd2015-04-10 12:44:28 -07003079 return output
Jon Hallc6793552016-01-19 14:18:37 -08003080 except AssertionError:
3081 main.log.exception( "" )
3082 return None
Jon Hall63604932015-02-26 17:09:50 -08003083 except TypeError:
3084 main.log.exception( self.name + ": Object not as expected" )
3085 return None
3086 except pexpect.EOF:
3087 main.log.error( self.name + ": EOF exception found" )
3088 main.log.error( self.name + ": " + self.handle.before )
3089 main.cleanup()
3090 main.exit()
Jon Hall77ba41c2015-04-06 10:25:40 -07003091 except Exception:
Jon Hall63604932015-02-26 17:09:50 -08003092 main.log.exception( self.name + ": Uncaught exception!" )
3093 main.cleanup()
3094 main.exit()
3095
Jon Hall61282e32015-03-19 11:34:11 -07003096 def partitions( self, jsonFormat=True ):
Jon Hall63604932015-02-26 17:09:50 -08003097 """
3098 Returns the output of the raft partitions command for ONOS.
3099 """
Jon Hall61282e32015-03-19 11:34:11 -07003100 # Sample JSON
3101 # {
3102 # "leader": "tcp://10.128.30.11:7238",
3103 # "members": [
3104 # "tcp://10.128.30.11:7238",
3105 # "tcp://10.128.30.17:7238",
3106 # "tcp://10.128.30.13:7238",
3107 # ],
3108 # "name": "p1",
3109 # "term": 3
3110 # },
Jon Hall63604932015-02-26 17:09:50 -08003111 try:
Jon Hallc6358dd2015-04-10 12:44:28 -07003112 cmdStr = "onos:partitions"
Jon Hall61282e32015-03-19 11:34:11 -07003113 if jsonFormat:
Jon Hallc6358dd2015-04-10 12:44:28 -07003114 cmdStr += " -j"
3115 output = self.sendline( cmdStr )
Jon Hallc6793552016-01-19 14:18:37 -08003116 assert "Command not found:" not in output, output
Jon Hallc6358dd2015-04-10 12:44:28 -07003117 return output
Jon Hallc6793552016-01-19 14:18:37 -08003118 except AssertionError:
3119 main.log.exception( "" )
3120 return None
Jon Hall63604932015-02-26 17:09:50 -08003121 except TypeError:
3122 main.log.exception( self.name + ": Object not as expected" )
3123 return None
3124 except pexpect.EOF:
3125 main.log.error( self.name + ": EOF exception found" )
3126 main.log.error( self.name + ": " + self.handle.before )
3127 main.cleanup()
3128 main.exit()
Jon Hall77ba41c2015-04-06 10:25:40 -07003129 except Exception:
Jon Hall63604932015-02-26 17:09:50 -08003130 main.log.exception( self.name + ": Uncaught exception!" )
3131 main.cleanup()
3132 main.exit()
3133
Jon Hallbe379602015-03-24 13:39:32 -07003134 def apps( self, jsonFormat=True ):
3135 """
3136 Returns the output of the apps command for ONOS. This command lists
3137 information about installed ONOS applications
3138 """
3139 # Sample JSON object
3140 # [{"name":"org.onosproject.openflow","id":0,"version":"1.2.0",
3141 # "description":"ONOS OpenFlow protocol southbound providers",
3142 # "origin":"ON.Lab","permissions":"[]","featuresRepo":"",
3143 # "features":"[onos-openflow]","state":"ACTIVE"}]
3144 try:
Jon Hallc6358dd2015-04-10 12:44:28 -07003145 cmdStr = "onos:apps"
Jon Hallbe379602015-03-24 13:39:32 -07003146 if jsonFormat:
Jon Hallc6358dd2015-04-10 12:44:28 -07003147 cmdStr += " -j"
3148 output = self.sendline( cmdStr )
Jon Hallc6793552016-01-19 14:18:37 -08003149 assert "Command not found:" not in output, output
3150 assert "Error executing command" not in output, output
Jon Hallc6358dd2015-04-10 12:44:28 -07003151 return output
Jon Hallbe379602015-03-24 13:39:32 -07003152 # FIXME: look at specific exceptions/Errors
3153 except AssertionError:
Jon Hallc6793552016-01-19 14:18:37 -08003154 main.log.exception( "Error in processing onos:app command." )
Jon Hallbe379602015-03-24 13:39:32 -07003155 return None
3156 except TypeError:
3157 main.log.exception( self.name + ": Object not as expected" )
3158 return None
3159 except pexpect.EOF:
3160 main.log.error( self.name + ": EOF exception found" )
3161 main.log.error( self.name + ": " + self.handle.before )
3162 main.cleanup()
3163 main.exit()
Jon Hall77ba41c2015-04-06 10:25:40 -07003164 except Exception:
Jon Hallbe379602015-03-24 13:39:32 -07003165 main.log.exception( self.name + ": Uncaught exception!" )
3166 main.cleanup()
3167 main.exit()
3168
Jon Hall146f1522015-03-24 15:33:24 -07003169 def appStatus( self, appName ):
3170 """
3171 Uses the onos:apps cli command to return the status of an application.
3172 Returns:
3173 "ACTIVE" - If app is installed and activated
3174 "INSTALLED" - If app is installed and deactivated
3175 "UNINSTALLED" - If app is not installed
3176 None - on error
3177 """
Jon Hall146f1522015-03-24 15:33:24 -07003178 try:
3179 if not isinstance( appName, types.StringType ):
3180 main.log.error( self.name + ".appStatus(): appName must be" +
3181 " a string" )
3182 return None
3183 output = self.apps( jsonFormat=True )
3184 appsJson = json.loads( output )
3185 state = None
3186 for app in appsJson:
3187 if appName == app.get('name'):
3188 state = app.get('state')
3189 break
3190 if state == "ACTIVE" or state == "INSTALLED":
3191 return state
3192 elif state is None:
3193 return "UNINSTALLED"
3194 elif state:
3195 main.log.error( "Unexpected state from 'onos:apps': " +
3196 str( state ) )
3197 return state
Jon Hallc6793552016-01-19 14:18:37 -08003198 except ( TypeError, ValueError ):
3199 main.log.exception( "{}: Object not as expected: {!r}".format( self.name, output ) )
Jon Hall146f1522015-03-24 15:33:24 -07003200 return None
3201 except pexpect.EOF:
3202 main.log.error( self.name + ": EOF exception found" )
3203 main.log.error( self.name + ": " + self.handle.before )
3204 main.cleanup()
3205 main.exit()
Jon Hall77ba41c2015-04-06 10:25:40 -07003206 except Exception:
Jon Hall146f1522015-03-24 15:33:24 -07003207 main.log.exception( self.name + ": Uncaught exception!" )
3208 main.cleanup()
3209 main.exit()
3210
Jon Hallbe379602015-03-24 13:39:32 -07003211 def app( self, appName, option ):
3212 """
3213 Interacts with the app command for ONOS. This command manages
3214 application inventory.
3215 """
Jon Hallbe379602015-03-24 13:39:32 -07003216 try:
Jon Hallbd16b922015-03-26 17:53:15 -07003217 # Validate argument types
3218 valid = True
3219 if not isinstance( appName, types.StringType ):
3220 main.log.error( self.name + ".app(): appName must be a " +
3221 "string" )
3222 valid = False
3223 if not isinstance( option, types.StringType ):
3224 main.log.error( self.name + ".app(): option must be a string" )
3225 valid = False
3226 if not valid:
3227 return main.FALSE
3228 # Validate Option
3229 option = option.lower()
3230 # NOTE: Install may become a valid option
3231 if option == "activate":
3232 pass
3233 elif option == "deactivate":
3234 pass
3235 elif option == "uninstall":
3236 pass
3237 else:
3238 # Invalid option
3239 main.log.error( "The ONOS app command argument only takes " +
3240 "the values: (activate|deactivate|uninstall)" +
3241 "; was given '" + option + "'")
3242 return main.FALSE
Jon Hall146f1522015-03-24 15:33:24 -07003243 cmdStr = "onos:app " + option + " " + appName
Jon Hallbe379602015-03-24 13:39:32 -07003244 output = self.sendline( cmdStr )
Jon Hallbe379602015-03-24 13:39:32 -07003245 if "Error executing command" in output:
3246 main.log.error( "Error in processing onos:app command: " +
3247 str( output ) )
Jon Hall146f1522015-03-24 15:33:24 -07003248 return main.FALSE
Jon Hallbe379602015-03-24 13:39:32 -07003249 elif "No such application" in output:
3250 main.log.error( "The application '" + appName +
3251 "' is not installed in ONOS" )
Jon Hall146f1522015-03-24 15:33:24 -07003252 return main.FALSE
3253 elif "Command not found:" in output:
3254 main.log.error( "Error in processing onos:app command: " +
3255 str( output ) )
3256 return main.FALSE
Jon Hallbd16b922015-03-26 17:53:15 -07003257 elif "Unsupported command:" in output:
3258 main.log.error( "Incorrect command given to 'app': " +
3259 str( output ) )
Jon Hallbe379602015-03-24 13:39:32 -07003260 # NOTE: we may need to add more checks here
Jon Hallbd16b922015-03-26 17:53:15 -07003261 # else: Command was successful
Jon Hall08f61bc2015-04-13 16:00:30 -07003262 # main.log.debug( "app response: " + repr( output ) )
Jon Hallbe379602015-03-24 13:39:32 -07003263 return main.TRUE
3264 except TypeError:
3265 main.log.exception( self.name + ": Object not as expected" )
3266 return main.ERROR
3267 except pexpect.EOF:
3268 main.log.error( self.name + ": EOF exception found" )
3269 main.log.error( self.name + ": " + self.handle.before )
3270 main.cleanup()
3271 main.exit()
Jon Hall77ba41c2015-04-06 10:25:40 -07003272 except Exception:
Jon Hallbe379602015-03-24 13:39:32 -07003273 main.log.exception( self.name + ": Uncaught exception!" )
3274 main.cleanup()
3275 main.exit()
Jon Hall146f1522015-03-24 15:33:24 -07003276
Jon Hallbd16b922015-03-26 17:53:15 -07003277 def activateApp( self, appName, check=True ):
Jon Hall146f1522015-03-24 15:33:24 -07003278 """
3279 Activate an app that is already installed in ONOS
Jon Hallbd16b922015-03-26 17:53:15 -07003280 appName is the hierarchical app name, not the feature name
3281 If check is True, method will check the status of the app after the
3282 command is issued
Jon Hall146f1522015-03-24 15:33:24 -07003283 Returns main.TRUE if the command was successfully sent
3284 main.FALSE if the cli responded with an error or given
3285 incorrect input
3286 """
3287 try:
3288 if not isinstance( appName, types.StringType ):
3289 main.log.error( self.name + ".activateApp(): appName must be" +
3290 " a string" )
3291 return main.FALSE
3292 status = self.appStatus( appName )
3293 if status == "INSTALLED":
3294 response = self.app( appName, "activate" )
Jon Hallbd16b922015-03-26 17:53:15 -07003295 if check and response == main.TRUE:
3296 for i in range(10): # try 10 times then give up
Jon Hallbd16b922015-03-26 17:53:15 -07003297 status = self.appStatus( appName )
3298 if status == "ACTIVE":
3299 return main.TRUE
3300 else:
Jon Hall050e1bd2015-03-30 13:33:02 -07003301 main.log.debug( "The state of application " +
3302 appName + " is " + status )
Jon Hallbd16b922015-03-26 17:53:15 -07003303 time.sleep( 1 )
3304 return main.FALSE
3305 else: # not 'check' or command didn't succeed
3306 return response
Jon Hall146f1522015-03-24 15:33:24 -07003307 elif status == "ACTIVE":
3308 return main.TRUE
3309 elif status == "UNINSTALLED":
3310 main.log.error( self.name + ": Tried to activate the " +
3311 "application '" + appName + "' which is not " +
3312 "installed." )
3313 else:
3314 main.log.error( "Unexpected return value from appStatus: " +
3315 str( status ) )
3316 return main.ERROR
3317 except TypeError:
3318 main.log.exception( self.name + ": Object not as expected" )
3319 return main.ERROR
3320 except pexpect.EOF:
3321 main.log.error( self.name + ": EOF exception found" )
3322 main.log.error( self.name + ": " + self.handle.before )
3323 main.cleanup()
3324 main.exit()
Jon Hall77ba41c2015-04-06 10:25:40 -07003325 except Exception:
Jon Hall146f1522015-03-24 15:33:24 -07003326 main.log.exception( self.name + ": Uncaught exception!" )
3327 main.cleanup()
3328 main.exit()
3329
Jon Hallbd16b922015-03-26 17:53:15 -07003330 def deactivateApp( self, appName, check=True ):
Jon Hall146f1522015-03-24 15:33:24 -07003331 """
3332 Deactivate an app that is already activated in ONOS
Jon Hallbd16b922015-03-26 17:53:15 -07003333 appName is the hierarchical app name, not the feature name
3334 If check is True, method will check the status of the app after the
3335 command is issued
Jon Hall146f1522015-03-24 15:33:24 -07003336 Returns main.TRUE if the command was successfully sent
3337 main.FALSE if the cli responded with an error or given
3338 incorrect input
3339 """
3340 try:
3341 if not isinstance( appName, types.StringType ):
3342 main.log.error( self.name + ".deactivateApp(): appName must " +
3343 "be a string" )
3344 return main.FALSE
3345 status = self.appStatus( appName )
3346 if status == "INSTALLED":
3347 return main.TRUE
3348 elif status == "ACTIVE":
3349 response = self.app( appName, "deactivate" )
Jon Hallbd16b922015-03-26 17:53:15 -07003350 if check and response == main.TRUE:
3351 for i in range(10): # try 10 times then give up
3352 status = self.appStatus( appName )
3353 if status == "INSTALLED":
3354 return main.TRUE
3355 else:
3356 time.sleep( 1 )
3357 return main.FALSE
3358 else: # not check or command didn't succeed
3359 return response
Jon Hall146f1522015-03-24 15:33:24 -07003360 elif status == "UNINSTALLED":
3361 main.log.warn( self.name + ": Tried to deactivate the " +
3362 "application '" + appName + "' which is not " +
3363 "installed." )
3364 return main.TRUE
3365 else:
3366 main.log.error( "Unexpected return value from appStatus: " +
3367 str( status ) )
3368 return main.ERROR
3369 except TypeError:
3370 main.log.exception( self.name + ": Object not as expected" )
3371 return main.ERROR
3372 except pexpect.EOF:
3373 main.log.error( self.name + ": EOF exception found" )
3374 main.log.error( self.name + ": " + self.handle.before )
3375 main.cleanup()
3376 main.exit()
Jon Hall77ba41c2015-04-06 10:25:40 -07003377 except Exception:
Jon Hall146f1522015-03-24 15:33:24 -07003378 main.log.exception( self.name + ": Uncaught exception!" )
3379 main.cleanup()
3380 main.exit()
3381
Jon Hallbd16b922015-03-26 17:53:15 -07003382 def uninstallApp( self, appName, check=True ):
Jon Hall146f1522015-03-24 15:33:24 -07003383 """
3384 Uninstall an app that is already installed in ONOS
Jon Hallbd16b922015-03-26 17:53:15 -07003385 appName is the hierarchical app name, not the feature name
3386 If check is True, method will check the status of the app after the
3387 command is issued
Jon Hall146f1522015-03-24 15:33:24 -07003388 Returns main.TRUE if the command was successfully sent
3389 main.FALSE if the cli responded with an error or given
3390 incorrect input
3391 """
3392 # TODO: check with Thomas about the state machine for apps
3393 try:
3394 if not isinstance( appName, types.StringType ):
3395 main.log.error( self.name + ".uninstallApp(): appName must " +
3396 "be a string" )
3397 return main.FALSE
3398 status = self.appStatus( appName )
3399 if status == "INSTALLED":
3400 response = self.app( appName, "uninstall" )
Jon Hallbd16b922015-03-26 17:53:15 -07003401 if check and response == main.TRUE:
3402 for i in range(10): # try 10 times then give up
3403 status = self.appStatus( appName )
3404 if status == "UNINSTALLED":
3405 return main.TRUE
3406 else:
3407 time.sleep( 1 )
3408 return main.FALSE
3409 else: # not check or command didn't succeed
3410 return response
Jon Hall146f1522015-03-24 15:33:24 -07003411 elif status == "ACTIVE":
3412 main.log.warn( self.name + ": Tried to uninstall the " +
3413 "application '" + appName + "' which is " +
3414 "currently active." )
3415 response = self.app( appName, "uninstall" )
Jon Hallbd16b922015-03-26 17:53:15 -07003416 if check and response == main.TRUE:
3417 for i in range(10): # try 10 times then give up
3418 status = self.appStatus( appName )
3419 if status == "UNINSTALLED":
3420 return main.TRUE
3421 else:
3422 time.sleep( 1 )
3423 return main.FALSE
3424 else: # not check or command didn't succeed
3425 return response
Jon Hall146f1522015-03-24 15:33:24 -07003426 elif status == "UNINSTALLED":
3427 return main.TRUE
3428 else:
3429 main.log.error( "Unexpected return value from appStatus: " +
3430 str( status ) )
3431 return main.ERROR
3432 except TypeError:
3433 main.log.exception( self.name + ": Object not as expected" )
3434 return main.ERROR
3435 except pexpect.EOF:
3436 main.log.error( self.name + ": EOF exception found" )
3437 main.log.error( self.name + ": " + self.handle.before )
3438 main.cleanup()
3439 main.exit()
Jon Hall77ba41c2015-04-06 10:25:40 -07003440 except Exception:
Jon Hall146f1522015-03-24 15:33:24 -07003441 main.log.exception( self.name + ": Uncaught exception!" )
3442 main.cleanup()
3443 main.exit()
Jon Hallbd16b922015-03-26 17:53:15 -07003444
3445 def appIDs( self, jsonFormat=True ):
3446 """
3447 Show the mappings between app id and app names given by the 'app-ids'
3448 cli command
3449 """
3450 try:
3451 cmdStr = "app-ids"
3452 if jsonFormat:
3453 cmdStr += " -j"
Jon Hallc6358dd2015-04-10 12:44:28 -07003454 output = self.sendline( cmdStr )
Jon Hallc6793552016-01-19 14:18:37 -08003455 assert "Command not found:" not in output, output
3456 assert "Error executing command" not in output, output
Jon Hallc6358dd2015-04-10 12:44:28 -07003457 return output
Jon Hallbd16b922015-03-26 17:53:15 -07003458 except AssertionError:
Jon Hallc6793552016-01-19 14:18:37 -08003459 main.log.exception( "Error in processing onos:app-ids command." )
Jon Hallbd16b922015-03-26 17:53:15 -07003460 return None
3461 except TypeError:
3462 main.log.exception( self.name + ": Object not as expected" )
3463 return None
3464 except pexpect.EOF:
3465 main.log.error( self.name + ": EOF exception found" )
3466 main.log.error( self.name + ": " + self.handle.before )
3467 main.cleanup()
3468 main.exit()
Jon Hall77ba41c2015-04-06 10:25:40 -07003469 except Exception:
Jon Hallbd16b922015-03-26 17:53:15 -07003470 main.log.exception( self.name + ": Uncaught exception!" )
3471 main.cleanup()
3472 main.exit()
3473
3474 def appToIDCheck( self ):
3475 """
3476 This method will check that each application's ID listed in 'apps' is
3477 the same as the ID listed in 'app-ids'. The check will also check that
3478 there are no duplicate IDs issued. Note that an app ID should be
3479 a globaly unique numerical identifier for app/app-like features. Once
3480 an ID is registered, the ID is never freed up so that if an app is
3481 reinstalled it will have the same ID.
3482
3483 Returns: main.TRUE if the check passes and
3484 main.FALSE if the check fails or
3485 main.ERROR if there is some error in processing the test
3486 """
3487 try:
Jon Hall390696c2015-05-05 17:13:41 -07003488 bail = False
Jon Hallc6793552016-01-19 14:18:37 -08003489 rawJson = self.appIDs( jsonFormat=True )
3490 if rawJson:
3491 ids = json.loads( rawJson )
Jon Hall390696c2015-05-05 17:13:41 -07003492 else:
Jon Hallc6793552016-01-19 14:18:37 -08003493 main.log.error( "app-ids returned nothing:" + repr( rawJson ) )
Jon Hall390696c2015-05-05 17:13:41 -07003494 bail = True
Jon Hallc6793552016-01-19 14:18:37 -08003495 rawJson = self.apps( jsonFormat=True )
3496 if rawJson:
3497 apps = json.loads( rawJson )
Jon Hall390696c2015-05-05 17:13:41 -07003498 else:
Jon Hallc6793552016-01-19 14:18:37 -08003499 main.log.error( "apps returned nothing:" + repr( rawJson ) )
Jon Hall390696c2015-05-05 17:13:41 -07003500 bail = True
3501 if bail:
3502 return main.FALSE
Jon Hallbd16b922015-03-26 17:53:15 -07003503 result = main.TRUE
3504 for app in apps:
3505 appID = app.get( 'id' )
3506 if appID is None:
3507 main.log.error( "Error parsing app: " + str( app ) )
3508 result = main.FALSE
3509 appName = app.get( 'name' )
3510 if appName is None:
3511 main.log.error( "Error parsing app: " + str( app ) )
3512 result = main.FALSE
3513 # get the entry in ids that has the same appID
Jon Hall390696c2015-05-05 17:13:41 -07003514 current = filter( lambda item: item[ 'id' ] == appID, ids )
Jon Hall050e1bd2015-03-30 13:33:02 -07003515 # main.log.debug( "Comparing " + str( app ) + " to " +
3516 # str( current ) )
Jon Hallbd16b922015-03-26 17:53:15 -07003517 if not current: # if ids doesn't have this id
3518 result = main.FALSE
3519 main.log.error( "'app-ids' does not have the ID for " +
3520 str( appName ) + " that apps does." )
3521 elif len( current ) > 1:
3522 # there is more than one app with this ID
3523 result = main.FALSE
3524 # We will log this later in the method
3525 elif not current[0][ 'name' ] == appName:
3526 currentName = current[0][ 'name' ]
3527 result = main.FALSE
3528 main.log.error( "'app-ids' has " + str( currentName ) +
3529 " registered under id:" + str( appID ) +
3530 " but 'apps' has " + str( appName ) )
3531 else:
3532 pass # id and name match!
3533 # now make sure that app-ids has no duplicates
3534 idsList = []
3535 namesList = []
3536 for item in ids:
3537 idsList.append( item[ 'id' ] )
3538 namesList.append( item[ 'name' ] )
3539 if len( idsList ) != len( set( idsList ) ) or\
3540 len( namesList ) != len( set( namesList ) ):
3541 main.log.error( "'app-ids' has some duplicate entries: \n"
3542 + json.dumps( ids,
3543 sort_keys=True,
3544 indent=4,
3545 separators=( ',', ': ' ) ) )
3546 result = main.FALSE
3547 return result
Jon Hallc6793552016-01-19 14:18:37 -08003548 except ( TypeError, ValueError ):
3549 main.log.exception( "{}: Object not as expected: {!r}".format( self.name, rawJson ) )
Jon Hallbd16b922015-03-26 17:53:15 -07003550 return main.ERROR
3551 except pexpect.EOF:
3552 main.log.error( self.name + ": EOF exception found" )
3553 main.log.error( self.name + ": " + self.handle.before )
3554 main.cleanup()
3555 main.exit()
Jon Hall77ba41c2015-04-06 10:25:40 -07003556 except Exception:
Jon Hallbd16b922015-03-26 17:53:15 -07003557 main.log.exception( self.name + ": Uncaught exception!" )
3558 main.cleanup()
3559 main.exit()
3560
Jon Hallfb760a02015-04-13 15:35:03 -07003561 def getCfg( self, component=None, propName=None, short=False,
3562 jsonFormat=True ):
3563 """
3564 Get configuration settings from onos cli
3565 Optional arguments:
3566 component - Optionally only list configurations for a specific
3567 component. If None, all components with configurations
3568 are displayed. Case Sensitive string.
3569 propName - If component is specified, propName option will show
3570 only this specific configuration from that component.
3571 Case Sensitive string.
3572 jsonFormat - Returns output as json. Note that this will override
3573 the short option
3574 short - Short, less verbose, version of configurations.
3575 This is overridden by the json option
3576 returns:
3577 Output from cli as a string or None on error
3578 """
3579 try:
3580 baseStr = "cfg"
3581 cmdStr = " get"
3582 componentStr = ""
3583 if component:
3584 componentStr += " " + component
3585 if propName:
3586 componentStr += " " + propName
3587 if jsonFormat:
3588 baseStr += " -j"
3589 elif short:
3590 baseStr += " -s"
3591 output = self.sendline( baseStr + cmdStr + componentStr )
Jon Hallc6793552016-01-19 14:18:37 -08003592 assert "Command not found:" not in output, output
3593 assert "Error executing command" not in output, output
Jon Hallfb760a02015-04-13 15:35:03 -07003594 return output
3595 except AssertionError:
Jon Hallc6793552016-01-19 14:18:37 -08003596 main.log.exception( "Error in processing 'cfg get' command." )
Jon Hallfb760a02015-04-13 15:35:03 -07003597 return None
3598 except TypeError:
3599 main.log.exception( self.name + ": Object not as expected" )
3600 return None
3601 except pexpect.EOF:
3602 main.log.error( self.name + ": EOF exception found" )
3603 main.log.error( self.name + ": " + self.handle.before )
3604 main.cleanup()
3605 main.exit()
3606 except Exception:
3607 main.log.exception( self.name + ": Uncaught exception!" )
3608 main.cleanup()
3609 main.exit()
3610
3611 def setCfg( self, component, propName, value=None, check=True ):
3612 """
3613 Set/Unset configuration settings from ONOS cli
Jon Hall390696c2015-05-05 17:13:41 -07003614 Required arguments:
Jon Hallfb760a02015-04-13 15:35:03 -07003615 component - The case sensitive name of the component whose
3616 property is to be set
3617 propName - The case sensitive name of the property to be set/unset
Jon Hall390696c2015-05-05 17:13:41 -07003618 Optional arguments:
Jon Hallfb760a02015-04-13 15:35:03 -07003619 value - The value to set the property to. If None, will unset the
3620 property and revert it to it's default value(if applicable)
3621 check - Boolean, Check whether the option was successfully set this
3622 only applies when a value is given.
3623 returns:
3624 main.TRUE on success or main.FALSE on failure. If check is False,
3625 will return main.TRUE unless there is an error
3626 """
3627 try:
3628 baseStr = "cfg"
3629 cmdStr = " set " + str( component ) + " " + str( propName )
3630 if value is not None:
3631 cmdStr += " " + str( value )
3632 output = self.sendline( baseStr + cmdStr )
Jon Hallc6793552016-01-19 14:18:37 -08003633 assert "Command not found:" not in output, output
3634 assert "Error executing command" not in output, output
Jon Hallfb760a02015-04-13 15:35:03 -07003635 if value and check:
3636 results = self.getCfg( component=str( component ),
3637 propName=str( propName ),
3638 jsonFormat=True )
3639 # Check if current value is what we just set
3640 try:
3641 jsonOutput = json.loads( results )
3642 current = jsonOutput[ 'value' ]
Jon Hallc6793552016-01-19 14:18:37 -08003643 except ( TypeError, ValueError ):
Jon Hallfb760a02015-04-13 15:35:03 -07003644 main.log.exception( "Error parsing cfg output" )
3645 main.log.error( "output:" + repr( results ) )
3646 return main.FALSE
3647 if current == str( value ):
3648 return main.TRUE
3649 return main.FALSE
3650 return main.TRUE
3651 except AssertionError:
Jon Hallc6793552016-01-19 14:18:37 -08003652 main.log.exception( "Error in processing 'cfg set' command." )
Jon Hallfb760a02015-04-13 15:35:03 -07003653 return main.FALSE
Jon Hallc6793552016-01-19 14:18:37 -08003654 except ( TypeError, ValueError ):
3655 main.log.exception( "{}: Object not as expected: {!r}".format( self.name, results ) )
Jon Hallfb760a02015-04-13 15:35:03 -07003656 return main.FALSE
3657 except pexpect.EOF:
3658 main.log.error( self.name + ": EOF exception found" )
3659 main.log.error( self.name + ": " + self.handle.before )
3660 main.cleanup()
3661 main.exit()
3662 except Exception:
3663 main.log.exception( self.name + ": Uncaught exception!" )
3664 main.cleanup()
3665 main.exit()
3666
Jon Hall390696c2015-05-05 17:13:41 -07003667 def setTestAdd( self, setName, values ):
3668 """
3669 CLI command to add elements to a distributed set.
3670 Arguments:
3671 setName - The name of the set to add to.
3672 values - The value(s) to add to the set, space seperated.
3673 Example usages:
3674 setTestAdd( "set1", "a b c" )
3675 setTestAdd( "set2", "1" )
3676 returns:
3677 main.TRUE on success OR
3678 main.FALSE if elements were already in the set OR
3679 main.ERROR on error
3680 """
3681 try:
3682 cmdStr = "set-test-add " + str( setName ) + " " + str( values )
3683 output = self.sendline( cmdStr )
Jon Hallc6793552016-01-19 14:18:37 -08003684 assert "Command not found:" not in output, output
Jon Hallfeff3082015-05-19 10:23:26 -07003685 try:
3686 # TODO: Maybe make this less hardcoded
3687 # ConsistentMap Exceptions
3688 assert "org.onosproject.store.service" not in output
3689 # Node not leader
3690 assert "java.lang.IllegalStateException" not in output
3691 except AssertionError:
Jon Halle1a3b752015-07-22 13:02:46 -07003692 main.log.error( "Error in processing '" + cmdStr + "' " +
Jon Hallfeff3082015-05-19 10:23:26 -07003693 "command: " + str( output ) )
3694 retryTime = 30 # Conservative time, given by Madan
3695 main.log.info( "Waiting " + str( retryTime ) +
3696 "seconds before retrying." )
3697 time.sleep( retryTime ) # Due to change in mastership
3698 output = self.sendline( cmdStr )
Jon Hall390696c2015-05-05 17:13:41 -07003699 assert "Error executing command" not in output
3700 positiveMatch = "\[(.*)\] was added to the set " + str( setName )
3701 negativeMatch = "\[(.*)\] was already in set " + str( setName )
3702 main.log.info( self.name + ": " + output )
3703 if re.search( positiveMatch, output):
3704 return main.TRUE
3705 elif re.search( negativeMatch, output):
3706 return main.FALSE
3707 else:
3708 main.log.error( self.name + ": setTestAdd did not" +
3709 " match expected output" )
Jon Hall390696c2015-05-05 17:13:41 -07003710 main.log.debug( self.name + " actual: " + repr( output ) )
3711 return main.ERROR
3712 except AssertionError:
Jon Hallc6793552016-01-19 14:18:37 -08003713 main.log.exception( "Error in processing '" + cmdStr + "' command. " )
Jon Hall390696c2015-05-05 17:13:41 -07003714 return main.ERROR
3715 except TypeError:
3716 main.log.exception( self.name + ": Object not as expected" )
3717 return main.ERROR
3718 except pexpect.EOF:
3719 main.log.error( self.name + ": EOF exception found" )
3720 main.log.error( self.name + ": " + self.handle.before )
3721 main.cleanup()
3722 main.exit()
3723 except Exception:
3724 main.log.exception( self.name + ": Uncaught exception!" )
3725 main.cleanup()
3726 main.exit()
3727
3728 def setTestRemove( self, setName, values, clear=False, retain=False ):
3729 """
3730 CLI command to remove elements from a distributed set.
3731 Required arguments:
3732 setName - The name of the set to remove from.
3733 values - The value(s) to remove from the set, space seperated.
3734 Optional arguments:
3735 clear - Clear all elements from the set
3736 retain - Retain only the given values. (intersection of the
3737 original set and the given set)
3738 returns:
3739 main.TRUE on success OR
3740 main.FALSE if the set was not changed OR
3741 main.ERROR on error
3742 """
3743 try:
3744 cmdStr = "set-test-remove "
3745 if clear:
3746 cmdStr += "-c " + str( setName )
3747 elif retain:
3748 cmdStr += "-r " + str( setName ) + " " + str( values )
3749 else:
3750 cmdStr += str( setName ) + " " + str( values )
3751 output = self.sendline( cmdStr )
Jon Hallfeff3082015-05-19 10:23:26 -07003752 try:
3753 # TODO: Maybe make this less hardcoded
3754 # ConsistentMap Exceptions
3755 assert "org.onosproject.store.service" not in output
3756 # Node not leader
3757 assert "java.lang.IllegalStateException" not in output
3758 except AssertionError:
Jon Halle1a3b752015-07-22 13:02:46 -07003759 main.log.error( "Error in processing '" + cmdStr + "' " +
Jon Hallfeff3082015-05-19 10:23:26 -07003760 "command: " + str( output ) )
3761 retryTime = 30 # Conservative time, given by Madan
3762 main.log.info( "Waiting " + str( retryTime ) +
3763 "seconds before retrying." )
3764 time.sleep( retryTime ) # Due to change in mastership
3765 output = self.sendline( cmdStr )
Jon Hallc6793552016-01-19 14:18:37 -08003766 assert "Command not found:" not in output, output
3767 assert "Error executing command" not in output, output
Jon Hall390696c2015-05-05 17:13:41 -07003768 main.log.info( self.name + ": " + output )
3769 if clear:
3770 pattern = "Set " + str( setName ) + " cleared"
3771 if re.search( pattern, output ):
3772 return main.TRUE
3773 elif retain:
3774 positivePattern = str( setName ) + " was pruned to contain " +\
3775 "only elements of set \[(.*)\]"
3776 negativePattern = str( setName ) + " was not changed by " +\
3777 "retaining only elements of the set " +\
3778 "\[(.*)\]"
3779 if re.search( positivePattern, output ):
3780 return main.TRUE
3781 elif re.search( negativePattern, output ):
3782 return main.FALSE
3783 else:
3784 positivePattern = "\[(.*)\] was removed from the set " +\
3785 str( setName )
3786 if ( len( values.split() ) == 1 ):
3787 negativePattern = "\[(.*)\] was not in set " +\
3788 str( setName )
3789 else:
3790 negativePattern = "No element of \[(.*)\] was in set " +\
3791 str( setName )
3792 if re.search( positivePattern, output ):
3793 return main.TRUE
3794 elif re.search( negativePattern, output ):
3795 return main.FALSE
3796 main.log.error( self.name + ": setTestRemove did not" +
3797 " match expected output" )
3798 main.log.debug( self.name + " expected: " + pattern )
3799 main.log.debug( self.name + " actual: " + repr( output ) )
3800 return main.ERROR
3801 except AssertionError:
Jon Hallc6793552016-01-19 14:18:37 -08003802 main.log.exception( "Error in processing '" + cmdStr + "' commandr. " )
Jon Hall390696c2015-05-05 17:13:41 -07003803 return main.ERROR
3804 except TypeError:
3805 main.log.exception( self.name + ": Object not as expected" )
3806 return main.ERROR
3807 except pexpect.EOF:
3808 main.log.error( self.name + ": EOF exception found" )
3809 main.log.error( self.name + ": " + self.handle.before )
3810 main.cleanup()
3811 main.exit()
3812 except Exception:
3813 main.log.exception( self.name + ": Uncaught exception!" )
3814 main.cleanup()
3815 main.exit()
3816
3817 def setTestGet( self, setName, values="" ):
3818 """
3819 CLI command to get the elements in a distributed set.
3820 Required arguments:
3821 setName - The name of the set to remove from.
3822 Optional arguments:
3823 values - The value(s) to check if in the set, space seperated.
3824 returns:
3825 main.ERROR on error OR
3826 A list of elements in the set if no optional arguments are
3827 supplied OR
3828 A tuple containing the list then:
3829 main.FALSE if the given values are not in the set OR
3830 main.TRUE if the given values are in the set OR
3831 """
3832 try:
3833 values = str( values ).strip()
3834 setName = str( setName ).strip()
3835 length = len( values.split() )
3836 containsCheck = None
3837 # Patterns to match
3838 setPattern = "\[(.*)\]"
3839 pattern = "Items in set " + setName + ":\n" + setPattern
3840 containsTrue = "Set " + setName + " contains the value " + values
3841 containsFalse = "Set " + setName + " did not contain the value " +\
3842 values
3843 containsAllTrue = "Set " + setName + " contains the the subset " +\
3844 setPattern
3845 containsAllFalse = "Set " + setName + " did not contain the the" +\
3846 " subset " + setPattern
3847
3848 cmdStr = "set-test-get "
3849 cmdStr += setName + " " + values
3850 output = self.sendline( cmdStr )
Jon Hallfeff3082015-05-19 10:23:26 -07003851 try:
3852 # TODO: Maybe make this less hardcoded
3853 # ConsistentMap Exceptions
3854 assert "org.onosproject.store.service" not in output
3855 # Node not leader
3856 assert "java.lang.IllegalStateException" not in output
3857 except AssertionError:
Jon Halle1a3b752015-07-22 13:02:46 -07003858 main.log.error( "Error in processing '" + cmdStr + "' " +
Jon Hallfeff3082015-05-19 10:23:26 -07003859 "command: " + str( output ) )
3860 retryTime = 30 # Conservative time, given by Madan
3861 main.log.info( "Waiting " + str( retryTime ) +
3862 "seconds before retrying." )
3863 time.sleep( retryTime ) # Due to change in mastership
3864 output = self.sendline( cmdStr )
Jon Hallc6793552016-01-19 14:18:37 -08003865 assert "Command not found:" not in output, output
3866 assert "Error executing command" not in output, output
Jon Hall390696c2015-05-05 17:13:41 -07003867 main.log.info( self.name + ": " + output )
3868
3869 if length == 0:
3870 match = re.search( pattern, output )
3871 else: # if given values
3872 if length == 1: # Contains output
3873 patternTrue = pattern + "\n" + containsTrue
3874 patternFalse = pattern + "\n" + containsFalse
3875 else: # ContainsAll output
3876 patternTrue = pattern + "\n" + containsAllTrue
3877 patternFalse = pattern + "\n" + containsAllFalse
3878 matchTrue = re.search( patternTrue, output )
3879 matchFalse = re.search( patternFalse, output )
3880 if matchTrue:
3881 containsCheck = main.TRUE
3882 match = matchTrue
3883 elif matchFalse:
3884 containsCheck = main.FALSE
3885 match = matchFalse
3886 else:
3887 main.log.error( self.name + " setTestGet did not match " +\
3888 "expected output" )
3889 main.log.debug( self.name + " expected: " + pattern )
3890 main.log.debug( self.name + " actual: " + repr( output ) )
3891 match = None
3892 if match:
3893 setMatch = match.group( 1 )
3894 if setMatch == '':
3895 setList = []
3896 else:
3897 setList = setMatch.split( ", " )
3898 if length > 0:
3899 return ( setList, containsCheck )
3900 else:
3901 return setList
3902 else: # no match
3903 main.log.error( self.name + ": setTestGet did not" +
3904 " match expected output" )
3905 main.log.debug( self.name + " expected: " + pattern )
3906 main.log.debug( self.name + " actual: " + repr( output ) )
3907 return main.ERROR
3908 except AssertionError:
Jon Hallc6793552016-01-19 14:18:37 -08003909 main.log.exception( "Error in processing '" + cmdStr + "' command." )
Jon Hall390696c2015-05-05 17:13:41 -07003910 return main.ERROR
3911 except TypeError:
3912 main.log.exception( self.name + ": Object not as expected" )
3913 return main.ERROR
3914 except pexpect.EOF:
3915 main.log.error( self.name + ": EOF exception found" )
3916 main.log.error( self.name + ": " + self.handle.before )
3917 main.cleanup()
3918 main.exit()
3919 except Exception:
3920 main.log.exception( self.name + ": Uncaught exception!" )
3921 main.cleanup()
3922 main.exit()
3923
3924 def setTestSize( self, setName ):
3925 """
3926 CLI command to get the elements in a distributed set.
3927 Required arguments:
3928 setName - The name of the set to remove from.
3929 returns:
Jon Hallfeff3082015-05-19 10:23:26 -07003930 The integer value of the size returned or
Jon Hall390696c2015-05-05 17:13:41 -07003931 None on error
3932 """
3933 try:
3934 # TODO: Should this check against the number of elements returned
3935 # and then return true/false based on that?
3936 setName = str( setName ).strip()
3937 # Patterns to match
3938 setPattern = "\[(.*)\]"
3939 pattern = "There are (\d+) items in set " + setName + ":\n" +\
3940 setPattern
3941 cmdStr = "set-test-get -s "
3942 cmdStr += setName
3943 output = self.sendline( cmdStr )
Jon Hallfeff3082015-05-19 10:23:26 -07003944 try:
3945 # TODO: Maybe make this less hardcoded
3946 # ConsistentMap Exceptions
3947 assert "org.onosproject.store.service" not in output
3948 # Node not leader
3949 assert "java.lang.IllegalStateException" not in output
3950 except AssertionError:
Jon Halle1a3b752015-07-22 13:02:46 -07003951 main.log.error( "Error in processing '" + cmdStr + "' " +
Jon Hallfeff3082015-05-19 10:23:26 -07003952 "command: " + str( output ) )
3953 retryTime = 30 # Conservative time, given by Madan
3954 main.log.info( "Waiting " + str( retryTime ) +
3955 "seconds before retrying." )
3956 time.sleep( retryTime ) # Due to change in mastership
3957 output = self.sendline( cmdStr )
Jon Hallc6793552016-01-19 14:18:37 -08003958 assert "Command not found:" not in output, output
3959 assert "Error executing command" not in output, output
Jon Hall390696c2015-05-05 17:13:41 -07003960 main.log.info( self.name + ": " + output )
3961 match = re.search( pattern, output )
3962 if match:
3963 setSize = int( match.group( 1 ) )
3964 setMatch = match.group( 2 )
3965 if len( setMatch.split() ) == setSize:
3966 main.log.info( "The size returned by " + self.name +
3967 " matches the number of elements in " +
3968 "the returned set" )
3969 else:
3970 main.log.error( "The size returned by " + self.name +
3971 " does not match the number of " +
3972 "elements in the returned set." )
3973 return setSize
3974 else: # no match
3975 main.log.error( self.name + ": setTestGet did not" +
3976 " match expected output" )
3977 main.log.debug( self.name + " expected: " + pattern )
3978 main.log.debug( self.name + " actual: " + repr( output ) )
3979 return None
3980 except AssertionError:
Jon Hallc6793552016-01-19 14:18:37 -08003981 main.log.exception( "Error in processing '" + cmdStr + "' command." )
acsmarsa4a4d1e2015-07-10 16:01:24 -07003982 return None
Jon Hall390696c2015-05-05 17:13:41 -07003983 except TypeError:
3984 main.log.exception( self.name + ": Object not as expected" )
3985 return None
3986 except pexpect.EOF:
3987 main.log.error( self.name + ": EOF exception found" )
3988 main.log.error( self.name + ": " + self.handle.before )
3989 main.cleanup()
3990 main.exit()
3991 except Exception:
3992 main.log.exception( self.name + ": Uncaught exception!" )
3993 main.cleanup()
3994 main.exit()
3995
Jon Hall80daded2015-05-27 16:07:00 -07003996 def counters( self, jsonFormat=True ):
Jon Hall390696c2015-05-05 17:13:41 -07003997 """
3998 Command to list the various counters in the system.
3999 returns:
Jon Hall80daded2015-05-27 16:07:00 -07004000 if jsonFormat, a string of the json object returned by the cli
4001 command
4002 if not jsonFormat, the normal string output of the cli command
Jon Hall390696c2015-05-05 17:13:41 -07004003 None on error
4004 """
Jon Hall390696c2015-05-05 17:13:41 -07004005 try:
4006 counters = {}
4007 cmdStr = "counters"
Jon Hall80daded2015-05-27 16:07:00 -07004008 if jsonFormat:
4009 cmdStr += " -j"
Jon Hall390696c2015-05-05 17:13:41 -07004010 output = self.sendline( cmdStr )
Jon Hallc6793552016-01-19 14:18:37 -08004011 assert "Command not found:" not in output, output
4012 assert "Error executing command" not in output, output
Jon Hall390696c2015-05-05 17:13:41 -07004013 main.log.info( self.name + ": " + output )
Jon Hall80daded2015-05-27 16:07:00 -07004014 return output
Jon Hall390696c2015-05-05 17:13:41 -07004015 except AssertionError:
Jon Hallc6793552016-01-19 14:18:37 -08004016 main.log.exception( "Error in processing 'counters' command." )
Jon Hall80daded2015-05-27 16:07:00 -07004017 return None
Jon Hall390696c2015-05-05 17:13:41 -07004018 except TypeError:
4019 main.log.exception( self.name + ": Object not as expected" )
Jon Hall80daded2015-05-27 16:07:00 -07004020 return None
Jon Hall390696c2015-05-05 17:13:41 -07004021 except pexpect.EOF:
4022 main.log.error( self.name + ": EOF exception found" )
4023 main.log.error( self.name + ": " + self.handle.before )
4024 main.cleanup()
4025 main.exit()
4026 except Exception:
4027 main.log.exception( self.name + ": Uncaught exception!" )
4028 main.cleanup()
4029 main.exit()
4030
Jon Halle1a3b752015-07-22 13:02:46 -07004031 def counterTestAddAndGet( self, counter, delta=1, inMemory=False ):
Jon Hall390696c2015-05-05 17:13:41 -07004032 """
Jon Halle1a3b752015-07-22 13:02:46 -07004033 CLI command to add a delta to then get a distributed counter.
Jon Hall390696c2015-05-05 17:13:41 -07004034 Required arguments:
4035 counter - The name of the counter to increment.
4036 Optional arguments:
Jon Halle1a3b752015-07-22 13:02:46 -07004037 delta - The long to add to the counter
Jon Hall390696c2015-05-05 17:13:41 -07004038 inMemory - use in memory map for the counter
4039 returns:
4040 integer value of the counter or
4041 None on Error
4042 """
4043 try:
4044 counter = str( counter )
Jon Halle1a3b752015-07-22 13:02:46 -07004045 delta = int( delta )
Jon Hall390696c2015-05-05 17:13:41 -07004046 cmdStr = "counter-test-increment "
4047 if inMemory:
4048 cmdStr += "-i "
4049 cmdStr += counter
Jon Halle1a3b752015-07-22 13:02:46 -07004050 if delta != 1:
4051 cmdStr += " " + str( delta )
Jon Hall390696c2015-05-05 17:13:41 -07004052 output = self.sendline( cmdStr )
Jon Hallfeff3082015-05-19 10:23:26 -07004053 try:
4054 # TODO: Maybe make this less hardcoded
4055 # ConsistentMap Exceptions
4056 assert "org.onosproject.store.service" not in output
4057 # Node not leader
4058 assert "java.lang.IllegalStateException" not in output
4059 except AssertionError:
Jon Halle1a3b752015-07-22 13:02:46 -07004060 main.log.error( "Error in processing '" + cmdStr + "' " +
Jon Hallfeff3082015-05-19 10:23:26 -07004061 "command: " + str( output ) )
4062 retryTime = 30 # Conservative time, given by Madan
4063 main.log.info( "Waiting " + str( retryTime ) +
4064 "seconds before retrying." )
4065 time.sleep( retryTime ) # Due to change in mastership
4066 output = self.sendline( cmdStr )
Jon Hallc6793552016-01-19 14:18:37 -08004067 assert "Command not found:" not in output, output
4068 assert "Error executing command" not in output, output
Jon Hall390696c2015-05-05 17:13:41 -07004069 main.log.info( self.name + ": " + output )
Jon Halle1a3b752015-07-22 13:02:46 -07004070 pattern = counter + " was updated to (-?\d+)"
Jon Hall390696c2015-05-05 17:13:41 -07004071 match = re.search( pattern, output )
4072 if match:
4073 return int( match.group( 1 ) )
4074 else:
Jon Halle1a3b752015-07-22 13:02:46 -07004075 main.log.error( self.name + ": counterTestAddAndGet did not" +
Jon Hall390696c2015-05-05 17:13:41 -07004076 " match expected output." )
4077 main.log.debug( self.name + " expected: " + pattern )
4078 main.log.debug( self.name + " actual: " + repr( output ) )
4079 return None
4080 except AssertionError:
Jon Hallc6793552016-01-19 14:18:37 -08004081 main.log.exception( "Error in processing '" + cmdStr + "' command." )
Jon Hall390696c2015-05-05 17:13:41 -07004082 return None
4083 except TypeError:
4084 main.log.exception( self.name + ": Object not as expected" )
4085 return None
4086 except pexpect.EOF:
4087 main.log.error( self.name + ": EOF exception found" )
4088 main.log.error( self.name + ": " + self.handle.before )
4089 main.cleanup()
4090 main.exit()
4091 except Exception:
4092 main.log.exception( self.name + ": Uncaught exception!" )
4093 main.cleanup()
4094 main.exit()
4095
Jon Halle1a3b752015-07-22 13:02:46 -07004096 def counterTestGetAndAdd( self, counter, delta=1, inMemory=False ):
4097 """
4098 CLI command to get a distributed counter then add a delta to it.
4099 Required arguments:
4100 counter - The name of the counter to increment.
4101 Optional arguments:
4102 delta - The long to add to the counter
4103 inMemory - use in memory map for the counter
4104 returns:
4105 integer value of the counter or
4106 None on Error
4107 """
4108 try:
4109 counter = str( counter )
4110 delta = int( delta )
4111 cmdStr = "counter-test-increment -g "
4112 if inMemory:
4113 cmdStr += "-i "
4114 cmdStr += counter
4115 if delta != 1:
4116 cmdStr += " " + str( delta )
4117 output = self.sendline( cmdStr )
4118 try:
4119 # TODO: Maybe make this less hardcoded
4120 # ConsistentMap Exceptions
4121 assert "org.onosproject.store.service" not in output
4122 # Node not leader
4123 assert "java.lang.IllegalStateException" not in output
4124 except AssertionError:
4125 main.log.error( "Error in processing '" + cmdStr + "' " +
4126 "command: " + str( output ) )
4127 retryTime = 30 # Conservative time, given by Madan
4128 main.log.info( "Waiting " + str( retryTime ) +
4129 "seconds before retrying." )
4130 time.sleep( retryTime ) # Due to change in mastership
4131 output = self.sendline( cmdStr )
Jon Hallc6793552016-01-19 14:18:37 -08004132 assert "Command not found:" not in output, output
4133 assert "Error executing command" not in output, output
Jon Halle1a3b752015-07-22 13:02:46 -07004134 main.log.info( self.name + ": " + output )
4135 pattern = counter + " was updated to (-?\d+)"
4136 match = re.search( pattern, output )
4137 if match:
4138 return int( match.group( 1 ) )
4139 else:
4140 main.log.error( self.name + ": counterTestGetAndAdd did not" +
4141 " match expected output." )
4142 main.log.debug( self.name + " expected: " + pattern )
4143 main.log.debug( self.name + " actual: " + repr( output ) )
4144 return None
4145 except AssertionError:
Jon Hallc6793552016-01-19 14:18:37 -08004146 main.log.exception( "Error in processing '" + cmdStr + "' command." )
Jon Halle1a3b752015-07-22 13:02:46 -07004147 return None
4148 except TypeError:
4149 main.log.exception( self.name + ": Object not as expected" )
4150 return None
4151 except pexpect.EOF:
4152 main.log.error( self.name + ": EOF exception found" )
4153 main.log.error( self.name + ": " + self.handle.before )
4154 main.cleanup()
4155 main.exit()
4156 except Exception:
4157 main.log.exception( self.name + ": Uncaught exception!" )
4158 main.cleanup()
4159 main.exit()
4160
kelvin-onlaba297c4d2015-06-01 13:53:55 -07004161 def summary( self, jsonFormat=True ):
4162 """
4163 Description: Execute summary command in onos
4164 Returns: json object ( summary -j ), returns main.FALSE if there is
4165 no output
4166
4167 """
4168 try:
4169 cmdStr = "summary"
4170 if jsonFormat:
4171 cmdStr += " -j"
4172 handle = self.sendline( cmdStr )
Jon Hallc6793552016-01-19 14:18:37 -08004173 assert "Command not found:" not in handle, handle
Jon Hall6e709752016-02-01 13:38:46 -08004174 assert "Error:" not in handle, handle
kelvin-onlaba297c4d2015-06-01 13:53:55 -07004175 if not handle:
4176 main.log.error( self.name + ": There is no output in " +
4177 "summary command" )
4178 return main.FALSE
4179 return handle
Jon Hallc6793552016-01-19 14:18:37 -08004180 except AssertionError:
Jon Hall6e709752016-02-01 13:38:46 -08004181 main.log.exception( "{} Error in summary output:".format( self.name ) )
Jon Hallc6793552016-01-19 14:18:37 -08004182 return None
kelvin-onlaba297c4d2015-06-01 13:53:55 -07004183 except TypeError:
4184 main.log.exception( self.name + ": Object not as expected" )
4185 return None
4186 except pexpect.EOF:
4187 main.log.error( self.name + ": EOF exception found" )
4188 main.log.error( self.name + ": " + self.handle.before )
4189 main.cleanup()
4190 main.exit()
4191 except Exception:
4192 main.log.exception( self.name + ": Uncaught exception!" )
4193 main.cleanup()
4194 main.exit()
Jon Hall2a5002c2015-08-21 16:49:11 -07004195
4196 def transactionalMapGet( self, keyName, inMemory=False ):
4197 """
4198 CLI command to get the value of a key in a consistent map using
4199 transactions. This a test function and can only get keys from the
4200 test map hard coded into the cli command
4201 Required arguments:
4202 keyName - The name of the key to get
4203 Optional arguments:
4204 inMemory - use in memory map for the counter
4205 returns:
4206 The string value of the key or
4207 None on Error
4208 """
4209 try:
4210 keyName = str( keyName )
4211 cmdStr = "transactional-map-test-get "
4212 if inMemory:
4213 cmdStr += "-i "
4214 cmdStr += keyName
4215 output = self.sendline( cmdStr )
Jon Hallc6793552016-01-19 14:18:37 -08004216 assert "Command not found:" not in output, output
Jon Hall2a5002c2015-08-21 16:49:11 -07004217 try:
4218 # TODO: Maybe make this less hardcoded
4219 # ConsistentMap Exceptions
4220 assert "org.onosproject.store.service" not in output
4221 # Node not leader
4222 assert "java.lang.IllegalStateException" not in output
4223 except AssertionError:
4224 main.log.error( "Error in processing '" + cmdStr + "' " +
4225 "command: " + str( output ) )
4226 return None
4227 pattern = "Key-value pair \(" + keyName + ", (?P<value>.+)\) found."
4228 if "Key " + keyName + " not found." in output:
4229 return None
4230 else:
4231 match = re.search( pattern, output )
4232 if match:
4233 return match.groupdict()[ 'value' ]
4234 else:
4235 main.log.error( self.name + ": transactionlMapGet did not" +
4236 " match expected output." )
4237 main.log.debug( self.name + " expected: " + pattern )
4238 main.log.debug( self.name + " actual: " + repr( output ) )
4239 return None
Jon Hallc6793552016-01-19 14:18:37 -08004240 except AssertionError:
4241 main.log.exception( "" )
4242 return None
Jon Hall2a5002c2015-08-21 16:49:11 -07004243 except TypeError:
4244 main.log.exception( self.name + ": Object not as expected" )
4245 return None
4246 except pexpect.EOF:
4247 main.log.error( self.name + ": EOF exception found" )
4248 main.log.error( self.name + ": " + self.handle.before )
4249 main.cleanup()
4250 main.exit()
4251 except Exception:
4252 main.log.exception( self.name + ": Uncaught exception!" )
4253 main.cleanup()
4254 main.exit()
4255
4256 def transactionalMapPut( self, numKeys, value, inMemory=False ):
4257 """
4258 CLI command to put a value into 'numKeys' number of keys in a
4259 consistent map using transactions. This a test function and can only
4260 put into keys named 'Key#' of the test map hard coded into the cli command
4261 Required arguments:
4262 numKeys - Number of keys to add the value to
4263 value - The string value to put into the keys
4264 Optional arguments:
4265 inMemory - use in memory map for the counter
4266 returns:
4267 A dictionary whose keys are the name of the keys put into the map
4268 and the values of the keys are dictionaries whose key-values are
4269 'value': value put into map and optionaly
4270 'oldValue': Previous value in the key or
4271 None on Error
4272
4273 Example output
4274 { 'Key1': {'oldValue': 'oldTestValue', 'value': 'Testing'},
4275 'Key2': {'value': 'Testing'} }
4276 """
4277 try:
4278 numKeys = str( numKeys )
4279 value = str( value )
4280 cmdStr = "transactional-map-test-put "
4281 if inMemory:
4282 cmdStr += "-i "
4283 cmdStr += numKeys + " " + value
4284 output = self.sendline( cmdStr )
Jon Hallc6793552016-01-19 14:18:37 -08004285 assert "Command not found:" not in output, output
Jon Hall2a5002c2015-08-21 16:49:11 -07004286 try:
4287 # TODO: Maybe make this less hardcoded
4288 # ConsistentMap Exceptions
4289 assert "org.onosproject.store.service" not in output
4290 # Node not leader
4291 assert "java.lang.IllegalStateException" not in output
4292 except AssertionError:
4293 main.log.error( "Error in processing '" + cmdStr + "' " +
4294 "command: " + str( output ) )
4295 return None
4296 newPattern = 'Created Key (?P<key>(\w)+) with value (?P<value>(.)+)\.'
4297 updatedPattern = "Put (?P<value>(.)+) into key (?P<key>(\w)+)\. The old value was (?P<oldValue>(.)+)\."
4298 results = {}
4299 for line in output.splitlines():
4300 new = re.search( newPattern, line )
4301 updated = re.search( updatedPattern, line )
4302 if new:
4303 results[ new.groupdict()[ 'key' ] ] = { 'value': new.groupdict()[ 'value' ] }
4304 elif updated:
4305 results[ updated.groupdict()[ 'key' ] ] = { 'value': updated.groupdict()[ 'value' ],
Jon Hallc6793552016-01-19 14:18:37 -08004306 'oldValue': updated.groupdict()[ 'oldValue' ] }
Jon Hall2a5002c2015-08-21 16:49:11 -07004307 else:
4308 main.log.error( self.name + ": transactionlMapGet did not" +
4309 " match expected output." )
Jon Hallc6793552016-01-19 14:18:37 -08004310 main.log.debug( "{} expected: {!r} or {!r}".format( self.name,
4311 newPattern,
4312 updatedPattern ) )
Jon Hall2a5002c2015-08-21 16:49:11 -07004313 main.log.debug( self.name + " actual: " + repr( output ) )
4314 return results
Jon Hallc6793552016-01-19 14:18:37 -08004315 except AssertionError:
4316 main.log.exception( "" )
4317 return None
Jon Hall2a5002c2015-08-21 16:49:11 -07004318 except TypeError:
4319 main.log.exception( self.name + ": Object not as expected" )
4320 return None
4321 except pexpect.EOF:
4322 main.log.error( self.name + ": EOF exception found" )
4323 main.log.error( self.name + ": " + self.handle.before )
4324 main.cleanup()
4325 main.exit()
4326 except Exception:
4327 main.log.exception( self.name + ": Uncaught exception!" )
4328 main.cleanup()
4329 main.exit()
Jon Hallc6793552016-01-19 14:18:37 -08004330
acsmarsdaea66c2015-09-03 11:44:06 -07004331 def maps( self, jsonFormat=True ):
4332 """
4333 Description: Returns result of onos:maps
4334 Optional:
4335 * jsonFormat: enable json formatting of output
4336 """
4337 try:
4338 cmdStr = "maps"
4339 if jsonFormat:
4340 cmdStr += " -j"
4341 handle = self.sendline( cmdStr )
Jon Hallc6793552016-01-19 14:18:37 -08004342 assert "Command not found:" not in handle, handle
acsmarsdaea66c2015-09-03 11:44:06 -07004343 return handle
Jon Hallc6793552016-01-19 14:18:37 -08004344 except AssertionError:
4345 main.log.exception( "" )
4346 return None
acsmarsdaea66c2015-09-03 11:44:06 -07004347 except TypeError:
4348 main.log.exception( self.name + ": Object not as expected" )
4349 return None
4350 except pexpect.EOF:
4351 main.log.error( self.name + ": EOF exception found" )
4352 main.log.error( self.name + ": " + self.handle.before )
4353 main.cleanup()
4354 main.exit()
4355 except Exception:
4356 main.log.exception( self.name + ": Uncaught exception!" )
4357 main.cleanup()
4358 main.exit()
GlennRC050596c2015-11-18 17:06:41 -08004359
4360 def getSwController( self, uri, jsonFormat=True ):
4361 """
4362 Descrition: Gets the controller information from the device
4363 """
4364 try:
4365 cmd = "device-controllers "
4366 if jsonFormat:
4367 cmd += "-j "
4368 response = self.sendline( cmd + uri )
Jon Hallc6793552016-01-19 14:18:37 -08004369 assert "Command not found:" not in response, response
GlennRC050596c2015-11-18 17:06:41 -08004370 return response
Jon Hallc6793552016-01-19 14:18:37 -08004371 except AssertionError:
4372 main.log.exception( "" )
4373 return None
GlennRC050596c2015-11-18 17:06:41 -08004374 except TypeError:
4375 main.log.exception( self.name + ": Object not as expected" )
4376 return None
4377 except pexpect.EOF:
4378 main.log.error( self.name + ": EOF exception found" )
4379 main.log.error( self.name + ": " + self.handle.before )
4380 main.cleanup()
4381 main.exit()
4382 except Exception:
4383 main.log.exception( self.name + ": Uncaught exception!" )
4384 main.cleanup()
4385 main.exit()
4386
4387 def setSwController( self, uri, ip, proto="tcp", port="6653", jsonFormat=True ):
4388 """
4389 Descrition: sets the controller(s) for the specified device
4390
4391 Parameters:
4392 Required: uri - String: The uri of the device(switch).
4393 ip - String or List: The ip address of the controller.
4394 This parameter can be formed in a couple of different ways.
4395 VALID:
4396 10.0.0.1 - just the ip address
4397 tcp:10.0.0.1 - the protocol and the ip address
4398 tcp:10.0.0.1:6653 - the protocol and port can be specified,
4399 so that you can add controllers with different
4400 protocols and ports
4401 INVALID:
4402 10.0.0.1:6653 - this is not supported by ONOS
4403
4404 Optional: proto - The type of connection e.g. tcp, ssl. If a list of ips are given
4405 port - The port number.
4406 jsonFormat - If set ONOS will output in json NOTE: This is currently not supported
4407
4408 Returns: main.TRUE if ONOS returns without any errors, otherwise returns main.FALSE
4409 """
4410 try:
4411 cmd = "device-setcontrollers"
4412
4413 if jsonFormat:
4414 cmd += " -j"
4415 cmd += " " + uri
4416 if isinstance( ip, str ):
4417 ip = [ip]
4418 for item in ip:
4419 if ":" in item:
4420 sitem = item.split( ":" )
4421 if len(sitem) == 3:
4422 cmd += " " + item
4423 elif "." in sitem[1]:
4424 cmd += " {}:{}".format(item, port)
4425 else:
4426 main.log.error( "Malformed entry: " + item )
4427 raise TypeError
4428 else:
4429 cmd += " {}:{}:{}".format( proto, item, port )
GlennRC050596c2015-11-18 17:06:41 -08004430 response = self.sendline( cmd )
Jon Hallc6793552016-01-19 14:18:37 -08004431 assert "Command not found:" not in response, response
GlennRC050596c2015-11-18 17:06:41 -08004432 if "Error" in response:
4433 main.log.error( response )
4434 return main.FALSE
GlennRC050596c2015-11-18 17:06:41 -08004435 return main.TRUE
Jon Hallc6793552016-01-19 14:18:37 -08004436 except AssertionError:
4437 main.log.exception( "" )
4438 return None
GlennRC050596c2015-11-18 17:06:41 -08004439 except TypeError:
4440 main.log.exception( self.name + ": Object not as expected" )
4441 return main.FALSE
4442 except pexpect.EOF:
4443 main.log.error( self.name + ": EOF exception found" )
4444 main.log.error( self.name + ": " + self.handle.before )
4445 main.cleanup()
4446 main.exit()
4447 except Exception:
4448 main.log.exception( self.name + ": Uncaught exception!" )
4449 main.cleanup()
4450 main.exit()
GlennRC20fc6522015-12-23 23:26:57 -08004451
4452 def removeDevice( self, device ):
4453 '''
4454 Description:
4455 Remove a device from ONOS by passing the uri of the device(s).
4456 Parameters:
4457 device - (str or list) the id or uri of the device ex. "of:0000000000000001"
4458 Returns:
4459 Returns main.FALSE if an exception is thrown or an error is present
4460 in the response. Otherwise, returns main.TRUE.
4461 NOTE:
4462 If a host cannot be removed, then this function will return main.FALSE
4463 '''
4464 try:
4465 if type( device ) is str:
4466 device = list( device )
4467
4468 for d in device:
4469 time.sleep( 1 )
4470 response = self.sendline( "device-remove {}".format( d ) )
Jon Hallc6793552016-01-19 14:18:37 -08004471 assert "Command not found:" not in response, response
GlennRC20fc6522015-12-23 23:26:57 -08004472 if "Error" in response:
4473 main.log.warn( "Error for device: {}\nResponse: {}".format( d, response ) )
4474 return main.FALSE
GlennRC20fc6522015-12-23 23:26:57 -08004475 return main.TRUE
Jon Hallc6793552016-01-19 14:18:37 -08004476 except AssertionError:
4477 main.log.exception( "" )
4478 return main.FALSE
GlennRC20fc6522015-12-23 23:26:57 -08004479 except TypeError:
4480 main.log.exception( self.name + ": Object not as expected" )
4481 return main.FALSE
4482 except pexpect.EOF:
4483 main.log.error( self.name + ": EOF exception found" )
4484 main.log.error( self.name + ": " + self.handle.before )
4485 main.cleanup()
4486 main.exit()
4487 except Exception:
4488 main.log.exception( self.name + ": Uncaught exception!" )
4489 main.cleanup()
4490 main.exit()
4491
4492 def removeHost( self, host ):
4493 '''
4494 Description:
4495 Remove a host from ONOS by passing the id of the host(s)
4496 Parameters:
4497 hostId - (str or list) the id or mac of the host ex. "00:00:00:00:00:01"
4498 Returns:
4499 Returns main.FALSE if an exception is thrown or an error is present
4500 in the response. Otherwise, returns main.TRUE.
4501 NOTE:
4502 If a host cannot be removed, then this function will return main.FALSE
4503 '''
4504 try:
4505 if type( host ) is str:
4506 host = list( host )
4507
4508 for h in host:
4509 time.sleep( 1 )
4510 response = self.sendline( "host-remove {}".format( h ) )
Jon Hallc6793552016-01-19 14:18:37 -08004511 assert "Command not found:" not in response, response
GlennRC20fc6522015-12-23 23:26:57 -08004512 if "Error" in response:
4513 main.log.warn( "Error for host: {}\nResponse: {}".format( h, response ) )
4514 return main.FALSE
GlennRC20fc6522015-12-23 23:26:57 -08004515 return main.TRUE
Jon Hallc6793552016-01-19 14:18:37 -08004516 except AssertionError:
4517 main.log.exception( "" )
4518 return None
GlennRC20fc6522015-12-23 23:26:57 -08004519 except TypeError:
4520 main.log.exception( self.name + ": Object not as expected" )
4521 return main.FALSE
4522 except pexpect.EOF:
4523 main.log.error( self.name + ": EOF exception found" )
4524 main.log.error( self.name + ": " + self.handle.before )
4525 main.cleanup()
4526 main.exit()
4527 except Exception:
4528 main.log.exception( self.name + ": Uncaught exception!" )
4529 main.cleanup()
4530 main.exit()
GlennRCed771242016-01-13 17:02:47 -08004531
Jon Hallc6793552016-01-19 14:18:37 -08004532 def link( self, begin, end, state ):
GlennRCed771242016-01-13 17:02:47 -08004533 '''
4534 Description:
4535 Bring link down or up in the null-provider.
4536 params:
4537 begin - (string) One end of a device or switch.
4538 end - (string) the other end of the device or switch
4539 returns:
4540 main.TRUE if no exceptions were thrown and no Errors are
4541 present in the resoponse. Otherwise, returns main.FALSE
4542 '''
4543 try:
Jon Hallc6793552016-01-19 14:18:37 -08004544 cmd = "null-link null:{} null:{} {}".format( begin, end, state )
GlennRCed771242016-01-13 17:02:47 -08004545 response = self.sendline( cmd, showResponse=True )
Jon Hallc6793552016-01-19 14:18:37 -08004546 assert "Command not found:" not in response, response
GlennRCed771242016-01-13 17:02:47 -08004547 if "Error" in response or "Failure" in response:
4548 main.log.error( response )
4549 return main.FALSE
GlennRCed771242016-01-13 17:02:47 -08004550 return main.TRUE
Jon Hallc6793552016-01-19 14:18:37 -08004551 except AssertionError:
4552 main.log.exception( "" )
4553 return None
GlennRCed771242016-01-13 17:02:47 -08004554 except TypeError:
4555 main.log.exception( self.name + ": Object not as expected" )
4556 return main.FALSE
4557 except pexpect.EOF:
4558 main.log.error( self.name + ": EOF exception found" )
4559 main.log.error( self.name + ": " + self.handle.before )
4560 main.cleanup()
4561 main.exit()
4562 except Exception:
4563 main.log.exception( self.name + ": Uncaught exception!" )
4564 main.cleanup()
4565 main.exit()
4566