blob: 93026c2a65e85a007763efecd3901f3e6ff834c1 [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 Hallc6358dd2015-04-10 12:44:28 -0700938 return handle
Jon Hallc6793552016-01-19 14:18:37 -0800939 except AssertionError:
Jeremyd9e4eb12016-04-13 12:09:06 -0700940 main.log.exception( "Error in processing '" + cmdStr + "' " +
Jeremy Songster6949cea2016-04-19 18:13:18 -0700941 "command: " + str( handle ) )
Jon Hallc6793552016-01-19 14:18:37 -0800942 return None
Jon Halld4d4b372015-01-28 16:02:41 -0800943 except TypeError:
944 main.log.exception( self.name + ": Object not as expected" )
945 return None
Jon Hall42db6dc2014-10-24 19:03:48 -0400946 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -0800947 main.log.error( self.name + ": EOF exception found" )
948 main.log.error( self.name + ": " + self.handle.before )
Jon Hall42db6dc2014-10-24 19:03:48 -0400949 main.cleanup()
950 main.exit()
Jon Hallfebb1c72015-03-05 13:30:09 -0800951 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -0800952 main.log.exception( self.name + ": Uncaught exception!" )
Jon Hall42db6dc2014-10-24 19:03:48 -0400953 main.cleanup()
954 main.exit()
955
kelvin-onlabd3b64892015-01-20 13:26:24 -0800956 def getHost( self, mac ):
kelvin8ec71442015-01-15 16:57:00 -0800957 """
Jon Hall42db6dc2014-10-24 19:03:48 -0400958 Return the first host from the hosts api whose 'id' contains 'mac'
Jon Halle3f39ff2015-01-13 11:50:53 -0800959
Jon Hallefbd9792015-03-05 16:11:36 -0800960 Note: mac must be a colon separated mac address, but could be a
Jon Halle3f39ff2015-01-13 11:50:53 -0800961 partial mac address
962
Jon Hall42db6dc2014-10-24 19:03:48 -0400963 Return None if there is no match
kelvin8ec71442015-01-15 16:57:00 -0800964 """
Jon Hall42db6dc2014-10-24 19:03:48 -0400965 try:
kelvin8ec71442015-01-15 16:57:00 -0800966 if mac is None:
Jon Hall42db6dc2014-10-24 19:03:48 -0400967 return None
968 else:
969 mac = mac
kelvin-onlabd3b64892015-01-20 13:26:24 -0800970 rawHosts = self.hosts()
971 hostsJson = json.loads( rawHosts )
kelvin8ec71442015-01-15 16:57:00 -0800972 # search json for the host with mac then return the device
kelvin-onlabd3b64892015-01-20 13:26:24 -0800973 for host in hostsJson:
kelvin8ec71442015-01-15 16:57:00 -0800974 # print "%s in %s?" % ( mac, host[ 'id' ] )
Jon Halld4d4b372015-01-28 16:02:41 -0800975 if not host:
976 pass
977 elif mac in host[ 'id' ]:
Jon Hall42db6dc2014-10-24 19:03:48 -0400978 return host
979 return None
Jon Hallc6793552016-01-19 14:18:37 -0800980 except ( TypeError, ValueError ):
981 main.log.exception( "{}: Object not as expected: {!r}".format( self.name, rawHosts ) )
Jon Halld4d4b372015-01-28 16:02:41 -0800982 return None
Jon Hall42db6dc2014-10-24 19:03:48 -0400983 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -0800984 main.log.error( self.name + ": EOF exception found" )
985 main.log.error( self.name + ": " + self.handle.before )
Jon Hall42db6dc2014-10-24 19:03:48 -0400986 main.cleanup()
987 main.exit()
Jon Hallfebb1c72015-03-05 13:30:09 -0800988 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -0800989 main.log.exception( self.name + ": Uncaught exception!" )
Jon Hall42db6dc2014-10-24 19:03:48 -0400990 main.cleanup()
991 main.exit()
992
kelvin-onlabd3b64892015-01-20 13:26:24 -0800993 def getHostsId( self, hostList ):
kelvin8ec71442015-01-15 16:57:00 -0800994 """
995 Obtain list of hosts
andrewonlab3f0a4af2014-10-17 12:25:14 -0400996 Issues command: 'onos> hosts'
kelvin8ec71442015-01-15 16:57:00 -0800997
andrewonlab3f0a4af2014-10-17 12:25:14 -0400998 Required:
kelvin-onlabd3b64892015-01-20 13:26:24 -0800999 * hostList: List of hosts obtained by Mininet
andrewonlab3f0a4af2014-10-17 12:25:14 -04001000 IMPORTANT:
1001 This function assumes that you started your
kelvin8ec71442015-01-15 16:57:00 -08001002 topology with the option '--mac'.
andrewonlab3f0a4af2014-10-17 12:25:14 -04001003 Furthermore, it assumes that value of VLAN is '-1'
1004 Description:
kelvin8ec71442015-01-15 16:57:00 -08001005 Converts mininet hosts ( h1, h2, h3... ) into
1006 ONOS format ( 00:00:00:00:00:01/-1 , ... )
1007 """
andrewonlab3f0a4af2014-10-17 12:25:14 -04001008 try:
kelvin-onlabd3b64892015-01-20 13:26:24 -08001009 onosHostList = []
andrewonlab3f0a4af2014-10-17 12:25:14 -04001010
kelvin-onlabd3b64892015-01-20 13:26:24 -08001011 for host in hostList:
kelvin8ec71442015-01-15 16:57:00 -08001012 host = host.replace( "h", "" )
kelvin-onlabd3b64892015-01-20 13:26:24 -08001013 hostHex = hex( int( host ) ).zfill( 12 )
1014 hostHex = str( hostHex ).replace( 'x', '0' )
1015 i = iter( str( hostHex ) )
1016 hostHex = ":".join( a + b for a, b in zip( i, i ) )
1017 hostHex = hostHex + "/-1"
1018 onosHostList.append( hostHex )
andrewonlab3f0a4af2014-10-17 12:25:14 -04001019
kelvin-onlabd3b64892015-01-20 13:26:24 -08001020 return onosHostList
andrewonlab3f0a4af2014-10-17 12:25:14 -04001021
Jon Halld4d4b372015-01-28 16:02:41 -08001022 except TypeError:
1023 main.log.exception( self.name + ": Object not as expected" )
1024 return None
andrewonlab3f0a4af2014-10-17 12:25:14 -04001025 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08001026 main.log.error( self.name + ": EOF exception found" )
1027 main.log.error( self.name + ": " + self.handle.before )
andrewonlab3f0a4af2014-10-17 12:25:14 -04001028 main.cleanup()
1029 main.exit()
Jon Hallfebb1c72015-03-05 13:30:09 -08001030 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -08001031 main.log.exception( self.name + ": Uncaught exception!" )
andrewonlab3f0a4af2014-10-17 12:25:14 -04001032 main.cleanup()
1033 main.exit()
andrewonlab3e15ead2014-10-15 14:21:34 -04001034
kelvin-onlabd3b64892015-01-20 13:26:24 -08001035 def addHostIntent( self, hostIdOne, hostIdTwo ):
kelvin8ec71442015-01-15 16:57:00 -08001036 """
andrewonlabe6745342014-10-17 14:29:13 -04001037 Required:
kelvin-onlabd3b64892015-01-20 13:26:24 -08001038 * hostIdOne: ONOS host id for host1
1039 * hostIdTwo: ONOS host id for host2
andrewonlabe6745342014-10-17 14:29:13 -04001040 Description:
Jon Hallefbd9792015-03-05 16:11:36 -08001041 Adds a host-to-host intent ( bidirectional ) by
Jon Hallb1290e82014-11-18 16:17:48 -05001042 specifying the two hosts.
kelvin-onlabfb521662015-02-27 09:52:40 -08001043 Returns:
1044 A string of the intent id or None on Error
kelvin8ec71442015-01-15 16:57:00 -08001045 """
andrewonlabe6745342014-10-17 14:29:13 -04001046 try:
kelvin-onlabd3b64892015-01-20 13:26:24 -08001047 cmdStr = "add-host-intent " + str( hostIdOne ) +\
1048 " " + str( hostIdTwo )
1049 handle = self.sendline( cmdStr )
Jon Hallc6793552016-01-19 14:18:37 -08001050 assert "Command not found:" not in handle, handle
Hari Krishnaac4e1782015-01-26 12:09:12 -08001051 if re.search( "Error", handle ):
1052 main.log.error( "Error in adding Host intent" )
Jon Hall61282e32015-03-19 11:34:11 -07001053 main.log.debug( "Response from ONOS was: " + repr( handle ) )
kelvin-onlabfb521662015-02-27 09:52:40 -08001054 return None
Hari Krishnaac4e1782015-01-26 12:09:12 -08001055 else:
1056 main.log.info( "Host intent installed between " +
kelvin-onlabfb521662015-02-27 09:52:40 -08001057 str( hostIdOne ) + " and " + str( hostIdTwo ) )
1058 match = re.search('id=0x([\da-f]+),', handle)
1059 if match:
1060 return match.group()[3:-1]
1061 else:
1062 main.log.error( "Error, intent ID not found" )
Jon Hall61282e32015-03-19 11:34:11 -07001063 main.log.debug( "Response from ONOS was: " +
1064 repr( handle ) )
kelvin-onlabfb521662015-02-27 09:52:40 -08001065 return None
Jon Hallc6793552016-01-19 14:18:37 -08001066 except AssertionError:
1067 main.log.exception( "" )
1068 return None
Jon Halld4d4b372015-01-28 16:02:41 -08001069 except TypeError:
1070 main.log.exception( self.name + ": Object not as expected" )
1071 return None
andrewonlabe6745342014-10-17 14:29:13 -04001072 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08001073 main.log.error( self.name + ": EOF exception found" )
1074 main.log.error( self.name + ": " + self.handle.before )
andrewonlabe6745342014-10-17 14:29:13 -04001075 main.cleanup()
1076 main.exit()
Jon Hallfebb1c72015-03-05 13:30:09 -08001077 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -08001078 main.log.exception( self.name + ": Uncaught exception!" )
andrewonlabe6745342014-10-17 14:29:13 -04001079 main.cleanup()
1080 main.exit()
1081
kelvin-onlabd3b64892015-01-20 13:26:24 -08001082 def addOpticalIntent( self, ingressDevice, egressDevice ):
kelvin8ec71442015-01-15 16:57:00 -08001083 """
andrewonlab7b31d232014-10-24 13:31:47 -04001084 Required:
kelvin-onlabd3b64892015-01-20 13:26:24 -08001085 * ingressDevice: device id of ingress device
1086 * egressDevice: device id of egress device
andrewonlab7b31d232014-10-24 13:31:47 -04001087 Optional:
1088 TODO: Still needs to be implemented via dev side
kelvin-onlabfb521662015-02-27 09:52:40 -08001089 Description:
1090 Adds an optical intent by specifying an ingress and egress device
1091 Returns:
1092 A string of the intent id or None on error
kelvin-onlab898a6c62015-01-16 14:13:53 -08001093 """
andrewonlab7b31d232014-10-24 13:31:47 -04001094 try:
kelvin-onlabd3b64892015-01-20 13:26:24 -08001095 cmdStr = "add-optical-intent " + str( ingressDevice ) +\
1096 " " + str( egressDevice )
1097 handle = self.sendline( cmdStr )
Jon Hallc6793552016-01-19 14:18:37 -08001098 assert "Command not found:" not in handle, handle
kelvin-onlab898a6c62015-01-16 14:13:53 -08001099 # If error, return error message
Jon Halle3f39ff2015-01-13 11:50:53 -08001100 if re.search( "Error", handle ):
kelvin-onlabfb521662015-02-27 09:52:40 -08001101 main.log.error( "Error in adding Optical intent" )
1102 return None
andrewonlab7b31d232014-10-24 13:31:47 -04001103 else:
kelvin-onlabfb521662015-02-27 09:52:40 -08001104 main.log.info( "Optical intent installed between " +
1105 str( ingressDevice ) + " and " +
1106 str( egressDevice ) )
1107 match = re.search('id=0x([\da-f]+),', handle)
1108 if match:
1109 return match.group()[3:-1]
1110 else:
1111 main.log.error( "Error, intent ID not found" )
1112 return None
Jon Hallc6793552016-01-19 14:18:37 -08001113 except AssertionError:
1114 main.log.exception( "" )
1115 return None
Jon Halld4d4b372015-01-28 16:02:41 -08001116 except TypeError:
1117 main.log.exception( self.name + ": Object not as expected" )
1118 return None
andrewonlab7b31d232014-10-24 13:31:47 -04001119 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08001120 main.log.error( self.name + ": EOF exception found" )
1121 main.log.error( self.name + ": " + self.handle.before )
andrewonlab7b31d232014-10-24 13:31:47 -04001122 main.cleanup()
1123 main.exit()
Jon Hallfebb1c72015-03-05 13:30:09 -08001124 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -08001125 main.log.exception( self.name + ": Uncaught exception!" )
andrewonlab7b31d232014-10-24 13:31:47 -04001126 main.cleanup()
1127 main.exit()
1128
kelvin-onlabd3b64892015-01-20 13:26:24 -08001129 def addPointIntent(
kelvin-onlab898a6c62015-01-16 14:13:53 -08001130 self,
kelvin-onlabd3b64892015-01-20 13:26:24 -08001131 ingressDevice,
1132 egressDevice,
1133 portIngress="",
1134 portEgress="",
kelvin-onlab898a6c62015-01-16 14:13:53 -08001135 ethType="",
1136 ethSrc="",
1137 ethDst="",
1138 bandwidth="",
kelvin-onlabd3b64892015-01-20 13:26:24 -08001139 lambdaAlloc=False,
kelvin-onlab898a6c62015-01-16 14:13:53 -08001140 ipProto="",
1141 ipSrc="",
1142 ipDst="",
1143 tcpSrc="",
1144 tcpDst="" ):
kelvin8ec71442015-01-15 16:57:00 -08001145 """
andrewonlab4dbb4d82014-10-17 18:22:31 -04001146 Required:
kelvin-onlabd3b64892015-01-20 13:26:24 -08001147 * ingressDevice: device id of ingress device
1148 * egressDevice: device id of egress device
andrewonlab289e4b72014-10-21 21:24:18 -04001149 Optional:
1150 * ethType: specify ethType
kelvin8ec71442015-01-15 16:57:00 -08001151 * ethSrc: specify ethSrc ( i.e. src mac addr )
1152 * ethDst: specify ethDst ( i.e. dst mac addr )
andrewonlab0dbb6ec2014-11-06 13:46:55 -05001153 * bandwidth: specify bandwidth capacity of link
kelvin-onlabd3b64892015-01-20 13:26:24 -08001154 * lambdaAlloc: if True, intent will allocate lambda
andrewonlab40ccd8b2014-11-06 16:23:34 -05001155 for the specified intent
Jon Halle3f39ff2015-01-13 11:50:53 -08001156 * ipProto: specify ip protocol
andrewonlabf77e0cb2014-11-11 17:17:59 -05001157 * ipSrc: specify ip source address
1158 * ipDst: specify ip destination address
1159 * tcpSrc: specify tcp source port
1160 * tcpDst: specify tcp destination port
andrewonlab4dbb4d82014-10-17 18:22:31 -04001161 Description:
kelvin8ec71442015-01-15 16:57:00 -08001162 Adds a point-to-point intent ( uni-directional ) by
andrewonlab289e4b72014-10-21 21:24:18 -04001163 specifying device id's and optional fields
kelvin-onlabfb521662015-02-27 09:52:40 -08001164 Returns:
1165 A string of the intent id or None on error
andrewonlab289e4b72014-10-21 21:24:18 -04001166
Jon Halle3f39ff2015-01-13 11:50:53 -08001167 NOTE: This function may change depending on the
andrewonlab4dbb4d82014-10-17 18:22:31 -04001168 options developers provide for point-to-point
1169 intent via cli
kelvin8ec71442015-01-15 16:57:00 -08001170 """
andrewonlab4dbb4d82014-10-17 18:22:31 -04001171 try:
kelvin8ec71442015-01-15 16:57:00 -08001172 # If there are no optional arguments
andrewonlab0dbb6ec2014-11-06 13:46:55 -05001173 if not ethType and not ethSrc and not ethDst\
kelvin-onlabd3b64892015-01-20 13:26:24 -08001174 and not bandwidth and not lambdaAlloc \
andrewonlabfa4ff502014-11-11 16:41:30 -05001175 and not ipProto and not ipSrc and not ipDst \
1176 and not tcpSrc and not tcpDst:
andrewonlab36af3822014-11-18 17:48:18 -05001177 cmd = "add-point-intent"
andrewonlab36af3822014-11-18 17:48:18 -05001178
andrewonlab289e4b72014-10-21 21:24:18 -04001179 else:
andrewonlab36af3822014-11-18 17:48:18 -05001180 cmd = "add-point-intent"
Jon Halle3f39ff2015-01-13 11:50:53 -08001181
andrewonlab0c0a6772014-10-22 12:31:18 -04001182 if ethType:
kelvin8ec71442015-01-15 16:57:00 -08001183 cmd += " --ethType " + str( ethType )
andrewonlab289e4b72014-10-21 21:24:18 -04001184 if ethSrc:
kelvin8ec71442015-01-15 16:57:00 -08001185 cmd += " --ethSrc " + str( ethSrc )
1186 if ethDst:
1187 cmd += " --ethDst " + str( ethDst )
andrewonlab0dbb6ec2014-11-06 13:46:55 -05001188 if bandwidth:
kelvin8ec71442015-01-15 16:57:00 -08001189 cmd += " --bandwidth " + str( bandwidth )
kelvin-onlabd3b64892015-01-20 13:26:24 -08001190 if lambdaAlloc:
andrewonlabfa4ff502014-11-11 16:41:30 -05001191 cmd += " --lambda "
1192 if ipProto:
kelvin8ec71442015-01-15 16:57:00 -08001193 cmd += " --ipProto " + str( ipProto )
andrewonlabfa4ff502014-11-11 16:41:30 -05001194 if ipSrc:
kelvin8ec71442015-01-15 16:57:00 -08001195 cmd += " --ipSrc " + str( ipSrc )
andrewonlabfa4ff502014-11-11 16:41:30 -05001196 if ipDst:
kelvin8ec71442015-01-15 16:57:00 -08001197 cmd += " --ipDst " + str( ipDst )
andrewonlabfa4ff502014-11-11 16:41:30 -05001198 if tcpSrc:
kelvin8ec71442015-01-15 16:57:00 -08001199 cmd += " --tcpSrc " + str( tcpSrc )
andrewonlabfa4ff502014-11-11 16:41:30 -05001200 if tcpDst:
kelvin8ec71442015-01-15 16:57:00 -08001201 cmd += " --tcpDst " + str( tcpDst )
andrewonlab289e4b72014-10-21 21:24:18 -04001202
kelvin8ec71442015-01-15 16:57:00 -08001203 # Check whether the user appended the port
1204 # or provided it as an input
kelvin-onlabd3b64892015-01-20 13:26:24 -08001205 if "/" in ingressDevice:
1206 cmd += " " + str( ingressDevice )
andrewonlab36af3822014-11-18 17:48:18 -05001207 else:
kelvin-onlabd3b64892015-01-20 13:26:24 -08001208 if not portIngress:
kelvin-onlabfb521662015-02-27 09:52:40 -08001209 main.log.error( "You must specify the ingress port" )
kelvin8ec71442015-01-15 16:57:00 -08001210 # TODO: perhaps more meaningful return
kelvin-onlabfb521662015-02-27 09:52:40 -08001211 # Would it make sense to throw an exception and exit
1212 # the test?
1213 return None
andrewonlab36af3822014-11-18 17:48:18 -05001214
kelvin8ec71442015-01-15 16:57:00 -08001215 cmd += " " + \
kelvin-onlabd3b64892015-01-20 13:26:24 -08001216 str( ingressDevice ) + "/" +\
1217 str( portIngress ) + " "
andrewonlab36af3822014-11-18 17:48:18 -05001218
kelvin-onlabd3b64892015-01-20 13:26:24 -08001219 if "/" in egressDevice:
1220 cmd += " " + str( egressDevice )
andrewonlab36af3822014-11-18 17:48:18 -05001221 else:
kelvin-onlabd3b64892015-01-20 13:26:24 -08001222 if not portEgress:
kelvin-onlabfb521662015-02-27 09:52:40 -08001223 main.log.error( "You must specify the egress port" )
1224 return None
Jon Halle3f39ff2015-01-13 11:50:53 -08001225
kelvin8ec71442015-01-15 16:57:00 -08001226 cmd += " " +\
kelvin-onlabd3b64892015-01-20 13:26:24 -08001227 str( egressDevice ) + "/" +\
1228 str( portEgress )
kelvin8ec71442015-01-15 16:57:00 -08001229
kelvin-onlab898a6c62015-01-16 14:13:53 -08001230 handle = self.sendline( cmd )
Jon Hallc6793552016-01-19 14:18:37 -08001231 assert "Command not found:" not in handle, handle
kelvin-onlabfb521662015-02-27 09:52:40 -08001232 # If error, return error message
kelvin-onlab898a6c62015-01-16 14:13:53 -08001233 if re.search( "Error", handle ):
kelvin8ec71442015-01-15 16:57:00 -08001234 main.log.error( "Error in adding point-to-point intent" )
kelvin-onlabfb521662015-02-27 09:52:40 -08001235 return None
andrewonlab4dbb4d82014-10-17 18:22:31 -04001236 else:
kelvin-onlabfb521662015-02-27 09:52:40 -08001237 # TODO: print out all the options in this message?
1238 main.log.info( "Point-to-point intent installed between " +
1239 str( ingressDevice ) + " and " +
1240 str( egressDevice ) )
1241 match = re.search('id=0x([\da-f]+),', handle)
1242 if match:
1243 return match.group()[3:-1]
1244 else:
1245 main.log.error( "Error, intent ID not found" )
1246 return None
Jon Hallc6793552016-01-19 14:18:37 -08001247 except AssertionError:
1248 main.log.exception( "" )
1249 return None
Jon Halld4d4b372015-01-28 16:02:41 -08001250 except TypeError:
1251 main.log.exception( self.name + ": Object not as expected" )
1252 return None
andrewonlab4dbb4d82014-10-17 18:22:31 -04001253 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08001254 main.log.error( self.name + ": EOF exception found" )
1255 main.log.error( self.name + ": " + self.handle.before )
andrewonlab4dbb4d82014-10-17 18:22:31 -04001256 main.cleanup()
1257 main.exit()
Jon Hallfebb1c72015-03-05 13:30:09 -08001258 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -08001259 main.log.exception( self.name + ": Uncaught exception!" )
andrewonlab4dbb4d82014-10-17 18:22:31 -04001260 main.cleanup()
1261 main.exit()
1262
kelvin-onlabd3b64892015-01-20 13:26:24 -08001263 def addMultipointToSinglepointIntent(
kelvin-onlab898a6c62015-01-16 14:13:53 -08001264 self,
shahshreyac2f97072015-03-19 17:04:29 -07001265 ingressDeviceList,
kelvin-onlabd3b64892015-01-20 13:26:24 -08001266 egressDevice,
shahshreyac2f97072015-03-19 17:04:29 -07001267 portIngressList=None,
kelvin-onlabd3b64892015-01-20 13:26:24 -08001268 portEgress="",
kelvin-onlab898a6c62015-01-16 14:13:53 -08001269 ethType="",
1270 ethSrc="",
1271 ethDst="",
1272 bandwidth="",
kelvin-onlabd3b64892015-01-20 13:26:24 -08001273 lambdaAlloc=False,
kelvin-onlab898a6c62015-01-16 14:13:53 -08001274 ipProto="",
1275 ipSrc="",
1276 ipDst="",
1277 tcpSrc="",
1278 tcpDst="",
1279 setEthSrc="",
1280 setEthDst="" ):
kelvin8ec71442015-01-15 16:57:00 -08001281 """
shahshreyad0c80432014-12-04 16:56:05 -08001282 Note:
shahshreya70622b12015-03-19 17:19:00 -07001283 This function assumes the format of all ingress devices
Jon Hallbe379602015-03-24 13:39:32 -07001284 is same. That is, all ingress devices include port numbers
1285 with a "/" or all ingress devices could specify device
1286 ids and port numbers seperately.
shahshreyad0c80432014-12-04 16:56:05 -08001287 Required:
Jon Hallbe379602015-03-24 13:39:32 -07001288 * ingressDeviceList: List of device ids of ingress device
shahshreyac2f97072015-03-19 17:04:29 -07001289 ( Atleast 2 ingress devices required in the list )
kelvin-onlabd3b64892015-01-20 13:26:24 -08001290 * egressDevice: device id of egress device
shahshreyad0c80432014-12-04 16:56:05 -08001291 Optional:
1292 * ethType: specify ethType
kelvin8ec71442015-01-15 16:57:00 -08001293 * ethSrc: specify ethSrc ( i.e. src mac addr )
1294 * ethDst: specify ethDst ( i.e. dst mac addr )
shahshreyad0c80432014-12-04 16:56:05 -08001295 * bandwidth: specify bandwidth capacity of link
kelvin-onlabd3b64892015-01-20 13:26:24 -08001296 * lambdaAlloc: if True, intent will allocate lambda
shahshreyad0c80432014-12-04 16:56:05 -08001297 for the specified intent
Jon Halle3f39ff2015-01-13 11:50:53 -08001298 * ipProto: specify ip protocol
shahshreyad0c80432014-12-04 16:56:05 -08001299 * ipSrc: specify ip source address
1300 * ipDst: specify ip destination address
1301 * tcpSrc: specify tcp source port
1302 * tcpDst: specify tcp destination port
1303 * setEthSrc: action to Rewrite Source MAC Address
1304 * setEthDst: action to Rewrite Destination MAC Address
1305 Description:
kelvin8ec71442015-01-15 16:57:00 -08001306 Adds a multipoint-to-singlepoint intent ( uni-directional ) by
shahshreyad0c80432014-12-04 16:56:05 -08001307 specifying device id's and optional fields
kelvin-onlabfb521662015-02-27 09:52:40 -08001308 Returns:
1309 A string of the intent id or None on error
shahshreyad0c80432014-12-04 16:56:05 -08001310
Jon Halle3f39ff2015-01-13 11:50:53 -08001311 NOTE: This function may change depending on the
Jon Hallefbd9792015-03-05 16:11:36 -08001312 options developers provide for multipoint-to-singlepoint
shahshreyad0c80432014-12-04 16:56:05 -08001313 intent via cli
kelvin8ec71442015-01-15 16:57:00 -08001314 """
shahshreyad0c80432014-12-04 16:56:05 -08001315 try:
kelvin8ec71442015-01-15 16:57:00 -08001316 # If there are no optional arguments
shahshreyad0c80432014-12-04 16:56:05 -08001317 if not ethType and not ethSrc and not ethDst\
kelvin-onlabd3b64892015-01-20 13:26:24 -08001318 and not bandwidth and not lambdaAlloc\
Jon Halle3f39ff2015-01-13 11:50:53 -08001319 and not ipProto and not ipSrc and not ipDst\
1320 and not tcpSrc and not tcpDst and not setEthSrc\
1321 and not setEthDst:
shahshreyad0c80432014-12-04 16:56:05 -08001322 cmd = "add-multi-to-single-intent"
shahshreyad0c80432014-12-04 16:56:05 -08001323
1324 else:
1325 cmd = "add-multi-to-single-intent"
Jon Halle3f39ff2015-01-13 11:50:53 -08001326
shahshreyad0c80432014-12-04 16:56:05 -08001327 if ethType:
kelvin8ec71442015-01-15 16:57:00 -08001328 cmd += " --ethType " + str( ethType )
shahshreyad0c80432014-12-04 16:56:05 -08001329 if ethSrc:
kelvin8ec71442015-01-15 16:57:00 -08001330 cmd += " --ethSrc " + str( ethSrc )
1331 if ethDst:
1332 cmd += " --ethDst " + str( ethDst )
shahshreyad0c80432014-12-04 16:56:05 -08001333 if bandwidth:
kelvin8ec71442015-01-15 16:57:00 -08001334 cmd += " --bandwidth " + str( bandwidth )
kelvin-onlabd3b64892015-01-20 13:26:24 -08001335 if lambdaAlloc:
shahshreyad0c80432014-12-04 16:56:05 -08001336 cmd += " --lambda "
1337 if ipProto:
kelvin8ec71442015-01-15 16:57:00 -08001338 cmd += " --ipProto " + str( ipProto )
shahshreyad0c80432014-12-04 16:56:05 -08001339 if ipSrc:
kelvin8ec71442015-01-15 16:57:00 -08001340 cmd += " --ipSrc " + str( ipSrc )
shahshreyad0c80432014-12-04 16:56:05 -08001341 if ipDst:
kelvin8ec71442015-01-15 16:57:00 -08001342 cmd += " --ipDst " + str( ipDst )
shahshreyad0c80432014-12-04 16:56:05 -08001343 if tcpSrc:
kelvin8ec71442015-01-15 16:57:00 -08001344 cmd += " --tcpSrc " + str( tcpSrc )
shahshreyad0c80432014-12-04 16:56:05 -08001345 if tcpDst:
kelvin8ec71442015-01-15 16:57:00 -08001346 cmd += " --tcpDst " + str( tcpDst )
shahshreyad0c80432014-12-04 16:56:05 -08001347 if setEthSrc:
kelvin8ec71442015-01-15 16:57:00 -08001348 cmd += " --setEthSrc " + str( setEthSrc )
shahshreyad0c80432014-12-04 16:56:05 -08001349 if setEthDst:
kelvin8ec71442015-01-15 16:57:00 -08001350 cmd += " --setEthDst " + str( setEthDst )
shahshreyad0c80432014-12-04 16:56:05 -08001351
kelvin8ec71442015-01-15 16:57:00 -08001352 # Check whether the user appended the port
1353 # or provided it as an input
shahshreyac2f97072015-03-19 17:04:29 -07001354
1355 if portIngressList is None:
1356 for ingressDevice in ingressDeviceList:
1357 if "/" in ingressDevice:
1358 cmd += " " + str( ingressDevice )
1359 else:
1360 main.log.error( "You must specify " +
Jon Hallbe379602015-03-24 13:39:32 -07001361 "the ingress port" )
shahshreyac2f97072015-03-19 17:04:29 -07001362 # TODO: perhaps more meaningful return
1363 return main.FALSE
shahshreyad0c80432014-12-04 16:56:05 -08001364 else:
Jon Hall71ce4e72015-03-23 14:05:58 -07001365 if len( ingressDeviceList ) == len( portIngressList ):
Jon Hall08f61bc2015-04-13 16:00:30 -07001366 for ingressDevice, portIngress in zip( ingressDeviceList,
1367 portIngressList ):
shahshreya70622b12015-03-19 17:19:00 -07001368 cmd += " " + \
1369 str( ingressDevice ) + "/" +\
1370 str( portIngress ) + " "
kelvin-onlab38143812015-04-01 15:03:01 -07001371 else:
Jon Hall08f61bc2015-04-13 16:00:30 -07001372 main.log.error( "Device list and port list does not " +
1373 "have the same length" )
kelvin-onlab38143812015-04-01 15:03:01 -07001374 return main.FALSE
kelvin-onlabd3b64892015-01-20 13:26:24 -08001375 if "/" in egressDevice:
1376 cmd += " " + str( egressDevice )
shahshreyad0c80432014-12-04 16:56:05 -08001377 else:
kelvin-onlabd3b64892015-01-20 13:26:24 -08001378 if not portEgress:
kelvin8ec71442015-01-15 16:57:00 -08001379 main.log.error( "You must specify " +
1380 "the egress port" )
shahshreyad0c80432014-12-04 16:56:05 -08001381 return main.FALSE
Jon Halle3f39ff2015-01-13 11:50:53 -08001382
kelvin8ec71442015-01-15 16:57:00 -08001383 cmd += " " +\
kelvin-onlabd3b64892015-01-20 13:26:24 -08001384 str( egressDevice ) + "/" +\
1385 str( portEgress )
kelvin-onlab898a6c62015-01-16 14:13:53 -08001386 handle = self.sendline( cmd )
Jon Hallc6793552016-01-19 14:18:37 -08001387 assert "Command not found:" not in handle, handle
kelvin-onlabfb521662015-02-27 09:52:40 -08001388 # If error, return error message
kelvin-onlab898a6c62015-01-16 14:13:53 -08001389 if re.search( "Error", handle ):
kelvin-onlabfb521662015-02-27 09:52:40 -08001390 main.log.error( "Error in adding multipoint-to-singlepoint " +
1391 "intent" )
1392 return None
shahshreyad0c80432014-12-04 16:56:05 -08001393 else:
kelvin-onlabb9408212015-04-01 13:34:04 -07001394 match = re.search('id=0x([\da-f]+),', handle)
1395 if match:
1396 return match.group()[3:-1]
1397 else:
1398 main.log.error( "Error, intent ID not found" )
1399 return None
Jon Hallc6793552016-01-19 14:18:37 -08001400 except AssertionError:
1401 main.log.exception( "" )
1402 return None
kelvin-onlabb9408212015-04-01 13:34:04 -07001403 except TypeError:
1404 main.log.exception( self.name + ": Object not as expected" )
1405 return None
1406 except pexpect.EOF:
1407 main.log.error( self.name + ": EOF exception found" )
1408 main.log.error( self.name + ": " + self.handle.before )
1409 main.cleanup()
1410 main.exit()
1411 except Exception:
1412 main.log.exception( self.name + ": Uncaught exception!" )
1413 main.cleanup()
1414 main.exit()
1415
1416 def addSinglepointToMultipointIntent(
1417 self,
1418 ingressDevice,
1419 egressDeviceList,
1420 portIngress="",
1421 portEgressList=None,
1422 ethType="",
1423 ethSrc="",
1424 ethDst="",
1425 bandwidth="",
1426 lambdaAlloc=False,
1427 ipProto="",
1428 ipSrc="",
1429 ipDst="",
1430 tcpSrc="",
1431 tcpDst="",
1432 setEthSrc="",
1433 setEthDst="" ):
1434 """
1435 Note:
1436 This function assumes the format of all egress devices
1437 is same. That is, all egress devices include port numbers
1438 with a "/" or all egress devices could specify device
1439 ids and port numbers seperately.
1440 Required:
1441 * EgressDeviceList: List of device ids of egress device
1442 ( Atleast 2 eress devices required in the list )
1443 * ingressDevice: device id of ingress device
1444 Optional:
1445 * ethType: specify ethType
1446 * ethSrc: specify ethSrc ( i.e. src mac addr )
1447 * ethDst: specify ethDst ( i.e. dst mac addr )
1448 * bandwidth: specify bandwidth capacity of link
1449 * lambdaAlloc: if True, intent will allocate lambda
1450 for the specified intent
1451 * ipProto: specify ip protocol
1452 * ipSrc: specify ip source address
1453 * ipDst: specify ip destination address
1454 * tcpSrc: specify tcp source port
1455 * tcpDst: specify tcp destination port
1456 * setEthSrc: action to Rewrite Source MAC Address
1457 * setEthDst: action to Rewrite Destination MAC Address
1458 Description:
1459 Adds a singlepoint-to-multipoint intent ( uni-directional ) by
1460 specifying device id's and optional fields
1461 Returns:
1462 A string of the intent id or None on error
1463
1464 NOTE: This function may change depending on the
1465 options developers provide for singlepoint-to-multipoint
1466 intent via cli
1467 """
1468 try:
1469 # If there are no optional arguments
1470 if not ethType and not ethSrc and not ethDst\
1471 and not bandwidth and not lambdaAlloc\
1472 and not ipProto and not ipSrc and not ipDst\
1473 and not tcpSrc and not tcpDst and not setEthSrc\
1474 and not setEthDst:
1475 cmd = "add-single-to-multi-intent"
1476
1477 else:
1478 cmd = "add-single-to-multi-intent"
1479
1480 if ethType:
1481 cmd += " --ethType " + str( ethType )
1482 if ethSrc:
1483 cmd += " --ethSrc " + str( ethSrc )
1484 if ethDst:
1485 cmd += " --ethDst " + str( ethDst )
1486 if bandwidth:
1487 cmd += " --bandwidth " + str( bandwidth )
1488 if lambdaAlloc:
1489 cmd += " --lambda "
1490 if ipProto:
1491 cmd += " --ipProto " + str( ipProto )
1492 if ipSrc:
1493 cmd += " --ipSrc " + str( ipSrc )
1494 if ipDst:
1495 cmd += " --ipDst " + str( ipDst )
1496 if tcpSrc:
1497 cmd += " --tcpSrc " + str( tcpSrc )
1498 if tcpDst:
1499 cmd += " --tcpDst " + str( tcpDst )
1500 if setEthSrc:
1501 cmd += " --setEthSrc " + str( setEthSrc )
1502 if setEthDst:
1503 cmd += " --setEthDst " + str( setEthDst )
1504
1505 # Check whether the user appended the port
1506 # or provided it as an input
Jon Hall08f61bc2015-04-13 16:00:30 -07001507
kelvin-onlabb9408212015-04-01 13:34:04 -07001508 if "/" in ingressDevice:
1509 cmd += " " + str( ingressDevice )
1510 else:
1511 if not portIngress:
1512 main.log.error( "You must specify " +
1513 "the Ingress port" )
1514 return main.FALSE
1515
1516 cmd += " " +\
1517 str( ingressDevice ) + "/" +\
1518 str( portIngress )
1519
1520 if portEgressList is None:
1521 for egressDevice in egressDeviceList:
1522 if "/" in egressDevice:
1523 cmd += " " + str( egressDevice )
1524 else:
1525 main.log.error( "You must specify " +
1526 "the egress port" )
1527 # TODO: perhaps more meaningful return
1528 return main.FALSE
1529 else:
1530 if len( egressDeviceList ) == len( portEgressList ):
Jon Hall08f61bc2015-04-13 16:00:30 -07001531 for egressDevice, portEgress in zip( egressDeviceList,
1532 portEgressList ):
kelvin-onlabb9408212015-04-01 13:34:04 -07001533 cmd += " " + \
1534 str( egressDevice ) + "/" +\
1535 str( portEgress )
kelvin-onlab38143812015-04-01 15:03:01 -07001536 else:
Jon Hall08f61bc2015-04-13 16:00:30 -07001537 main.log.error( "Device list and port list does not " +
1538 "have the same length" )
kelvin-onlab38143812015-04-01 15:03:01 -07001539 return main.FALSE
kelvin-onlabb9408212015-04-01 13:34:04 -07001540 handle = self.sendline( cmd )
Jon Hallc6793552016-01-19 14:18:37 -08001541 assert "Command not found:" not in handle, handle
kelvin-onlabb9408212015-04-01 13:34:04 -07001542 # If error, return error message
1543 if re.search( "Error", handle ):
1544 main.log.error( "Error in adding singlepoint-to-multipoint " +
1545 "intent" )
shahshreyac2f97072015-03-19 17:04:29 -07001546 return None
kelvin-onlabb9408212015-04-01 13:34:04 -07001547 else:
1548 match = re.search('id=0x([\da-f]+),', handle)
1549 if match:
1550 return match.group()[3:-1]
1551 else:
1552 main.log.error( "Error, intent ID not found" )
1553 return None
Jon Hallc6793552016-01-19 14:18:37 -08001554 except AssertionError:
1555 main.log.exception( "" )
1556 return None
Jon Halld4d4b372015-01-28 16:02:41 -08001557 except TypeError:
1558 main.log.exception( self.name + ": Object not as expected" )
1559 return None
shahshreyad0c80432014-12-04 16:56:05 -08001560 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08001561 main.log.error( self.name + ": EOF exception found" )
1562 main.log.error( self.name + ": " + self.handle.before )
shahshreyad0c80432014-12-04 16:56:05 -08001563 main.cleanup()
1564 main.exit()
Jon Hallfebb1c72015-03-05 13:30:09 -08001565 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -08001566 main.log.exception( self.name + ": Uncaught exception!" )
shahshreyad0c80432014-12-04 16:56:05 -08001567 main.cleanup()
1568 main.exit()
1569
Hari Krishna9e232602015-04-13 17:29:08 -07001570 def addMplsIntent(
1571 self,
1572 ingressDevice,
1573 egressDevice,
Hari Krishna87a17f12015-04-13 17:42:23 -07001574 ingressPort="",
1575 egressPort="",
Hari Krishna9e232602015-04-13 17:29:08 -07001576 ethType="",
1577 ethSrc="",
1578 ethDst="",
1579 bandwidth="",
1580 lambdaAlloc=False,
1581 ipProto="",
1582 ipSrc="",
1583 ipDst="",
1584 tcpSrc="",
1585 tcpDst="",
Hari Krishna87a17f12015-04-13 17:42:23 -07001586 ingressLabel="",
Hari Krishnadfff6672015-04-13 17:53:27 -07001587 egressLabel="",
Hari Krishna9e232602015-04-13 17:29:08 -07001588 priority=""):
1589 """
1590 Required:
1591 * ingressDevice: device id of ingress device
1592 * egressDevice: device id of egress device
1593 Optional:
1594 * ethType: specify ethType
1595 * ethSrc: specify ethSrc ( i.e. src mac addr )
1596 * ethDst: specify ethDst ( i.e. dst mac addr )
1597 * bandwidth: specify bandwidth capacity of link
1598 * lambdaAlloc: if True, intent will allocate lambda
1599 for the specified intent
1600 * ipProto: specify ip protocol
1601 * ipSrc: specify ip source address
1602 * ipDst: specify ip destination address
1603 * tcpSrc: specify tcp source port
1604 * tcpDst: specify tcp destination port
1605 * ingressLabel: Ingress MPLS label
1606 * egressLabel: Egress MPLS label
1607 Description:
1608 Adds MPLS intent by
1609 specifying device id's and optional fields
1610 Returns:
1611 A string of the intent id or None on error
1612
1613 NOTE: This function may change depending on the
1614 options developers provide for MPLS
1615 intent via cli
1616 """
1617 try:
1618 # If there are no optional arguments
1619 if not ethType and not ethSrc and not ethDst\
1620 and not bandwidth and not lambdaAlloc \
1621 and not ipProto and not ipSrc and not ipDst \
1622 and not tcpSrc and not tcpDst and not ingressLabel \
1623 and not egressLabel:
1624 cmd = "add-mpls-intent"
1625
1626 else:
1627 cmd = "add-mpls-intent"
1628
1629 if ethType:
1630 cmd += " --ethType " + str( ethType )
1631 if ethSrc:
1632 cmd += " --ethSrc " + str( ethSrc )
1633 if ethDst:
1634 cmd += " --ethDst " + str( ethDst )
1635 if bandwidth:
1636 cmd += " --bandwidth " + str( bandwidth )
1637 if lambdaAlloc:
1638 cmd += " --lambda "
1639 if ipProto:
1640 cmd += " --ipProto " + str( ipProto )
1641 if ipSrc:
1642 cmd += " --ipSrc " + str( ipSrc )
1643 if ipDst:
1644 cmd += " --ipDst " + str( ipDst )
1645 if tcpSrc:
1646 cmd += " --tcpSrc " + str( tcpSrc )
1647 if tcpDst:
1648 cmd += " --tcpDst " + str( tcpDst )
1649 if ingressLabel:
1650 cmd += " --ingressLabel " + str( ingressLabel )
1651 if egressLabel:
1652 cmd += " --egressLabel " + str( egressLabel )
1653 if priority:
1654 cmd += " --priority " + str( priority )
1655
1656 # Check whether the user appended the port
1657 # or provided it as an input
1658 if "/" in ingressDevice:
1659 cmd += " " + str( ingressDevice )
1660 else:
Hari Krishna87a17f12015-04-13 17:42:23 -07001661 if not ingressPort:
Hari Krishna9e232602015-04-13 17:29:08 -07001662 main.log.error( "You must specify the ingress port" )
1663 return None
1664
1665 cmd += " " + \
1666 str( ingressDevice ) + "/" +\
Hari Krishna87a17f12015-04-13 17:42:23 -07001667 str( ingressPort ) + " "
Hari Krishna9e232602015-04-13 17:29:08 -07001668
1669 if "/" in egressDevice:
1670 cmd += " " + str( egressDevice )
1671 else:
Hari Krishna87a17f12015-04-13 17:42:23 -07001672 if not egressPort:
Hari Krishna9e232602015-04-13 17:29:08 -07001673 main.log.error( "You must specify the egress port" )
1674 return None
1675
1676 cmd += " " +\
1677 str( egressDevice ) + "/" +\
Hari Krishna87a17f12015-04-13 17:42:23 -07001678 str( egressPort )
Hari Krishna9e232602015-04-13 17:29:08 -07001679
1680 handle = self.sendline( cmd )
Jon Hallc6793552016-01-19 14:18:37 -08001681 assert "Command not found:" not in handle, handle
Hari Krishna9e232602015-04-13 17:29:08 -07001682 # If error, return error message
1683 if re.search( "Error", handle ):
1684 main.log.error( "Error in adding mpls intent" )
1685 return None
1686 else:
1687 # TODO: print out all the options in this message?
1688 main.log.info( "MPLS intent installed between " +
1689 str( ingressDevice ) + " and " +
1690 str( egressDevice ) )
1691 match = re.search('id=0x([\da-f]+),', handle)
1692 if match:
1693 return match.group()[3:-1]
1694 else:
1695 main.log.error( "Error, intent ID not found" )
1696 return None
Jon Hallc6793552016-01-19 14:18:37 -08001697 except AssertionError:
1698 main.log.exception( "" )
1699 return None
Hari Krishna9e232602015-04-13 17:29:08 -07001700 except TypeError:
1701 main.log.exception( self.name + ": Object not as expected" )
1702 return None
1703 except pexpect.EOF:
1704 main.log.error( self.name + ": EOF exception found" )
1705 main.log.error( self.name + ": " + self.handle.before )
1706 main.cleanup()
1707 main.exit()
1708 except Exception:
1709 main.log.exception( self.name + ": Uncaught exception!" )
1710 main.cleanup()
1711 main.exit()
1712
Jon Hallefbd9792015-03-05 16:11:36 -08001713 def removeIntent( self, intentId, app='org.onosproject.cli',
1714 purge=False, sync=False ):
kelvin-onlab898a6c62015-01-16 14:13:53 -08001715 """
shahshreya1c818fc2015-02-26 13:44:08 -08001716 Remove intent for specified application id and intent id
Jon Hall61282e32015-03-19 11:34:11 -07001717 Optional args:-
shahshreya1c818fc2015-02-26 13:44:08 -08001718 -s or --sync: Waits for the removal before returning
Jon Hall61282e32015-03-19 11:34:11 -07001719 -p or --purge: Purge the intent from the store after removal
1720
Jon Halle3f39ff2015-01-13 11:50:53 -08001721 Returns:
1722 main.False on error and
1723 cli output otherwise
kelvin-onlab898a6c62015-01-16 14:13:53 -08001724 """
andrewonlab9a50dfe2014-10-17 17:22:31 -04001725 try:
Jon Hallc6358dd2015-04-10 12:44:28 -07001726 cmdStr = "remove-intent"
shahshreya1c818fc2015-02-26 13:44:08 -08001727 if purge:
1728 cmdStr += " -p"
1729 if sync:
1730 cmdStr += " -s"
1731
1732 cmdStr += " " + app + " " + str( intentId )
kelvin-onlabd3b64892015-01-20 13:26:24 -08001733 handle = self.sendline( cmdStr )
Jon Hallc6793552016-01-19 14:18:37 -08001734 assert "Command not found:" not in handle, handle
Jon Halle3f39ff2015-01-13 11:50:53 -08001735 if re.search( "Error", handle ):
kelvin-onlab898a6c62015-01-16 14:13:53 -08001736 main.log.error( "Error in removing intent" )
Jon Halle3f39ff2015-01-13 11:50:53 -08001737 return main.FALSE
andrewonlab9a50dfe2014-10-17 17:22:31 -04001738 else:
Jon Halle3f39ff2015-01-13 11:50:53 -08001739 # TODO: Should this be main.TRUE
1740 return handle
Jon Hallc6793552016-01-19 14:18:37 -08001741 except AssertionError:
1742 main.log.exception( "" )
1743 return None
Jon Halld4d4b372015-01-28 16:02:41 -08001744 except TypeError:
1745 main.log.exception( self.name + ": Object not as expected" )
1746 return None
andrewonlab9a50dfe2014-10-17 17:22:31 -04001747 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08001748 main.log.error( self.name + ": EOF exception found" )
1749 main.log.error( self.name + ": " + self.handle.before )
andrewonlab9a50dfe2014-10-17 17:22:31 -04001750 main.cleanup()
1751 main.exit()
Jon Hallfebb1c72015-03-05 13:30:09 -08001752 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -08001753 main.log.exception( self.name + ": Uncaught exception!" )
andrewonlab9a50dfe2014-10-17 17:22:31 -04001754 main.cleanup()
1755 main.exit()
1756
Jeremy42df2e72016-02-23 16:37:46 -08001757 def removeAllIntents( self, purge=False, sync=False, app='org.onosproject.cli' ):
1758 """
1759 Description:
1760 Remove all the intents
1761 Optional args:-
1762 -s or --sync: Waits for the removal before returning
1763 -p or --purge: Purge the intent from the store after removal
1764 Returns:
1765 Returns main.TRUE if all intents are removed, otherwise returns
1766 main.FALSE; Returns None for exception
1767 """
1768 try:
1769 cmdStr = "remove-intent"
1770 if purge:
1771 cmdStr += " -p"
1772 if sync:
1773 cmdStr += " -s"
1774
1775 cmdStr += " " + app
1776 handle = self.sendline( cmdStr )
1777 assert "Command not found:" not in handle, handle
1778 if re.search( "Error", handle ):
1779 main.log.error( "Error in removing intent" )
1780 return main.FALSE
1781 else:
1782 return main.TRUE
1783 except AssertionError:
1784 main.log.exception( "" )
1785 return None
1786 except TypeError:
1787 main.log.exception( self.name + ": Object not as expected" )
1788 return None
1789 except pexpect.EOF:
1790 main.log.error( self.name + ": EOF exception found" )
1791 main.log.error( self.name + ": " + self.handle.before )
1792 main.cleanup()
1793 main.exit()
1794 except Exception:
1795 main.log.exception( self.name + ": Uncaught exception!" )
1796 main.cleanup()
1797 main.exit()
1798
Hari Krishnaacabd5a2015-07-01 17:10:19 -07001799 def purgeWithdrawnIntents( self ):
Hari Krishna0ce0e152015-06-23 09:55:29 -07001800 """
1801 Purges all WITHDRAWN Intents
1802 """
1803 try:
1804 cmdStr = "purge-intents"
1805 handle = self.sendline( cmdStr )
Jon Hallc6793552016-01-19 14:18:37 -08001806 assert "Command not found:" not in handle, handle
Hari Krishna0ce0e152015-06-23 09:55:29 -07001807 if re.search( "Error", handle ):
1808 main.log.error( "Error in purging intents" )
1809 return main.FALSE
1810 else:
1811 return main.TRUE
Jon Hallc6793552016-01-19 14:18:37 -08001812 except AssertionError:
1813 main.log.exception( "" )
1814 return None
Hari Krishna0ce0e152015-06-23 09:55:29 -07001815 except TypeError:
1816 main.log.exception( self.name + ": Object not as expected" )
1817 return None
1818 except pexpect.EOF:
1819 main.log.error( self.name + ": EOF exception found" )
1820 main.log.error( self.name + ": " + self.handle.before )
1821 main.cleanup()
1822 main.exit()
1823 except Exception:
1824 main.log.exception( self.name + ": Uncaught exception!" )
1825 main.cleanup()
1826 main.exit()
1827
kelvin-onlabd3b64892015-01-20 13:26:24 -08001828 def routes( self, jsonFormat=False ):
kelvin8ec71442015-01-15 16:57:00 -08001829 """
kelvin-onlab898a6c62015-01-16 14:13:53 -08001830 NOTE: This method should be used after installing application:
1831 onos-app-sdnip
pingping-lin8b306ac2014-11-17 18:13:51 -08001832 Optional:
kelvin-onlabd3b64892015-01-20 13:26:24 -08001833 * jsonFormat: enable output formatting in json
pingping-lin8b306ac2014-11-17 18:13:51 -08001834 Description:
1835 Obtain all routes in the system
kelvin8ec71442015-01-15 16:57:00 -08001836 """
pingping-lin8b306ac2014-11-17 18:13:51 -08001837 try:
Jon Hallc6358dd2015-04-10 12:44:28 -07001838 cmdStr = "routes"
kelvin-onlabd3b64892015-01-20 13:26:24 -08001839 if jsonFormat:
Jon Hallc6358dd2015-04-10 12:44:28 -07001840 cmdStr += " -j"
1841 handle = self.sendline( cmdStr )
Jon Hallc6793552016-01-19 14:18:37 -08001842 assert "Command not found:" not in handle, handle
pingping-lin8b306ac2014-11-17 18:13:51 -08001843 return handle
Jon Hallc6793552016-01-19 14:18:37 -08001844 except AssertionError:
1845 main.log.exception( "" )
1846 return None
Jon Halld4d4b372015-01-28 16:02:41 -08001847 except TypeError:
1848 main.log.exception( self.name + ": Object not as expected" )
1849 return None
pingping-lin8b306ac2014-11-17 18:13:51 -08001850 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08001851 main.log.error( self.name + ": EOF exception found" )
1852 main.log.error( self.name + ": " + self.handle.before )
pingping-lin8b306ac2014-11-17 18:13:51 -08001853 main.cleanup()
1854 main.exit()
Jon Hallfebb1c72015-03-05 13:30:09 -08001855 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -08001856 main.log.exception( self.name + ": Uncaught exception!" )
pingping-lin8b306ac2014-11-17 18:13:51 -08001857 main.cleanup()
1858 main.exit()
1859
pingping-lin54b03372015-08-13 14:43:10 -07001860 def ipv4RouteNumber( self ):
1861 """
1862 NOTE: This method should be used after installing application:
1863 onos-app-sdnip
1864 Description:
1865 Obtain the total IPv4 routes number in the system
1866 """
1867 try:
1868 cmdStr = "routes -s -j"
1869 handle = self.sendline( cmdStr )
Jon Hallc6793552016-01-19 14:18:37 -08001870 assert "Command not found:" not in handle, handle
pingping-lin54b03372015-08-13 14:43:10 -07001871 jsonResult = json.loads( handle )
1872 return jsonResult['totalRoutes4']
Jon Hallc6793552016-01-19 14:18:37 -08001873 except AssertionError:
1874 main.log.exception( "" )
1875 return None
1876 except ( TypeError, ValueError ):
1877 main.log.exception( "{}: Object not as expected: {!r}".format( self.name, handle ) )
pingping-lin54b03372015-08-13 14:43:10 -07001878 return None
1879 except pexpect.EOF:
1880 main.log.error( self.name + ": EOF exception found" )
1881 main.log.error( self.name + ": " + self.handle.before )
1882 main.cleanup()
1883 main.exit()
1884 except Exception:
1885 main.log.exception( self.name + ": Uncaught exception!" )
1886 main.cleanup()
1887 main.exit()
1888
pingping-lin8244a3b2015-09-16 13:36:56 -07001889 def intents( self, jsonFormat = True, summary = False, **intentargs):
kelvin8ec71442015-01-15 16:57:00 -08001890 """
andrewonlabe6745342014-10-17 14:29:13 -04001891 Description:
Jon Hallff566d52016-01-15 14:45:36 -08001892 Obtain intents from the ONOS cli.
1893 Optional:
1894 * jsonFormat: Enable output formatting in json, default to True
1895 * summary: Whether only output the intent summary, defaults to False
1896 * type: Only output a certain type of intent. This options is valid
1897 only when jsonFormat is True and summary is True.
kelvin-onlab898a6c62015-01-16 14:13:53 -08001898 """
andrewonlabe6745342014-10-17 14:29:13 -04001899 try:
Jon Hallc6358dd2015-04-10 12:44:28 -07001900 cmdStr = "intents"
pingping-lin8244a3b2015-09-16 13:36:56 -07001901 if summary:
1902 cmdStr += " -s"
kelvin-onlabd3b64892015-01-20 13:26:24 -08001903 if jsonFormat:
Jon Hallc6358dd2015-04-10 12:44:28 -07001904 cmdStr += " -j"
1905 handle = self.sendline( cmdStr )
Jon Hallc6793552016-01-19 14:18:37 -08001906 assert "Command not found:" not in handle, handle
pingping-lin8244a3b2015-09-16 13:36:56 -07001907 args = utilities.parse_args( [ "TYPE" ], **intentargs )
acsmars5b5fbaf2015-09-18 10:38:20 -07001908 if "TYPE" in args.keys():
Jon Hallff566d52016-01-15 14:45:36 -08001909 intentType = args[ "TYPE" ]
acsmars5b5fbaf2015-09-18 10:38:20 -07001910 else:
Jon Hallff566d52016-01-15 14:45:36 -08001911 intentType = ""
1912 # IF we want the summary of a specific intent type
1913 if jsonFormat and summary and ( intentType != "" ):
pingping-lin8244a3b2015-09-16 13:36:56 -07001914 jsonResult = json.loads( handle )
Jon Hallff566d52016-01-15 14:45:36 -08001915 if intentType in jsonResult.keys():
1916 return jsonResult[ intentType ]
pingping-lin8244a3b2015-09-16 13:36:56 -07001917 else:
Jon Hallff566d52016-01-15 14:45:36 -08001918 main.log.error( "unknown TYPE, returning all types of intents" )
pingping-lin8244a3b2015-09-16 13:36:56 -07001919 return handle
1920 else:
1921 return handle
Jon Hallc6793552016-01-19 14:18:37 -08001922 except AssertionError:
1923 main.log.exception( "" )
1924 return None
1925 except ( TypeError, ValueError ):
1926 main.log.exception( "{}: Object not as expected: {!r}".format( self.name, handle ) )
pingping-lin54b03372015-08-13 14:43:10 -07001927 return None
1928 except pexpect.EOF:
1929 main.log.error( self.name + ": EOF exception found" )
1930 main.log.error( self.name + ": " + self.handle.before )
1931 main.cleanup()
1932 main.exit()
1933 except Exception:
1934 main.log.exception( self.name + ": Uncaught exception!" )
1935 main.cleanup()
1936 main.exit()
1937
kelvin-onlab54400a92015-02-26 18:05:51 -08001938 def getIntentState(self, intentsId, intentsJson=None):
1939 """
kelvin-onlab54400a92015-02-26 18:05:51 -08001940 Check intent state.
1941 Accepts a single intent ID (string type) or a list of intent IDs.
1942 Returns the state(string type) of the id if a single intent ID is
1943 accepted.
Jon Hallefbd9792015-03-05 16:11:36 -08001944 Returns a dictionary with intent IDs as the key and its
1945 corresponding states as the values
kelvin-onlabfb521662015-02-27 09:52:40 -08001946 Parameters:
kelvin-onlab54400a92015-02-26 18:05:51 -08001947 intentId: intent ID (string type)
1948 intentsJson: parsed json object from the onos:intents api
1949 Returns:
1950 state = An intent's state- INSTALL,WITHDRAWN etc.
1951 stateDict = Dictionary of intent's state. intent ID as the keys and
1952 state as the values.
1953 """
kelvin-onlab54400a92015-02-26 18:05:51 -08001954 try:
1955 state = "State is Undefined"
1956 if not intentsJson:
Jon Hallc6793552016-01-19 14:18:37 -08001957 rawJson = self.intents()
kelvin-onlab54400a92015-02-26 18:05:51 -08001958 else:
Jon Hallc6793552016-01-19 14:18:37 -08001959 rawJson = intentsJson
1960 parsedIntentsJson = json.loads( rawJson )
Jon Hallefbd9792015-03-05 16:11:36 -08001961 if isinstance( intentsId, types.StringType ):
Jon Hallc6793552016-01-19 14:18:37 -08001962 for intent in parsedIntentsJson:
kelvin-onlabc2dcd3f2015-04-09 16:40:02 -07001963 if intentsId == intent[ 'id' ]:
1964 state = intent[ 'state' ]
kelvin-onlab54400a92015-02-26 18:05:51 -08001965 return state
Jon Hallefbd9792015-03-05 16:11:36 -08001966 main.log.info( "Cannot find intent ID" + str( intentsId ) +
1967 " on the list" )
kelvin-onlab54400a92015-02-26 18:05:51 -08001968 return state
Jon Hallefbd9792015-03-05 16:11:36 -08001969 elif isinstance( intentsId, types.ListType ):
kelvin-onlab07dbd012015-03-04 16:29:39 -08001970 dictList = []
kelvin-onlabc2dcd3f2015-04-09 16:40:02 -07001971 for i in xrange( len( intentsId ) ):
kelvin-onlab07dbd012015-03-04 16:29:39 -08001972 stateDict = {}
Jon Hallc6793552016-01-19 14:18:37 -08001973 for intents in parsedIntentsJson:
kelvin-onlabc2dcd3f2015-04-09 16:40:02 -07001974 if intentsId[ i ] == intents[ 'id' ]:
1975 stateDict[ 'state' ] = intents[ 'state' ]
1976 stateDict[ 'id' ] = intentsId[ i ]
Jon Hallefbd9792015-03-05 16:11:36 -08001977 dictList.append( stateDict )
kelvin-onlab54400a92015-02-26 18:05:51 -08001978 break
Jon Hallefbd9792015-03-05 16:11:36 -08001979 if len( intentsId ) != len( dictList ):
1980 main.log.info( "Cannot find some of the intent ID state" )
kelvin-onlab07dbd012015-03-04 16:29:39 -08001981 return dictList
kelvin-onlab54400a92015-02-26 18:05:51 -08001982 else:
kelvin-onlabc2dcd3f2015-04-09 16:40:02 -07001983 main.log.info( "Invalid intents ID entry" )
kelvin-onlab54400a92015-02-26 18:05:51 -08001984 return None
Jon Hallc6793552016-01-19 14:18:37 -08001985 except ( TypeError, ValueError ):
1986 main.log.exception( "{}: Object not as expected: {!r}".format( self.name, rawJson ) )
kelvin-onlab54400a92015-02-26 18:05:51 -08001987 return None
1988 except pexpect.EOF:
1989 main.log.error( self.name + ": EOF exception found" )
1990 main.log.error( self.name + ": " + self.handle.before )
1991 main.cleanup()
1992 main.exit()
Jon Hallfebb1c72015-03-05 13:30:09 -08001993 except Exception:
kelvin-onlab54400a92015-02-26 18:05:51 -08001994 main.log.exception( self.name + ": Uncaught exception!" )
andrewonlabe6745342014-10-17 14:29:13 -04001995 main.cleanup()
1996 main.exit()
Jon Hall390696c2015-05-05 17:13:41 -07001997
kelvin-onlabf512e942015-06-08 19:42:59 -07001998 def checkIntentState( self, intentsId, expectedState='INSTALLED' ):
kelvin-onlabc2dcd3f2015-04-09 16:40:02 -07001999 """
2000 Description:
2001 Check intents state
2002 Required:
2003 intentsId - List of intents ID to be checked
2004 Optional:
kelvin-onlabf512e942015-06-08 19:42:59 -07002005 expectedState - Check the expected state(s) of each intents
2006 state in the list.
2007 *NOTE: You can pass in a list of expected state,
2008 Eg: expectedState = [ 'INSTALLED' , 'INSTALLING' ]
kelvin-onlabc2dcd3f2015-04-09 16:40:02 -07002009 Return:
kelvin-onlabf512e942015-06-08 19:42:59 -07002010 Returns main.TRUE only if all intent are the same as expected states
2011 , otherwise, returns main.FALSE.
kelvin-onlabc2dcd3f2015-04-09 16:40:02 -07002012 """
2013 try:
2014 # Generating a dictionary: intent id as a key and state as value
kelvin-onlabf512e942015-06-08 19:42:59 -07002015 returnValue = main.TRUE
kelvin-onlabc2dcd3f2015-04-09 16:40:02 -07002016 intentsDict = self.getIntentState( intentsId )
kelvin-onlabc2dcd3f2015-04-09 16:40:02 -07002017 if len( intentsId ) != len( intentsDict ):
Jon Hallae04e622016-01-27 10:38:05 -08002018 main.log.info( self.name + ": There is something wrong " +
kelvin-onlabc2dcd3f2015-04-09 16:40:02 -07002019 "getting intents state" )
2020 return main.FALSE
kelvin-onlabf512e942015-06-08 19:42:59 -07002021
2022 if isinstance( expectedState, types.StringType ):
2023 for intents in intentsDict:
2024 if intents.get( 'state' ) != expectedState:
kelvin-onlaba297c4d2015-06-01 13:53:55 -07002025 main.log.debug( self.name + " : Intent ID - " +
2026 intents.get( 'id' ) +
kelvin-onlabf512e942015-06-08 19:42:59 -07002027 " actual state = " +
2028 intents.get( 'state' )
2029 + " does not equal expected state = "
2030 + expectedState )
kelvin-onlaba297c4d2015-06-01 13:53:55 -07002031 returnValue = main.FALSE
kelvin-onlabf512e942015-06-08 19:42:59 -07002032
2033 elif isinstance( expectedState, types.ListType ):
2034 for intents in intentsDict:
2035 if not any( state == intents.get( 'state' ) for state in
2036 expectedState ):
2037 main.log.debug( self.name + " : Intent ID - " +
2038 intents.get( 'id' ) +
2039 " actual state = " +
2040 intents.get( 'state' ) +
2041 " does not equal expected states = "
2042 + str( expectedState ) )
2043 returnValue = main.FALSE
2044
kelvin-onlabc2dcd3f2015-04-09 16:40:02 -07002045 if returnValue == main.TRUE:
2046 main.log.info( self.name + ": All " +
2047 str( len( intentsDict ) ) +
kelvin-onlabf512e942015-06-08 19:42:59 -07002048 " intents are in " + str( expectedState ) +
2049 " state" )
kelvin-onlabc2dcd3f2015-04-09 16:40:02 -07002050 return returnValue
2051 except TypeError:
2052 main.log.exception( self.name + ": Object not as expected" )
2053 return None
2054 except pexpect.EOF:
2055 main.log.error( self.name + ": EOF exception found" )
2056 main.log.error( self.name + ": " + self.handle.before )
2057 main.cleanup()
2058 main.exit()
2059 except Exception:
2060 main.log.exception( self.name + ": Uncaught exception!" )
2061 main.cleanup()
2062 main.exit()
andrewonlabe6745342014-10-17 14:29:13 -04002063
GlennRCed771242016-01-13 17:02:47 -08002064 def checkIntentSummary( self, timeout=60 ):
2065 """
2066 Description:
2067 Check the number of installed intents.
2068 Optional:
2069 timeout - the timeout for pexcept
2070 Return:
2071 Returns main.TRUE only if the number of all installed intents are the same as total intents number
2072 , otherwise, returns main.FALSE.
2073 """
2074
2075 try:
2076 cmd = "intents -s -j"
2077
2078 # Check response if something wrong
2079 response = self.sendline( cmd, timeout=timeout )
2080 if response == None:
2081 return main.False
2082 response = json.loads( response )
2083
2084 # get total and installed number, see if they are match
2085 allState = response.get( 'all' )
2086 if allState.get('total') == allState.get('installed'):
YPZhangb5d3f832016-01-23 22:54:26 -08002087 main.log.info( 'Total Intents: {} Installed Intents: {}'.format( allState.get('total'), allState.get('installed') ) )
GlennRCed771242016-01-13 17:02:47 -08002088 return main.TRUE
YPZhangb5d3f832016-01-23 22:54:26 -08002089 main.log.info( 'Verified Intents failed Excepte intetnes: {} installed intents: {}'.format( allState.get('total'), allState.get('installed') ) )
GlennRCed771242016-01-13 17:02:47 -08002090 return main.FALSE
2091
Jon Hallc6793552016-01-19 14:18:37 -08002092 except ( TypeError, ValueError ):
2093 main.log.exception( "{}: Object not as expected: {!r}".format( self.name, response ) )
GlennRCed771242016-01-13 17:02:47 -08002094 return None
2095 except pexpect.EOF:
2096 main.log.error( self.name + ": EOF exception found" )
2097 main.log.error( self.name + ": " + self.handle.before )
2098 main.cleanup()
2099 main.exit()
2100 except Exception:
2101 main.log.exception( self.name + ": Uncaught exception!" )
2102 main.cleanup()
2103 main.exit()
2104
2105 def flows( self, state="", jsonFormat=True, timeout=60 ):
kelvin8ec71442015-01-15 16:57:00 -08002106 """
Shreya Shah0f01c812014-10-26 20:15:28 -04002107 Optional:
kelvin-onlabd3b64892015-01-20 13:26:24 -08002108 * jsonFormat: enable output formatting in json
Shreya Shah0f01c812014-10-26 20:15:28 -04002109 Description:
Jon Halle3f39ff2015-01-13 11:50:53 -08002110 Obtain flows currently installed
kelvin-onlab898a6c62015-01-16 14:13:53 -08002111 """
Shreya Shah0f01c812014-10-26 20:15:28 -04002112 try:
Jon Hallc6358dd2015-04-10 12:44:28 -07002113 cmdStr = "flows"
kelvin-onlabd3b64892015-01-20 13:26:24 -08002114 if jsonFormat:
GlennRCed771242016-01-13 17:02:47 -08002115 cmdStr += " -j "
2116 cmdStr += state
Jon Hallc6793552016-01-19 14:18:37 -08002117 handle = self.sendline( cmdStr, timeout=timeout )
2118 assert "Command not found:" not in handle, handle
2119 if re.search( "Error:", handle ):
2120 main.log.error( self.name + ": flows() response: " +
2121 str( handle ) )
2122 return handle
2123 except AssertionError:
2124 main.log.exception( "" )
GlennRCed771242016-01-13 17:02:47 -08002125 return None
Jon Halld4d4b372015-01-28 16:02:41 -08002126 except TypeError:
2127 main.log.exception( self.name + ": Object not as expected" )
2128 return None
Jon Hallc6793552016-01-19 14:18:37 -08002129 except pexpect.TIMEOUT:
2130 main.log.error( self.name + ": ONOS timeout" )
2131 return None
Shreya Shah0f01c812014-10-26 20:15:28 -04002132 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08002133 main.log.error( self.name + ": EOF exception found" )
2134 main.log.error( self.name + ": " + self.handle.before )
Shreya Shah0f01c812014-10-26 20:15:28 -04002135 main.cleanup()
2136 main.exit()
Jon Hallfebb1c72015-03-05 13:30:09 -08002137 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -08002138 main.log.exception( self.name + ": Uncaught exception!" )
Shreya Shah0f01c812014-10-26 20:15:28 -04002139 main.cleanup()
2140 main.exit()
2141
Flavio Castrod2ffffa2016-04-26 15:56:56 -07002142 def checkFlowCount(self, min=0, timeout=60 ):
2143 count = int(self.getTotalFlowsNum( timeout=timeout ))
2144 return count if (count > min) else False
GlennRCed771242016-01-13 17:02:47 -08002145
Jon Hallc6793552016-01-19 14:18:37 -08002146 def checkFlowsState( self, isPENDING=True, timeout=60 ):
kelvin-onlab4df89f22015-04-13 18:10:23 -07002147 """
2148 Description:
GlennRCed771242016-01-13 17:02:47 -08002149 Check the if all the current flows are in ADDED state
Jon Hallc6793552016-01-19 14:18:37 -08002150 We check PENDING_ADD, PENDING_REMOVE, REMOVED, and FAILED flows,
2151 if the count of those states is 0, which means all current flows
2152 are in ADDED state, and return main.TRUE otherwise return main.FALSE
pingping-linbab7f8a2015-09-21 17:33:36 -07002153 Optional:
GlennRCed771242016-01-13 17:02:47 -08002154 * isPENDING: whether the PENDING_ADD is also a correct status
kelvin-onlab4df89f22015-04-13 18:10:23 -07002155 Return:
2156 returnValue - Returns main.TRUE only if all flows are in
Jon Hallc6793552016-01-19 14:18:37 -08002157 ADDED state or PENDING_ADD if the isPENDING
pingping-linbab7f8a2015-09-21 17:33:36 -07002158 parameter is set true, return main.FALSE otherwise.
kelvin-onlab4df89f22015-04-13 18:10:23 -07002159 """
2160 try:
GlennRCed771242016-01-13 17:02:47 -08002161 states = ["PENDING_ADD", "PENDING_REMOVE", "REMOVED", "FAILED"]
2162 checkedStates = []
2163 statesCount = [0, 0, 0, 0]
2164 for s in states:
Jon Hallc6793552016-01-19 14:18:37 -08002165 rawFlows = self.flows( state=s, timeout = timeout )
2166 checkedStates.append( json.loads( rawFlows ) )
2167 for i in range( len( states ) ):
GlennRCed771242016-01-13 17:02:47 -08002168 for c in checkedStates[i]:
Jon Hallc6793552016-01-19 14:18:37 -08002169 try:
2170 statesCount[i] += int( c.get( "flowCount" ) )
2171 except TypeError:
2172 main.log.exception( "Json object not as expected" )
2173 main.log.info( states[i] + " flows: " + str( statesCount[i] ) )
kelvin-onlabf2ec6e02015-05-27 14:15:28 -07002174
GlennRCed771242016-01-13 17:02:47 -08002175 # We want to count PENDING_ADD if isPENDING is true
2176 if isPENDING:
2177 if statesCount[1] + statesCount[2] + statesCount[3] > 0:
2178 return main.FALSE
pingping-linbab7f8a2015-09-21 17:33:36 -07002179 else:
GlennRCed771242016-01-13 17:02:47 -08002180 if statesCount[0] + statesCount[1] + statesCount[2] + statesCount[3] > 0:
2181 return main.FALSE
GlennRCed771242016-01-13 17:02:47 -08002182 return main.TRUE
Jon Hallc6793552016-01-19 14:18:37 -08002183 except ( TypeError, ValueError ):
2184 main.log.exception( "{}: Object not as expected: {!r}".format( self.name, rawFlows ) )
kelvin-onlab4df89f22015-04-13 18:10:23 -07002185 return None
2186 except pexpect.EOF:
2187 main.log.error( self.name + ": EOF exception found" )
2188 main.log.error( self.name + ": " + self.handle.before )
2189 main.cleanup()
2190 main.exit()
2191 except Exception:
2192 main.log.exception( self.name + ": Uncaught exception!" )
2193 main.cleanup()
2194 main.exit()
2195
GlennRCed771242016-01-13 17:02:47 -08002196 def pushTestIntents( self, ingress, egress, batchSize, offset="",
2197 options="", timeout=10, background = False ):
kelvin8ec71442015-01-15 16:57:00 -08002198 """
andrewonlab87852b02014-11-19 18:44:19 -05002199 Description:
Jon Halle3f39ff2015-01-13 11:50:53 -08002200 Push a number of intents in a batch format to
andrewonlab87852b02014-11-19 18:44:19 -05002201 a specific point-to-point intent definition
2202 Required:
GlennRCed771242016-01-13 17:02:47 -08002203 * ingress: specify source dpid
2204 * egress: specify destination dpid
2205 * batchSize: specify number of intents to push
andrewonlab87852b02014-11-19 18:44:19 -05002206 Optional:
GlennRCed771242016-01-13 17:02:47 -08002207 * offset: the keyOffset is where the next batch of intents
2208 will be installed
2209 Returns: If failed to push test intents, it will returen None,
2210 if successful, return true.
2211 Timeout expection will return None,
2212 TypeError will return false
2213 other expections will exit()
kelvin8ec71442015-01-15 16:57:00 -08002214 """
andrewonlab87852b02014-11-19 18:44:19 -05002215 try:
GlennRCed771242016-01-13 17:02:47 -08002216 if background:
2217 back = "&"
andrewonlab87852b02014-11-19 18:44:19 -05002218 else:
GlennRCed771242016-01-13 17:02:47 -08002219 back = ""
2220 cmd = "push-test-intents {} {} {} {} {} {}".format( options,
Jon Hallc6793552016-01-19 14:18:37 -08002221 ingress,
2222 egress,
2223 batchSize,
2224 offset,
2225 back )
GlennRCed771242016-01-13 17:02:47 -08002226 response = self.sendline( cmd, timeout=timeout )
Jon Hallc6793552016-01-19 14:18:37 -08002227 assert "Command not found:" not in response, response
GlennRCed771242016-01-13 17:02:47 -08002228 main.log.info( response )
2229 if response == None:
2230 return None
2231
2232 # TODO: We should handle if there is failure in installation
2233 return main.TRUE
2234
Jon Hallc6793552016-01-19 14:18:37 -08002235 except AssertionError:
2236 main.log.exception( "" )
2237 return None
GlennRCed771242016-01-13 17:02:47 -08002238 except pexpect.TIMEOUT:
2239 main.log.error( self.name + ": ONOS timeout" )
Jon Halld4d4b372015-01-28 16:02:41 -08002240 return None
andrewonlab87852b02014-11-19 18:44:19 -05002241 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08002242 main.log.error( self.name + ": EOF exception found" )
2243 main.log.error( self.name + ": " + self.handle.before )
andrewonlab87852b02014-11-19 18:44:19 -05002244 main.cleanup()
2245 main.exit()
GlennRCed771242016-01-13 17:02:47 -08002246 except TypeError:
2247 main.log.exception( self.name + ": Object not as expected" )
Jon Hallc6793552016-01-19 14:18:37 -08002248 return None
Jon Hallfebb1c72015-03-05 13:30:09 -08002249 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -08002250 main.log.exception( self.name + ": Uncaught exception!" )
andrewonlab87852b02014-11-19 18:44:19 -05002251 main.cleanup()
2252 main.exit()
2253
YPZhangf6f14a02016-01-28 15:17:31 -08002254 def getTotalFlowsNum( self, timeout=60 ):
YPZhangb5d3f832016-01-23 22:54:26 -08002255 """
2256 Description:
YPZhangf6f14a02016-01-28 15:17:31 -08002257 Get the number of ADDED flows.
YPZhangb5d3f832016-01-23 22:54:26 -08002258 Return:
YPZhangf6f14a02016-01-28 15:17:31 -08002259 The number of ADDED flows
YPZhangb5d3f832016-01-23 22:54:26 -08002260 """
YPZhange3109a72016-02-02 11:25:37 -08002261
YPZhangb5d3f832016-01-23 22:54:26 -08002262 try:
YPZhange3109a72016-02-02 11:25:37 -08002263 # get total added flows number
YPZhangf6f14a02016-01-28 15:17:31 -08002264 cmd = "flows -s|grep ADDED|wc -l"
YPZhange3109a72016-02-02 11:25:37 -08002265 totalFlows = self.sendline( cmd, timeout=timeout )
2266
2267 if totalFlows == None:
2268 # if timeout, we will get total number of all flows, and subtract other states
2269 states = ["PENDING_ADD", "PENDING_REMOVE", "REMOVED", "FAILED"]
2270 checkedStates = []
2271 totalFlows = 0
2272 statesCount = [0, 0, 0, 0]
2273
2274 # get total flows from summary
2275 response = json.loads( self.sendline( "summary -j", timeout=timeout ) )
2276 totalFlows = int( response.get("flows") )
2277
2278 for s in states:
2279 rawFlows = self.flows( state=s, timeout = timeout )
2280 if rawFlows == None:
2281 # if timeout, return the total flows number from summary command
2282 return totalFlows
2283 checkedStates.append( json.loads( rawFlows ) )
2284
2285 # Calculate ADDED flows number, equal total subtracts others
2286 for i in range( len( states ) ):
2287 for c in checkedStates[i]:
2288 try:
2289 statesCount[i] += int( c.get( "flowCount" ) )
2290 except TypeError:
2291 main.log.exception( "Json object not as expected" )
2292 totalFlows = totalFlows - int( statesCount[i] )
2293 main.log.info( states[i] + " flows: " + str( statesCount[i] ) )
2294
2295 return totalFlows
2296
Flavio Castrod2ffffa2016-04-26 15:56:56 -07002297 return int(totalFlows)
YPZhange3109a72016-02-02 11:25:37 -08002298
YPZhangb5d3f832016-01-23 22:54:26 -08002299 except TypeError:
2300 main.log.exception( self.name + ": Object not as expected" )
2301 return None
2302 except pexpect.EOF:
2303 main.log.error( self.name + ": EOF exception found" )
2304 main.log.error( self.name + ": " + self.handle.before )
2305 main.cleanup()
2306 main.exit()
2307 except Exception:
2308 main.log.exception( self.name + ": Uncaught exception!" )
2309 main.cleanup()
2310 main.exit()
2311
2312 def getTotalIntentsNum( self ):
2313 """
2314 Description:
2315 Get the total number of intents, include every states.
2316 Return:
2317 The number of intents
2318 """
2319 try:
2320 cmd = "summary -j"
2321 response = self.sendline( cmd )
2322 if response == None:
2323 return -1
2324 response = json.loads( response )
2325 return int( response.get("intents") )
2326 except TypeError:
2327 main.log.exception( self.name + ": Object not as expected" )
2328 return None
2329 except pexpect.EOF:
2330 main.log.error( self.name + ": EOF exception found" )
2331 main.log.error( self.name + ": " + self.handle.before )
2332 main.cleanup()
2333 main.exit()
2334 except Exception:
2335 main.log.exception( self.name + ": Uncaught exception!" )
2336 main.cleanup()
2337 main.exit()
2338
kelvin-onlabd3b64892015-01-20 13:26:24 -08002339 def intentsEventsMetrics( self, jsonFormat=True ):
kelvin8ec71442015-01-15 16:57:00 -08002340 """
Jon Halle3f39ff2015-01-13 11:50:53 -08002341 Description:Returns topology metrics
andrewonlab0dbb6ec2014-11-06 13:46:55 -05002342 Optional:
kelvin-onlabd3b64892015-01-20 13:26:24 -08002343 * jsonFormat: enable json formatting of output
kelvin8ec71442015-01-15 16:57:00 -08002344 """
andrewonlab0dbb6ec2014-11-06 13:46:55 -05002345 try:
Jon Hallc6358dd2015-04-10 12:44:28 -07002346 cmdStr = "intents-events-metrics"
kelvin-onlabd3b64892015-01-20 13:26:24 -08002347 if jsonFormat:
Jon Hallc6358dd2015-04-10 12:44:28 -07002348 cmdStr += " -j"
2349 handle = self.sendline( cmdStr )
Jon Hallc6793552016-01-19 14:18:37 -08002350 assert "Command not found:" not in handle, handle
andrewonlab0dbb6ec2014-11-06 13:46:55 -05002351 return handle
Jon Hallc6793552016-01-19 14:18:37 -08002352 except AssertionError:
2353 main.log.exception( "" )
2354 return None
Jon Halld4d4b372015-01-28 16:02:41 -08002355 except TypeError:
2356 main.log.exception( self.name + ": Object not as expected" )
2357 return None
andrewonlab0dbb6ec2014-11-06 13:46:55 -05002358 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08002359 main.log.error( self.name + ": EOF exception found" )
2360 main.log.error( self.name + ": " + self.handle.before )
andrewonlab0dbb6ec2014-11-06 13:46:55 -05002361 main.cleanup()
2362 main.exit()
Jon Hallfebb1c72015-03-05 13:30:09 -08002363 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -08002364 main.log.exception( self.name + ": Uncaught exception!" )
andrewonlab0dbb6ec2014-11-06 13:46:55 -05002365 main.cleanup()
2366 main.exit()
Shreya Shah0f01c812014-10-26 20:15:28 -04002367
kelvin-onlabd3b64892015-01-20 13:26:24 -08002368 def topologyEventsMetrics( self, jsonFormat=True ):
kelvin8ec71442015-01-15 16:57:00 -08002369 """
2370 Description:Returns topology metrics
andrewonlab867212a2014-10-22 20:13:38 -04002371 Optional:
kelvin-onlabd3b64892015-01-20 13:26:24 -08002372 * jsonFormat: enable json formatting of output
kelvin8ec71442015-01-15 16:57:00 -08002373 """
andrewonlab867212a2014-10-22 20:13:38 -04002374 try:
Jon Hallc6358dd2015-04-10 12:44:28 -07002375 cmdStr = "topology-events-metrics"
kelvin-onlabd3b64892015-01-20 13:26:24 -08002376 if jsonFormat:
Jon Hallc6358dd2015-04-10 12:44:28 -07002377 cmdStr += " -j"
2378 handle = self.sendline( cmdStr )
Jon Hallc6793552016-01-19 14:18:37 -08002379 assert "Command not found:" not in handle, handle
jenkins7ead5a82015-03-13 10:28:21 -07002380 if handle:
2381 return handle
Jon Hallc6358dd2015-04-10 12:44:28 -07002382 elif jsonFormat:
Jon Hallbe379602015-03-24 13:39:32 -07002383 # Return empty json
jenkins7ead5a82015-03-13 10:28:21 -07002384 return '{}'
Jon Hallc6358dd2015-04-10 12:44:28 -07002385 else:
2386 return handle
Jon Hallc6793552016-01-19 14:18:37 -08002387 except AssertionError:
2388 main.log.exception( "" )
2389 return None
Jon Halld4d4b372015-01-28 16:02:41 -08002390 except TypeError:
2391 main.log.exception( self.name + ": Object not as expected" )
2392 return None
andrewonlab867212a2014-10-22 20:13:38 -04002393 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08002394 main.log.error( self.name + ": EOF exception found" )
2395 main.log.error( self.name + ": " + self.handle.before )
andrewonlab867212a2014-10-22 20:13:38 -04002396 main.cleanup()
2397 main.exit()
Jon Hallfebb1c72015-03-05 13:30:09 -08002398 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -08002399 main.log.exception( self.name + ": Uncaught exception!" )
andrewonlab867212a2014-10-22 20:13:38 -04002400 main.cleanup()
2401 main.exit()
2402
kelvin8ec71442015-01-15 16:57:00 -08002403 # Wrapper functions ****************
2404 # Wrapper functions use existing driver
2405 # functions and extends their use case.
2406 # For example, we may use the output of
2407 # a normal driver function, and parse it
2408 # using a wrapper function
andrewonlabc2d05aa2014-10-13 16:51:10 -04002409
kelvin-onlabd3b64892015-01-20 13:26:24 -08002410 def getAllIntentsId( self ):
kelvin8ec71442015-01-15 16:57:00 -08002411 """
andrewonlab9a50dfe2014-10-17 17:22:31 -04002412 Description:
2413 Obtain all intent id's in a list
kelvin8ec71442015-01-15 16:57:00 -08002414 """
andrewonlab9a50dfe2014-10-17 17:22:31 -04002415 try:
kelvin8ec71442015-01-15 16:57:00 -08002416 # Obtain output of intents function
kelvin-onlabfb521662015-02-27 09:52:40 -08002417 intentsStr = self.intents(jsonFormat=False)
kelvin-onlabd3b64892015-01-20 13:26:24 -08002418 intentIdList = []
andrewonlab9a50dfe2014-10-17 17:22:31 -04002419
kelvin8ec71442015-01-15 16:57:00 -08002420 # Parse the intents output for ID's
kelvin-onlabd3b64892015-01-20 13:26:24 -08002421 intentsList = [ s.strip() for s in intentsStr.splitlines() ]
2422 for intents in intentsList:
kelvin-onlabfb521662015-02-27 09:52:40 -08002423 match = re.search('id=0x([\da-f]+),', intents)
2424 if match:
2425 tmpId = match.group()[3:-1]
2426 intentIdList.append( tmpId )
kelvin-onlabd3b64892015-01-20 13:26:24 -08002427 return intentIdList
andrewonlab9a50dfe2014-10-17 17:22:31 -04002428
Jon Halld4d4b372015-01-28 16:02:41 -08002429 except TypeError:
2430 main.log.exception( self.name + ": Object not as expected" )
2431 return None
andrewonlab9a50dfe2014-10-17 17:22:31 -04002432 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08002433 main.log.error( self.name + ": EOF exception found" )
2434 main.log.error( self.name + ": " + self.handle.before )
andrewonlab9a50dfe2014-10-17 17:22:31 -04002435 main.cleanup()
2436 main.exit()
Jon Hallfebb1c72015-03-05 13:30:09 -08002437 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -08002438 main.log.exception( self.name + ": Uncaught exception!" )
andrewonlab9a50dfe2014-10-17 17:22:31 -04002439 main.cleanup()
2440 main.exit()
2441
Jon Hall30b82fa2015-03-04 17:15:43 -08002442 def FlowAddedCount( self, deviceId ):
2443 """
2444 Determine the number of flow rules for the given device id that are
2445 in the added state
2446 """
2447 try:
2448 cmdStr = "flows any " + str( deviceId ) + " | " +\
2449 "grep 'state=ADDED' | wc -l"
2450 handle = self.sendline( cmdStr )
Jon Hallc6793552016-01-19 14:18:37 -08002451 assert "Command not found:" not in handle, handle
Jon Hall30b82fa2015-03-04 17:15:43 -08002452 return handle
Jon Hallc6793552016-01-19 14:18:37 -08002453 except AssertionError:
2454 main.log.exception( "" )
2455 return None
Jon Hall30b82fa2015-03-04 17:15:43 -08002456 except pexpect.EOF:
2457 main.log.error( self.name + ": EOF exception found" )
2458 main.log.error( self.name + ": " + self.handle.before )
2459 main.cleanup()
2460 main.exit()
Jon Hallfebb1c72015-03-05 13:30:09 -08002461 except Exception:
Jon Hall30b82fa2015-03-04 17:15:43 -08002462 main.log.exception( self.name + ": Uncaught exception!" )
andrewonlab95ce8322014-10-13 14:12:04 -04002463 main.cleanup()
2464 main.exit()
2465
kelvin-onlabd3b64892015-01-20 13:26:24 -08002466 def getAllDevicesId( self ):
kelvin8ec71442015-01-15 16:57:00 -08002467 """
andrewonlab7e4d2d32014-10-15 13:23:21 -04002468 Use 'devices' function to obtain list of all devices
2469 and parse the result to obtain a list of all device
2470 id's. Returns this list. Returns empty list if no
2471 devices exist
kelvin8ec71442015-01-15 16:57:00 -08002472 List is ordered sequentially
2473
andrewonlab3e15ead2014-10-15 14:21:34 -04002474 This function may be useful if you are not sure of the
kelvin8ec71442015-01-15 16:57:00 -08002475 device id, and wish to execute other commands using
andrewonlab3e15ead2014-10-15 14:21:34 -04002476 the ids. By obtaining the list of device ids on the fly,
2477 you can iterate through the list to get mastership, etc.
kelvin8ec71442015-01-15 16:57:00 -08002478 """
andrewonlab7e4d2d32014-10-15 13:23:21 -04002479 try:
kelvin8ec71442015-01-15 16:57:00 -08002480 # Call devices and store result string
kelvin-onlabd3b64892015-01-20 13:26:24 -08002481 devicesStr = self.devices( jsonFormat=False )
2482 idList = []
kelvin8ec71442015-01-15 16:57:00 -08002483
kelvin-onlabd3b64892015-01-20 13:26:24 -08002484 if not devicesStr:
kelvin8ec71442015-01-15 16:57:00 -08002485 main.log.info( "There are no devices to get id from" )
kelvin-onlabd3b64892015-01-20 13:26:24 -08002486 return idList
kelvin8ec71442015-01-15 16:57:00 -08002487
2488 # Split the string into list by comma
kelvin-onlabd3b64892015-01-20 13:26:24 -08002489 deviceList = devicesStr.split( "," )
kelvin8ec71442015-01-15 16:57:00 -08002490 # Get temporary list of all arguments with string 'id='
kelvin-onlabd3b64892015-01-20 13:26:24 -08002491 tempList = [ dev for dev in deviceList if "id=" in dev ]
kelvin8ec71442015-01-15 16:57:00 -08002492 # Split list further into arguments before and after string
2493 # 'id='. Get the latter portion ( the actual device id ) and
kelvin-onlabd3b64892015-01-20 13:26:24 -08002494 # append to idList
2495 for arg in tempList:
2496 idList.append( arg.split( "id=" )[ 1 ] )
2497 return idList
andrewonlab7e4d2d32014-10-15 13:23:21 -04002498
Jon Halld4d4b372015-01-28 16:02:41 -08002499 except TypeError:
2500 main.log.exception( self.name + ": Object not as expected" )
2501 return None
andrewonlab7e4d2d32014-10-15 13:23:21 -04002502 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08002503 main.log.error( self.name + ": EOF exception found" )
2504 main.log.error( self.name + ": " + self.handle.before )
andrewonlab7e4d2d32014-10-15 13:23:21 -04002505 main.cleanup()
2506 main.exit()
Jon Hallfebb1c72015-03-05 13:30:09 -08002507 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -08002508 main.log.exception( self.name + ": Uncaught exception!" )
andrewonlab7e4d2d32014-10-15 13:23:21 -04002509 main.cleanup()
2510 main.exit()
2511
kelvin-onlabd3b64892015-01-20 13:26:24 -08002512 def getAllNodesId( self ):
kelvin8ec71442015-01-15 16:57:00 -08002513 """
andrewonlab7c211572014-10-15 16:45:20 -04002514 Uses 'nodes' function to obtain list of all nodes
2515 and parse the result of nodes to obtain just the
kelvin8ec71442015-01-15 16:57:00 -08002516 node id's.
andrewonlab7c211572014-10-15 16:45:20 -04002517 Returns:
2518 list of node id's
kelvin8ec71442015-01-15 16:57:00 -08002519 """
andrewonlab7c211572014-10-15 16:45:20 -04002520 try:
Jon Hall5aa168b2015-03-23 14:23:09 -07002521 nodesStr = self.nodes( jsonFormat=True )
kelvin-onlabd3b64892015-01-20 13:26:24 -08002522 idList = []
Jon Hall5aa168b2015-03-23 14:23:09 -07002523 # Sample nodesStr output
Jon Hallbd182782016-03-28 16:42:22 -07002524 # id=local, address=127.0.0.1:9876, state=READY *
kelvin-onlabd3b64892015-01-20 13:26:24 -08002525 if not nodesStr:
kelvin8ec71442015-01-15 16:57:00 -08002526 main.log.info( "There are no nodes to get id from" )
kelvin-onlabd3b64892015-01-20 13:26:24 -08002527 return idList
Jon Hall5aa168b2015-03-23 14:23:09 -07002528 nodesJson = json.loads( nodesStr )
2529 idList = [ node.get('id') for node in nodesJson ]
kelvin-onlabd3b64892015-01-20 13:26:24 -08002530 return idList
Jon Hallc6793552016-01-19 14:18:37 -08002531 except ( TypeError, ValueError ):
2532 main.log.exception( "{}: Object not as expected: {!r}".format( self.name, nodesStr ) )
Jon Halld4d4b372015-01-28 16:02:41 -08002533 return None
andrewonlab7c211572014-10-15 16:45:20 -04002534 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08002535 main.log.error( self.name + ": EOF exception found" )
2536 main.log.error( self.name + ": " + self.handle.before )
andrewonlab7c211572014-10-15 16:45:20 -04002537 main.cleanup()
2538 main.exit()
Jon Hallfebb1c72015-03-05 13:30:09 -08002539 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -08002540 main.log.exception( self.name + ": Uncaught exception!" )
andrewonlab7c211572014-10-15 16:45:20 -04002541 main.cleanup()
2542 main.exit()
andrewonlab7e4d2d32014-10-15 13:23:21 -04002543
kelvin-onlabd3b64892015-01-20 13:26:24 -08002544 def getDevice( self, dpid=None ):
kelvin8ec71442015-01-15 16:57:00 -08002545 """
Jon Halla91c4dc2014-10-22 12:57:04 -04002546 Return the first device from the devices api whose 'id' contains 'dpid'
2547 Return None if there is no match
kelvin8ec71442015-01-15 16:57:00 -08002548 """
Jon Halla91c4dc2014-10-22 12:57:04 -04002549 try:
kelvin8ec71442015-01-15 16:57:00 -08002550 if dpid is None:
Jon Halla91c4dc2014-10-22 12:57:04 -04002551 return None
2552 else:
kelvin8ec71442015-01-15 16:57:00 -08002553 dpid = dpid.replace( ':', '' )
kelvin-onlabd3b64892015-01-20 13:26:24 -08002554 rawDevices = self.devices()
2555 devicesJson = json.loads( rawDevices )
kelvin8ec71442015-01-15 16:57:00 -08002556 # search json for the device with dpid then return the device
kelvin-onlabd3b64892015-01-20 13:26:24 -08002557 for device in devicesJson:
kelvin8ec71442015-01-15 16:57:00 -08002558 # print "%s in %s?" % ( dpid, device[ 'id' ] )
2559 if dpid in device[ 'id' ]:
Jon Halla91c4dc2014-10-22 12:57:04 -04002560 return device
2561 return None
Jon Hallc6793552016-01-19 14:18:37 -08002562 except ( TypeError, ValueError ):
2563 main.log.exception( "{}: Object not as expected: {!r}".format( self.name, rawDevices ) )
Jon Halld4d4b372015-01-28 16:02:41 -08002564 return None
Jon Halla91c4dc2014-10-22 12:57:04 -04002565 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08002566 main.log.error( self.name + ": EOF exception found" )
2567 main.log.error( self.name + ": " + self.handle.before )
Jon Halla91c4dc2014-10-22 12:57:04 -04002568 main.cleanup()
2569 main.exit()
Jon Hallfebb1c72015-03-05 13:30:09 -08002570 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -08002571 main.log.exception( self.name + ": Uncaught exception!" )
Jon Halla91c4dc2014-10-22 12:57:04 -04002572 main.cleanup()
2573 main.exit()
2574
kelvin-onlabd3b64892015-01-20 13:26:24 -08002575 def checkStatus( self, ip, numoswitch, numolink, logLevel="info" ):
kelvin8ec71442015-01-15 16:57:00 -08002576 """
Jon Hallefbd9792015-03-05 16:11:36 -08002577 Checks the number of switches & links that ONOS sees against the
kelvin8ec71442015-01-15 16:57:00 -08002578 supplied values. By default this will report to main.log, but the
Jon Hallefbd9792015-03-05 16:11:36 -08002579 log level can be specified.
kelvin8ec71442015-01-15 16:57:00 -08002580
Jon Hall42db6dc2014-10-24 19:03:48 -04002581 Params: ip = ip used for the onos cli
2582 numoswitch = expected number of switches
Jon Hallefbd9792015-03-05 16:11:36 -08002583 numolink = expected number of links
kelvin-onlabd3b64892015-01-20 13:26:24 -08002584 logLevel = level to log to. Currently accepts
2585 'info', 'warn' and 'report'
Jon Hall42db6dc2014-10-24 19:03:48 -04002586
2587
kelvin-onlabd3b64892015-01-20 13:26:24 -08002588 logLevel can
Jon Hall42db6dc2014-10-24 19:03:48 -04002589
Jon Hallefbd9792015-03-05 16:11:36 -08002590 Returns: main.TRUE if the number of switches and links are correct,
2591 main.FALSE if the number of switches and links is incorrect,
Jon Hall42db6dc2014-10-24 19:03:48 -04002592 and main.ERROR otherwise
kelvin8ec71442015-01-15 16:57:00 -08002593 """
Jon Hall42db6dc2014-10-24 19:03:48 -04002594 try:
kelvin-onlabd3b64892015-01-20 13:26:24 -08002595 topology = self.getTopology( ip )
Jon Hall42db6dc2014-10-24 19:03:48 -04002596 if topology == {}:
2597 return main.ERROR
2598 output = ""
kelvin8ec71442015-01-15 16:57:00 -08002599 # Is the number of switches is what we expected
2600 devices = topology.get( 'devices', False )
2601 links = topology.get( 'links', False )
kelvin-onlabfb521662015-02-27 09:52:40 -08002602 if devices is False or links is False:
Jon Hall42db6dc2014-10-24 19:03:48 -04002603 return main.ERROR
kelvin-onlabd3b64892015-01-20 13:26:24 -08002604 switchCheck = ( int( devices ) == int( numoswitch ) )
kelvin8ec71442015-01-15 16:57:00 -08002605 # Is the number of links is what we expected
kelvin-onlabd3b64892015-01-20 13:26:24 -08002606 linkCheck = ( int( links ) == int( numolink ) )
2607 if ( switchCheck and linkCheck ):
kelvin8ec71442015-01-15 16:57:00 -08002608 # We expected the correct numbers
Jon Hallefbd9792015-03-05 16:11:36 -08002609 output += "The number of links and switches match " +\
2610 "what was expected"
Jon Hall42db6dc2014-10-24 19:03:48 -04002611 result = main.TRUE
2612 else:
Jon Hallefbd9792015-03-05 16:11:36 -08002613 output += "The number of links and switches does not match " +\
2614 "what was expected"
Jon Hall42db6dc2014-10-24 19:03:48 -04002615 result = main.FALSE
kelvin-onlabd3b64892015-01-20 13:26:24 -08002616 output = output + "\n ONOS sees %i devices (%i expected) \
2617 and %i links (%i expected)" % (
2618 int( devices ), int( numoswitch ), int( links ),
2619 int( numolink ) )
2620 if logLevel == "report":
kelvin8ec71442015-01-15 16:57:00 -08002621 main.log.report( output )
kelvin-onlabd3b64892015-01-20 13:26:24 -08002622 elif logLevel == "warn":
kelvin8ec71442015-01-15 16:57:00 -08002623 main.log.warn( output )
Jon Hall42db6dc2014-10-24 19:03:48 -04002624 else:
Jon Hall390696c2015-05-05 17:13:41 -07002625 main.log.info( self.name + ": " + output )
kelvin8ec71442015-01-15 16:57:00 -08002626 return result
Jon Halld4d4b372015-01-28 16:02:41 -08002627 except TypeError:
2628 main.log.exception( self.name + ": Object not as expected" )
2629 return None
Jon Hall42db6dc2014-10-24 19:03:48 -04002630 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08002631 main.log.error( self.name + ": EOF exception found" )
2632 main.log.error( self.name + ": " + self.handle.before )
Jon Hall42db6dc2014-10-24 19:03:48 -04002633 main.cleanup()
2634 main.exit()
Jon Hallfebb1c72015-03-05 13:30:09 -08002635 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -08002636 main.log.exception( self.name + ": Uncaught exception!" )
Jon Hall42db6dc2014-10-24 19:03:48 -04002637 main.cleanup()
2638 main.exit()
Jon Hall1c9e8732014-10-27 19:29:27 -04002639
kelvin-onlabd3b64892015-01-20 13:26:24 -08002640 def deviceRole( self, deviceId, onosNode, role="master" ):
kelvin8ec71442015-01-15 16:57:00 -08002641 """
Jon Hall1c9e8732014-10-27 19:29:27 -04002642 Calls the device-role cli command.
kelvin-onlabd3b64892015-01-20 13:26:24 -08002643 deviceId must be the id of a device as seen in the onos devices command
2644 onosNode is the ip of one of the onos nodes in the cluster
Jon Hall1c9e8732014-10-27 19:29:27 -04002645 role must be either master, standby, or none
2646
Jon Halle3f39ff2015-01-13 11:50:53 -08002647 Returns:
2648 main.TRUE or main.FALSE based on argument verification and
2649 main.ERROR if command returns and error
kelvin-onlab898a6c62015-01-16 14:13:53 -08002650 """
Jon Hall1c9e8732014-10-27 19:29:27 -04002651 try:
Jon Halle3f39ff2015-01-13 11:50:53 -08002652 if role.lower() == "master" or role.lower() == "standby" or\
Jon Hall1c9e8732014-10-27 19:29:27 -04002653 role.lower() == "none":
kelvin-onlabd3b64892015-01-20 13:26:24 -08002654 cmdStr = "device-role " +\
2655 str( deviceId ) + " " +\
2656 str( onosNode ) + " " +\
kelvin-onlab898a6c62015-01-16 14:13:53 -08002657 str( role )
kelvin-onlabd3b64892015-01-20 13:26:24 -08002658 handle = self.sendline( cmdStr )
Jon Hallc6793552016-01-19 14:18:37 -08002659 assert "Command not found:" not in handle, handle
kelvin-onlab898a6c62015-01-16 14:13:53 -08002660 if re.search( "Error", handle ):
2661 # end color output to escape any colours
2662 # from the cli
kelvin8ec71442015-01-15 16:57:00 -08002663 main.log.error( self.name + ": " +
kelvin-onlab898a6c62015-01-16 14:13:53 -08002664 handle + '\033[0m' )
kelvin8ec71442015-01-15 16:57:00 -08002665 return main.ERROR
kelvin8ec71442015-01-15 16:57:00 -08002666 return main.TRUE
Jon Hall1c9e8732014-10-27 19:29:27 -04002667 else:
kelvin-onlab898a6c62015-01-16 14:13:53 -08002668 main.log.error( "Invalid 'role' given to device_role(). " +
2669 "Value was '" + str(role) + "'." )
Jon Hall1c9e8732014-10-27 19:29:27 -04002670 return main.FALSE
Jon Hallc6793552016-01-19 14:18:37 -08002671 except AssertionError:
2672 main.log.exception( "" )
2673 return None
Jon Halld4d4b372015-01-28 16:02:41 -08002674 except TypeError:
2675 main.log.exception( self.name + ": Object not as expected" )
2676 return None
Jon Hall1c9e8732014-10-27 19:29:27 -04002677 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08002678 main.log.error( self.name + ": EOF exception found" )
2679 main.log.error( self.name + ": " + self.handle.before )
Jon Hall1c9e8732014-10-27 19:29:27 -04002680 main.cleanup()
2681 main.exit()
Jon Hallfebb1c72015-03-05 13:30:09 -08002682 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -08002683 main.log.exception( self.name + ": Uncaught exception!" )
Jon Hall1c9e8732014-10-27 19:29:27 -04002684 main.cleanup()
2685 main.exit()
2686
kelvin-onlabd3b64892015-01-20 13:26:24 -08002687 def clusters( self, jsonFormat=True ):
kelvin8ec71442015-01-15 16:57:00 -08002688 """
Jon Hall73cf9cc2014-11-20 22:28:38 -08002689 Lists all clusters
Jon Hallffb386d2014-11-21 13:43:38 -08002690 Optional argument:
kelvin-onlabd3b64892015-01-20 13:26:24 -08002691 * jsonFormat - boolean indicating if you want output in json
kelvin8ec71442015-01-15 16:57:00 -08002692 """
Jon Hall73cf9cc2014-11-20 22:28:38 -08002693 try:
Jon Hallc6358dd2015-04-10 12:44:28 -07002694 cmdStr = "clusters"
kelvin-onlabd3b64892015-01-20 13:26:24 -08002695 if jsonFormat:
Jon Hallc6358dd2015-04-10 12:44:28 -07002696 cmdStr += " -j"
2697 handle = self.sendline( cmdStr )
Jon Hallc6793552016-01-19 14:18:37 -08002698 assert "Command not found:" not in handle, handle
Jon Hallc6358dd2015-04-10 12:44:28 -07002699 return handle
Jon Hallc6793552016-01-19 14:18:37 -08002700 except AssertionError:
2701 main.log.exception( "" )
2702 return None
Jon Halld4d4b372015-01-28 16:02:41 -08002703 except TypeError:
2704 main.log.exception( self.name + ": Object not as expected" )
2705 return None
Jon Hall73cf9cc2014-11-20 22:28:38 -08002706 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08002707 main.log.error( self.name + ": EOF exception found" )
2708 main.log.error( self.name + ": " + self.handle.before )
Jon Hall73cf9cc2014-11-20 22:28:38 -08002709 main.cleanup()
2710 main.exit()
Jon Hallfebb1c72015-03-05 13:30:09 -08002711 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -08002712 main.log.exception( self.name + ": Uncaught exception!" )
Jon Hall73cf9cc2014-11-20 22:28:38 -08002713 main.cleanup()
2714 main.exit()
2715
kelvin-onlabd3b64892015-01-20 13:26:24 -08002716 def electionTestLeader( self ):
kelvin-onlab898a6c62015-01-16 14:13:53 -08002717 """
Jon Halle3f39ff2015-01-13 11:50:53 -08002718 CLI command to get the current leader for the Election test application
2719 NOTE: Requires installation of the onos-app-election feature
2720 Returns: Node IP of the leader if one exists
2721 None if none exists
2722 Main.FALSE on error
kelvin-onlab898a6c62015-01-16 14:13:53 -08002723 """
Jon Hall94fd0472014-12-08 11:52:42 -08002724 try:
kelvin-onlabd3b64892015-01-20 13:26:24 -08002725 cmdStr = "election-test-leader"
2726 response = self.sendline( cmdStr )
Jon Hallc6793552016-01-19 14:18:37 -08002727 assert "Command not found:" not in response, response
Jon Halle3f39ff2015-01-13 11:50:53 -08002728 # Leader
2729 leaderPattern = "The\scurrent\sleader\sfor\sthe\sElection\s" +\
kelvin-onlab898a6c62015-01-16 14:13:53 -08002730 "app\sis\s(?P<node>.+)\."
kelvin-onlabd3b64892015-01-20 13:26:24 -08002731 nodeSearch = re.search( leaderPattern, response )
2732 if nodeSearch:
2733 node = nodeSearch.group( 'node' )
Jon Halle3f39ff2015-01-13 11:50:53 -08002734 main.log.info( "Election-test-leader on " + str( self.name ) +
kelvin-onlab898a6c62015-01-16 14:13:53 -08002735 " found " + node + " as the leader" )
Jon Hall94fd0472014-12-08 11:52:42 -08002736 return node
Jon Halle3f39ff2015-01-13 11:50:53 -08002737 # no leader
2738 nullPattern = "There\sis\scurrently\sno\sleader\selected\sfor\s" +\
kelvin-onlab898a6c62015-01-16 14:13:53 -08002739 "the\sElection\sapp"
kelvin-onlabd3b64892015-01-20 13:26:24 -08002740 nullSearch = re.search( nullPattern, response )
2741 if nullSearch:
Jon Halle3f39ff2015-01-13 11:50:53 -08002742 main.log.info( "Election-test-leader found no leader on " +
kelvin-onlab898a6c62015-01-16 14:13:53 -08002743 self.name )
Jon Hall94fd0472014-12-08 11:52:42 -08002744 return None
kelvin-onlab898a6c62015-01-16 14:13:53 -08002745 # error
Jon Halle3f39ff2015-01-13 11:50:53 -08002746 errorPattern = "Command\snot\sfound"
kelvin-onlab898a6c62015-01-16 14:13:53 -08002747 if re.search( errorPattern, response ):
2748 main.log.error( "Election app is not loaded on " + self.name )
Jon Halle3f39ff2015-01-13 11:50:53 -08002749 # TODO: Should this be main.ERROR?
Jon Hall669173b2014-12-17 11:36:30 -08002750 return main.FALSE
2751 else:
Jon Hall390696c2015-05-05 17:13:41 -07002752 main.log.error( "Error in electionTestLeader on " + self.name +
2753 ": " + "unexpected response" )
kelvin8ec71442015-01-15 16:57:00 -08002754 main.log.error( repr( response ) )
Jon Hall669173b2014-12-17 11:36:30 -08002755 return main.FALSE
Jon Hallc6793552016-01-19 14:18:37 -08002756 except AssertionError:
2757 main.log.exception( "" )
2758 return None
Jon Halld4d4b372015-01-28 16:02:41 -08002759 except TypeError:
2760 main.log.exception( self.name + ": Object not as expected" )
2761 return main.FALSE
Jon Hall94fd0472014-12-08 11:52:42 -08002762 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08002763 main.log.error( self.name + ": EOF exception found" )
2764 main.log.error( self.name + ": " + self.handle.before )
Jon Hall94fd0472014-12-08 11:52:42 -08002765 main.cleanup()
2766 main.exit()
Jon Hallfebb1c72015-03-05 13:30:09 -08002767 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -08002768 main.log.exception( self.name + ": Uncaught exception!" )
Jon Hall94fd0472014-12-08 11:52:42 -08002769 main.cleanup()
2770 main.exit()
2771
kelvin-onlabd3b64892015-01-20 13:26:24 -08002772 def electionTestRun( self ):
kelvin-onlab898a6c62015-01-16 14:13:53 -08002773 """
Jon Halle3f39ff2015-01-13 11:50:53 -08002774 CLI command to run for leadership of the Election test application.
2775 NOTE: Requires installation of the onos-app-election feature
2776 Returns: Main.TRUE on success
2777 Main.FALSE on error
kelvin-onlab898a6c62015-01-16 14:13:53 -08002778 """
Jon Hall94fd0472014-12-08 11:52:42 -08002779 try:
kelvin-onlabd3b64892015-01-20 13:26:24 -08002780 cmdStr = "election-test-run"
2781 response = self.sendline( cmdStr )
Jon Hallc6793552016-01-19 14:18:37 -08002782 assert "Command not found:" not in response, response
kelvin-onlab898a6c62015-01-16 14:13:53 -08002783 # success
Jon Halle3f39ff2015-01-13 11:50:53 -08002784 successPattern = "Entering\sleadership\selections\sfor\sthe\s" +\
kelvin-onlab898a6c62015-01-16 14:13:53 -08002785 "Election\sapp."
Jon Halle3f39ff2015-01-13 11:50:53 -08002786 search = re.search( successPattern, response )
Jon Hall94fd0472014-12-08 11:52:42 -08002787 if search:
Jon Halle3f39ff2015-01-13 11:50:53 -08002788 main.log.info( self.name + " entering leadership elections " +
kelvin-onlab898a6c62015-01-16 14:13:53 -08002789 "for the Election app." )
Jon Hall94fd0472014-12-08 11:52:42 -08002790 return main.TRUE
kelvin-onlab898a6c62015-01-16 14:13:53 -08002791 # error
Jon Halle3f39ff2015-01-13 11:50:53 -08002792 errorPattern = "Command\snot\sfound"
2793 if re.search( errorPattern, response ):
2794 main.log.error( "Election app is not loaded on " + self.name )
Jon Hall669173b2014-12-17 11:36:30 -08002795 return main.FALSE
2796 else:
Jon Hall390696c2015-05-05 17:13:41 -07002797 main.log.error( "Error in electionTestRun on " + self.name +
2798 ": " + "unexpected response" )
Jon Halle3f39ff2015-01-13 11:50:53 -08002799 main.log.error( repr( response ) )
Jon Hall669173b2014-12-17 11:36:30 -08002800 return main.FALSE
Jon Hallc6793552016-01-19 14:18:37 -08002801 except AssertionError:
2802 main.log.exception( "" )
2803 return None
Jon Halld4d4b372015-01-28 16:02:41 -08002804 except TypeError:
2805 main.log.exception( self.name + ": Object not as expected" )
2806 return main.FALSE
Jon Hall94fd0472014-12-08 11:52:42 -08002807 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08002808 main.log.error( self.name + ": EOF exception found" )
2809 main.log.error( self.name + ": " + self.handle.before )
Jon Hall94fd0472014-12-08 11:52:42 -08002810 main.cleanup()
2811 main.exit()
Jon Hallfebb1c72015-03-05 13:30:09 -08002812 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -08002813 main.log.exception( self.name + ": Uncaught exception!" )
Jon Hall94fd0472014-12-08 11:52:42 -08002814 main.cleanup()
2815 main.exit()
2816
kelvin-onlabd3b64892015-01-20 13:26:24 -08002817 def electionTestWithdraw( self ):
kelvin8ec71442015-01-15 16:57:00 -08002818 """
Jon Hall94fd0472014-12-08 11:52:42 -08002819 * CLI command to withdraw the local node from leadership election for
2820 * the Election test application.
2821 #NOTE: Requires installation of the onos-app-election feature
2822 Returns: Main.TRUE on success
2823 Main.FALSE on error
kelvin8ec71442015-01-15 16:57:00 -08002824 """
Jon Hall94fd0472014-12-08 11:52:42 -08002825 try:
kelvin-onlabd3b64892015-01-20 13:26:24 -08002826 cmdStr = "election-test-withdraw"
2827 response = self.sendline( cmdStr )
Jon Hallc6793552016-01-19 14:18:37 -08002828 assert "Command not found:" not in response, response
kelvin-onlab898a6c62015-01-16 14:13:53 -08002829 # success
Jon Halle3f39ff2015-01-13 11:50:53 -08002830 successPattern = "Withdrawing\sfrom\sleadership\selections\sfor" +\
kelvin-onlab898a6c62015-01-16 14:13:53 -08002831 "\sthe\sElection\sapp."
Jon Halle3f39ff2015-01-13 11:50:53 -08002832 if re.search( successPattern, response ):
2833 main.log.info( self.name + " withdrawing from leadership " +
kelvin-onlab898a6c62015-01-16 14:13:53 -08002834 "elections for the Election app." )
Jon Hall94fd0472014-12-08 11:52:42 -08002835 return main.TRUE
kelvin-onlab898a6c62015-01-16 14:13:53 -08002836 # error
Jon Halle3f39ff2015-01-13 11:50:53 -08002837 errorPattern = "Command\snot\sfound"
2838 if re.search( errorPattern, response ):
2839 main.log.error( "Election app is not loaded on " + self.name )
Jon Hall669173b2014-12-17 11:36:30 -08002840 return main.FALSE
2841 else:
Jon Hall390696c2015-05-05 17:13:41 -07002842 main.log.error( "Error in electionTestWithdraw on " +
2843 self.name + ": " + "unexpected response" )
Jon Halle3f39ff2015-01-13 11:50:53 -08002844 main.log.error( repr( response ) )
Jon Hall669173b2014-12-17 11:36:30 -08002845 return main.FALSE
Jon Hallc6793552016-01-19 14:18:37 -08002846 except AssertionError:
2847 main.log.exception( "" )
2848 return None
Jon Halld4d4b372015-01-28 16:02:41 -08002849 except TypeError:
2850 main.log.exception( self.name + ": Object not as expected" )
2851 return main.FALSE
Jon Hall94fd0472014-12-08 11:52:42 -08002852 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08002853 main.log.error( self.name + ": EOF exception found" )
2854 main.log.error( self.name + ": " + self.handle.before )
Jon Hall94fd0472014-12-08 11:52:42 -08002855 main.cleanup()
2856 main.exit()
Jon Hallfebb1c72015-03-05 13:30:09 -08002857 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -08002858 main.log.exception( self.name + ": Uncaught exception!" )
Jon Hall94fd0472014-12-08 11:52:42 -08002859 main.cleanup()
2860 main.exit()
Jon Hall1c9e8732014-10-27 19:29:27 -04002861
kelvin8ec71442015-01-15 16:57:00 -08002862 def getDevicePortsEnabledCount( self, dpid ):
2863 """
Hari Krishnaa43d4e92014-12-19 13:22:40 -08002864 Get the count of all enabled ports on a particular device/switch
kelvin8ec71442015-01-15 16:57:00 -08002865 """
Hari Krishnaa43d4e92014-12-19 13:22:40 -08002866 try:
Jon Halle3f39ff2015-01-13 11:50:53 -08002867 dpid = str( dpid )
kelvin-onlabd3b64892015-01-20 13:26:24 -08002868 cmdStr = "onos:ports -e " + dpid + " | wc -l"
2869 output = self.sendline( cmdStr )
Jon Hallc6793552016-01-19 14:18:37 -08002870 assert "Command not found:" not in output, output
Jon Halle3f39ff2015-01-13 11:50:53 -08002871 if re.search( "No such device", output ):
2872 main.log.error( "Error in getting ports" )
2873 return ( output, "Error" )
Hari Krishnaa43d4e92014-12-19 13:22:40 -08002874 else:
Jon Halle3f39ff2015-01-13 11:50:53 -08002875 return output
Jon Hallc6793552016-01-19 14:18:37 -08002876 except AssertionError:
2877 main.log.exception( "" )
2878 return None
Jon Halld4d4b372015-01-28 16:02:41 -08002879 except TypeError:
2880 main.log.exception( self.name + ": Object not as expected" )
2881 return ( output, "Error" )
Hari Krishnaa43d4e92014-12-19 13:22:40 -08002882 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08002883 main.log.error( self.name + ": EOF exception found" )
2884 main.log.error( self.name + ": " + self.handle.before )
Hari Krishnaa43d4e92014-12-19 13:22:40 -08002885 main.cleanup()
2886 main.exit()
Jon Hallfebb1c72015-03-05 13:30:09 -08002887 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -08002888 main.log.exception( self.name + ": Uncaught exception!" )
Hari Krishnaa43d4e92014-12-19 13:22:40 -08002889 main.cleanup()
2890 main.exit()
2891
kelvin8ec71442015-01-15 16:57:00 -08002892 def getDeviceLinksActiveCount( self, dpid ):
2893 """
Hari Krishnaa43d4e92014-12-19 13:22:40 -08002894 Get the count of all enabled ports on a particular device/switch
kelvin8ec71442015-01-15 16:57:00 -08002895 """
Hari Krishnaa43d4e92014-12-19 13:22:40 -08002896 try:
kelvin-onlab898a6c62015-01-16 14:13:53 -08002897 dpid = str( dpid )
kelvin-onlabd3b64892015-01-20 13:26:24 -08002898 cmdStr = "onos:links " + dpid + " | grep ACTIVE | wc -l"
2899 output = self.sendline( cmdStr )
Jon Hallc6793552016-01-19 14:18:37 -08002900 assert "Command not found:" not in output, output
Jon Halle3f39ff2015-01-13 11:50:53 -08002901 if re.search( "No such device", output ):
kelvin-onlab898a6c62015-01-16 14:13:53 -08002902 main.log.error( "Error in getting ports " )
2903 return ( output, "Error " )
Hari Krishnaa43d4e92014-12-19 13:22:40 -08002904 else:
Jon Halle3f39ff2015-01-13 11:50:53 -08002905 return output
Jon Hallc6793552016-01-19 14:18:37 -08002906 except AssertionError:
2907 main.log.exception( "" )
2908 return None
Jon Halld4d4b372015-01-28 16:02:41 -08002909 except TypeError:
2910 main.log.exception( self.name + ": Object not as expected" )
2911 return ( output, "Error " )
Hari Krishnaa43d4e92014-12-19 13:22:40 -08002912 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08002913 main.log.error( self.name + ": EOF exception found" )
2914 main.log.error( self.name + ": " + self.handle.before )
Hari Krishnaa43d4e92014-12-19 13:22:40 -08002915 main.cleanup()
2916 main.exit()
Jon Hallfebb1c72015-03-05 13:30:09 -08002917 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -08002918 main.log.exception( self.name + ": Uncaught exception!" )
Hari Krishnaa43d4e92014-12-19 13:22:40 -08002919 main.cleanup()
2920 main.exit()
2921
kelvin8ec71442015-01-15 16:57:00 -08002922 def getAllIntentIds( self ):
2923 """
Hari Krishnaa43d4e92014-12-19 13:22:40 -08002924 Return a list of all Intent IDs
kelvin8ec71442015-01-15 16:57:00 -08002925 """
Hari Krishnaa43d4e92014-12-19 13:22:40 -08002926 try:
kelvin-onlabd3b64892015-01-20 13:26:24 -08002927 cmdStr = "onos:intents | grep id="
2928 output = self.sendline( cmdStr )
Jon Hallc6793552016-01-19 14:18:37 -08002929 assert "Command not found:" not in output, output
Jon Halle3f39ff2015-01-13 11:50:53 -08002930 if re.search( "Error", output ):
2931 main.log.error( "Error in getting ports" )
2932 return ( output, "Error" )
Hari Krishnaa43d4e92014-12-19 13:22:40 -08002933 else:
Jon Halle3f39ff2015-01-13 11:50:53 -08002934 return output
Jon Hallc6793552016-01-19 14:18:37 -08002935 except AssertionError:
2936 main.log.exception( "" )
2937 return None
Jon Halld4d4b372015-01-28 16:02:41 -08002938 except TypeError:
2939 main.log.exception( self.name + ": Object not as expected" )
2940 return ( output, "Error" )
Hari Krishnaa43d4e92014-12-19 13:22:40 -08002941 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08002942 main.log.error( self.name + ": EOF exception found" )
2943 main.log.error( self.name + ": " + self.handle.before )
Hari Krishnaa43d4e92014-12-19 13:22:40 -08002944 main.cleanup()
2945 main.exit()
Jon Hallfebb1c72015-03-05 13:30:09 -08002946 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -08002947 main.log.exception( self.name + ": Uncaught exception!" )
2948 main.cleanup()
2949 main.exit()
2950
Jon Hall73509952015-02-24 16:42:56 -08002951 def intentSummary( self ):
2952 """
Jon Hallefbd9792015-03-05 16:11:36 -08002953 Returns a dictionary containing the current intent states and the count
Jon Hall73509952015-02-24 16:42:56 -08002954 """
2955 try:
2956 intents = self.intents( )
Jon Hall08f61bc2015-04-13 16:00:30 -07002957 states = []
Jon Hall5aa168b2015-03-23 14:23:09 -07002958 for intent in json.loads( intents ):
Jon Hall08f61bc2015-04-13 16:00:30 -07002959 states.append( intent.get( 'state', None ) )
2960 out = [ ( i, states.count( i ) ) for i in set( states ) ]
Jon Hall63604932015-02-26 17:09:50 -08002961 main.log.info( dict( out ) )
Jon Hall73509952015-02-24 16:42:56 -08002962 return dict( out )
Jon Hallc6793552016-01-19 14:18:37 -08002963 except ( TypeError, ValueError ):
2964 main.log.exception( "{}: Object not as expected: {!r}".format( self.name, intents ) )
Jon Hall73509952015-02-24 16:42:56 -08002965 return None
2966 except pexpect.EOF:
2967 main.log.error( self.name + ": EOF exception found" )
2968 main.log.error( self.name + ": " + self.handle.before )
2969 main.cleanup()
2970 main.exit()
Jon Hallfebb1c72015-03-05 13:30:09 -08002971 except Exception:
Jon Hall73509952015-02-24 16:42:56 -08002972 main.log.exception( self.name + ": Uncaught exception!" )
2973 main.cleanup()
2974 main.exit()
Jon Hall63604932015-02-26 17:09:50 -08002975
Jon Hall61282e32015-03-19 11:34:11 -07002976 def leaders( self, jsonFormat=True ):
Jon Hall63604932015-02-26 17:09:50 -08002977 """
2978 Returns the output of the leaders command.
Jon Hall61282e32015-03-19 11:34:11 -07002979 Optional argument:
2980 * jsonFormat - boolean indicating if you want output in json
Jon Hall63604932015-02-26 17:09:50 -08002981 """
Jon Hall63604932015-02-26 17:09:50 -08002982 try:
Jon Hallc6358dd2015-04-10 12:44:28 -07002983 cmdStr = "onos:leaders"
Jon Hall61282e32015-03-19 11:34:11 -07002984 if jsonFormat:
Jon Hallc6358dd2015-04-10 12:44:28 -07002985 cmdStr += " -j"
2986 output = self.sendline( cmdStr )
Jon Hallc6793552016-01-19 14:18:37 -08002987 assert "Command not found:" not in output, output
Jon Hallc6358dd2015-04-10 12:44:28 -07002988 return output
Jon Hallc6793552016-01-19 14:18:37 -08002989 except AssertionError:
2990 main.log.exception( "" )
2991 return None
Jon Hall63604932015-02-26 17:09:50 -08002992 except TypeError:
2993 main.log.exception( self.name + ": Object not as expected" )
2994 return None
Hari Krishnaa43d4e92014-12-19 13:22:40 -08002995 except pexpect.EOF:
2996 main.log.error( self.name + ": EOF exception found" )
2997 main.log.error( self.name + ": " + self.handle.before )
2998 main.cleanup()
2999 main.exit()
Jon Hall77ba41c2015-04-06 10:25:40 -07003000 except Exception:
Jon Hall63604932015-02-26 17:09:50 -08003001 main.log.exception( self.name + ": Uncaught exception!" )
Hari Krishnaa43d4e92014-12-19 13:22:40 -08003002 main.cleanup()
3003 main.exit()
Jon Hall63604932015-02-26 17:09:50 -08003004
acsmarsa4a4d1e2015-07-10 16:01:24 -07003005 def leaderCandidates( self, jsonFormat=True ):
3006 """
3007 Returns the output of the leaders -c command.
3008 Optional argument:
3009 * jsonFormat - boolean indicating if you want output in json
3010 """
3011 try:
3012 cmdStr = "onos:leaders -c"
3013 if jsonFormat:
3014 cmdStr += " -j"
3015 output = self.sendline( cmdStr )
Jon Hallc6793552016-01-19 14:18:37 -08003016 assert "Command not found:" not in output, output
acsmarsa4a4d1e2015-07-10 16:01:24 -07003017 return output
Jon Hallc6793552016-01-19 14:18:37 -08003018 except AssertionError:
3019 main.log.exception( "" )
3020 return None
acsmarsa4a4d1e2015-07-10 16:01:24 -07003021 except TypeError:
3022 main.log.exception( self.name + ": Object not as expected" )
3023 return None
3024 except pexpect.EOF:
3025 main.log.error( self.name + ": EOF exception found" )
3026 main.log.error( self.name + ": " + self.handle.before )
3027 main.cleanup()
3028 main.exit()
3029 except Exception:
3030 main.log.exception( self.name + ": Uncaught exception!" )
3031 main.cleanup()
3032 main.exit()
3033
Jon Hallc6793552016-01-19 14:18:37 -08003034 def specificLeaderCandidate( self, topic ):
acsmarsa4a4d1e2015-07-10 16:01:24 -07003035 """
3036 Returns a list in format [leader,candidate1,candidate2,...] for a given
3037 topic parameter and an empty list if the topic doesn't exist
3038 If no leader is elected leader in the returned list will be "none"
3039 Returns None if there is a type error processing the json object
3040 """
3041 try:
Jon Hall6e709752016-02-01 13:38:46 -08003042 cmdStr = "onos:leaders -j"
Jon Hallc6793552016-01-19 14:18:37 -08003043 rawOutput = self.sendline( cmdStr )
3044 assert "Command not found:" not in rawOutput, rawOutput
3045 output = json.loads( rawOutput )
acsmarsa4a4d1e2015-07-10 16:01:24 -07003046 results = []
3047 for dict in output:
3048 if dict["topic"] == topic:
3049 leader = dict["leader"]
Jon Hallc6793552016-01-19 14:18:37 -08003050 candidates = re.split( ", ", dict["candidates"][1:-1] )
3051 results.append( leader )
3052 results.extend( candidates )
acsmarsa4a4d1e2015-07-10 16:01:24 -07003053 return results
Jon Hallc6793552016-01-19 14:18:37 -08003054 except AssertionError:
3055 main.log.exception( "" )
3056 return None
3057 except ( TypeError, ValueError ):
3058 main.log.exception( "{}: Object not as expected: {!r}".format( self.name, rawOutput ) )
acsmarsa4a4d1e2015-07-10 16:01:24 -07003059 return None
3060 except pexpect.EOF:
3061 main.log.error( self.name + ": EOF exception found" )
3062 main.log.error( self.name + ": " + self.handle.before )
3063 main.cleanup()
3064 main.exit()
3065 except Exception:
3066 main.log.exception( self.name + ": Uncaught exception!" )
3067 main.cleanup()
3068 main.exit()
3069
Jon Hall61282e32015-03-19 11:34:11 -07003070 def pendingMap( self, jsonFormat=True ):
Jon Hall63604932015-02-26 17:09:50 -08003071 """
3072 Returns the output of the intent Pending map.
3073 """
Jon Hall63604932015-02-26 17:09:50 -08003074 try:
Jon Hallc6358dd2015-04-10 12:44:28 -07003075 cmdStr = "onos:intents -p"
Jon Hall61282e32015-03-19 11:34:11 -07003076 if jsonFormat:
Jon Hallc6358dd2015-04-10 12:44:28 -07003077 cmdStr += " -j"
3078 output = self.sendline( cmdStr )
Jon Hallc6793552016-01-19 14:18:37 -08003079 assert "Command not found:" not in output, output
Jon Hallc6358dd2015-04-10 12:44:28 -07003080 return output
Jon Hallc6793552016-01-19 14:18:37 -08003081 except AssertionError:
3082 main.log.exception( "" )
3083 return None
Jon Hall63604932015-02-26 17:09:50 -08003084 except TypeError:
3085 main.log.exception( self.name + ": Object not as expected" )
3086 return None
3087 except pexpect.EOF:
3088 main.log.error( self.name + ": EOF exception found" )
3089 main.log.error( self.name + ": " + self.handle.before )
3090 main.cleanup()
3091 main.exit()
Jon Hall77ba41c2015-04-06 10:25:40 -07003092 except Exception:
Jon Hall63604932015-02-26 17:09:50 -08003093 main.log.exception( self.name + ": Uncaught exception!" )
3094 main.cleanup()
3095 main.exit()
3096
Jon Hall61282e32015-03-19 11:34:11 -07003097 def partitions( self, jsonFormat=True ):
Jon Hall63604932015-02-26 17:09:50 -08003098 """
3099 Returns the output of the raft partitions command for ONOS.
3100 """
Jon Hall61282e32015-03-19 11:34:11 -07003101 # Sample JSON
3102 # {
3103 # "leader": "tcp://10.128.30.11:7238",
3104 # "members": [
3105 # "tcp://10.128.30.11:7238",
3106 # "tcp://10.128.30.17:7238",
3107 # "tcp://10.128.30.13:7238",
3108 # ],
3109 # "name": "p1",
3110 # "term": 3
3111 # },
Jon Hall63604932015-02-26 17:09:50 -08003112 try:
Jon Hallc6358dd2015-04-10 12:44:28 -07003113 cmdStr = "onos:partitions"
Jon Hall61282e32015-03-19 11:34:11 -07003114 if jsonFormat:
Jon Hallc6358dd2015-04-10 12:44:28 -07003115 cmdStr += " -j"
3116 output = self.sendline( cmdStr )
Jon Hallc6793552016-01-19 14:18:37 -08003117 assert "Command not found:" not in output, output
Jon Hallc6358dd2015-04-10 12:44:28 -07003118 return output
Jon Hallc6793552016-01-19 14:18:37 -08003119 except AssertionError:
3120 main.log.exception( "" )
3121 return None
Jon Hall63604932015-02-26 17:09:50 -08003122 except TypeError:
3123 main.log.exception( self.name + ": Object not as expected" )
3124 return None
3125 except pexpect.EOF:
3126 main.log.error( self.name + ": EOF exception found" )
3127 main.log.error( self.name + ": " + self.handle.before )
3128 main.cleanup()
3129 main.exit()
Jon Hall77ba41c2015-04-06 10:25:40 -07003130 except Exception:
Jon Hall63604932015-02-26 17:09:50 -08003131 main.log.exception( self.name + ": Uncaught exception!" )
3132 main.cleanup()
3133 main.exit()
3134
Jon Hallbe379602015-03-24 13:39:32 -07003135 def apps( self, jsonFormat=True ):
3136 """
3137 Returns the output of the apps command for ONOS. This command lists
3138 information about installed ONOS applications
3139 """
3140 # Sample JSON object
3141 # [{"name":"org.onosproject.openflow","id":0,"version":"1.2.0",
3142 # "description":"ONOS OpenFlow protocol southbound providers",
3143 # "origin":"ON.Lab","permissions":"[]","featuresRepo":"",
3144 # "features":"[onos-openflow]","state":"ACTIVE"}]
3145 try:
Jon Hallc6358dd2015-04-10 12:44:28 -07003146 cmdStr = "onos:apps"
Jon Hallbe379602015-03-24 13:39:32 -07003147 if jsonFormat:
Jon Hallc6358dd2015-04-10 12:44:28 -07003148 cmdStr += " -j"
3149 output = self.sendline( cmdStr )
Jon Hallc6793552016-01-19 14:18:37 -08003150 assert "Command not found:" not in output, output
3151 assert "Error executing command" not in output, output
Jon Hallc6358dd2015-04-10 12:44:28 -07003152 return output
Jon Hallbe379602015-03-24 13:39:32 -07003153 # FIXME: look at specific exceptions/Errors
3154 except AssertionError:
Jon Hallc6793552016-01-19 14:18:37 -08003155 main.log.exception( "Error in processing onos:app command." )
Jon Hallbe379602015-03-24 13:39:32 -07003156 return None
3157 except TypeError:
3158 main.log.exception( self.name + ": Object not as expected" )
3159 return None
3160 except pexpect.EOF:
3161 main.log.error( self.name + ": EOF exception found" )
3162 main.log.error( self.name + ": " + self.handle.before )
3163 main.cleanup()
3164 main.exit()
Jon Hall77ba41c2015-04-06 10:25:40 -07003165 except Exception:
Jon Hallbe379602015-03-24 13:39:32 -07003166 main.log.exception( self.name + ": Uncaught exception!" )
3167 main.cleanup()
3168 main.exit()
3169
Jon Hall146f1522015-03-24 15:33:24 -07003170 def appStatus( self, appName ):
3171 """
3172 Uses the onos:apps cli command to return the status of an application.
3173 Returns:
3174 "ACTIVE" - If app is installed and activated
3175 "INSTALLED" - If app is installed and deactivated
3176 "UNINSTALLED" - If app is not installed
3177 None - on error
3178 """
Jon Hall146f1522015-03-24 15:33:24 -07003179 try:
3180 if not isinstance( appName, types.StringType ):
3181 main.log.error( self.name + ".appStatus(): appName must be" +
3182 " a string" )
3183 return None
3184 output = self.apps( jsonFormat=True )
3185 appsJson = json.loads( output )
3186 state = None
3187 for app in appsJson:
3188 if appName == app.get('name'):
3189 state = app.get('state')
3190 break
3191 if state == "ACTIVE" or state == "INSTALLED":
3192 return state
3193 elif state is None:
3194 return "UNINSTALLED"
3195 elif state:
3196 main.log.error( "Unexpected state from 'onos:apps': " +
3197 str( state ) )
3198 return state
Jon Hallc6793552016-01-19 14:18:37 -08003199 except ( TypeError, ValueError ):
3200 main.log.exception( "{}: Object not as expected: {!r}".format( self.name, output ) )
Jon Hall146f1522015-03-24 15:33:24 -07003201 return None
3202 except pexpect.EOF:
3203 main.log.error( self.name + ": EOF exception found" )
3204 main.log.error( self.name + ": " + self.handle.before )
3205 main.cleanup()
3206 main.exit()
Jon Hall77ba41c2015-04-06 10:25:40 -07003207 except Exception:
Jon Hall146f1522015-03-24 15:33:24 -07003208 main.log.exception( self.name + ": Uncaught exception!" )
3209 main.cleanup()
3210 main.exit()
3211
Jon Hallbe379602015-03-24 13:39:32 -07003212 def app( self, appName, option ):
3213 """
3214 Interacts with the app command for ONOS. This command manages
3215 application inventory.
3216 """
Jon Hallbe379602015-03-24 13:39:32 -07003217 try:
Jon Hallbd16b922015-03-26 17:53:15 -07003218 # Validate argument types
3219 valid = True
3220 if not isinstance( appName, types.StringType ):
3221 main.log.error( self.name + ".app(): appName must be a " +
3222 "string" )
3223 valid = False
3224 if not isinstance( option, types.StringType ):
3225 main.log.error( self.name + ".app(): option must be a string" )
3226 valid = False
3227 if not valid:
3228 return main.FALSE
3229 # Validate Option
3230 option = option.lower()
3231 # NOTE: Install may become a valid option
3232 if option == "activate":
3233 pass
3234 elif option == "deactivate":
3235 pass
3236 elif option == "uninstall":
3237 pass
3238 else:
3239 # Invalid option
3240 main.log.error( "The ONOS app command argument only takes " +
3241 "the values: (activate|deactivate|uninstall)" +
3242 "; was given '" + option + "'")
3243 return main.FALSE
Jon Hall146f1522015-03-24 15:33:24 -07003244 cmdStr = "onos:app " + option + " " + appName
Jon Hallbe379602015-03-24 13:39:32 -07003245 output = self.sendline( cmdStr )
Jon Hallbe379602015-03-24 13:39:32 -07003246 if "Error executing command" in output:
3247 main.log.error( "Error in processing onos:app command: " +
3248 str( output ) )
Jon Hall146f1522015-03-24 15:33:24 -07003249 return main.FALSE
Jon Hallbe379602015-03-24 13:39:32 -07003250 elif "No such application" in output:
3251 main.log.error( "The application '" + appName +
3252 "' is not installed in ONOS" )
Jon Hall146f1522015-03-24 15:33:24 -07003253 return main.FALSE
3254 elif "Command not found:" in output:
3255 main.log.error( "Error in processing onos:app command: " +
3256 str( output ) )
3257 return main.FALSE
Jon Hallbd16b922015-03-26 17:53:15 -07003258 elif "Unsupported command:" in output:
3259 main.log.error( "Incorrect command given to 'app': " +
3260 str( output ) )
Jon Hallbe379602015-03-24 13:39:32 -07003261 # NOTE: we may need to add more checks here
Jon Hallbd16b922015-03-26 17:53:15 -07003262 # else: Command was successful
Jon Hall08f61bc2015-04-13 16:00:30 -07003263 # main.log.debug( "app response: " + repr( output ) )
Jon Hallbe379602015-03-24 13:39:32 -07003264 return main.TRUE
3265 except TypeError:
3266 main.log.exception( self.name + ": Object not as expected" )
3267 return main.ERROR
3268 except pexpect.EOF:
3269 main.log.error( self.name + ": EOF exception found" )
3270 main.log.error( self.name + ": " + self.handle.before )
3271 main.cleanup()
3272 main.exit()
Jon Hall77ba41c2015-04-06 10:25:40 -07003273 except Exception:
Jon Hallbe379602015-03-24 13:39:32 -07003274 main.log.exception( self.name + ": Uncaught exception!" )
3275 main.cleanup()
3276 main.exit()
Jon Hall146f1522015-03-24 15:33:24 -07003277
Jon Hallbd16b922015-03-26 17:53:15 -07003278 def activateApp( self, appName, check=True ):
Jon Hall146f1522015-03-24 15:33:24 -07003279 """
3280 Activate an app that is already installed in ONOS
Jon Hallbd16b922015-03-26 17:53:15 -07003281 appName is the hierarchical app name, not the feature name
3282 If check is True, method will check the status of the app after the
3283 command is issued
Jon Hall146f1522015-03-24 15:33:24 -07003284 Returns main.TRUE if the command was successfully sent
3285 main.FALSE if the cli responded with an error or given
3286 incorrect input
3287 """
3288 try:
3289 if not isinstance( appName, types.StringType ):
3290 main.log.error( self.name + ".activateApp(): appName must be" +
3291 " a string" )
3292 return main.FALSE
3293 status = self.appStatus( appName )
3294 if status == "INSTALLED":
3295 response = self.app( appName, "activate" )
Jon Hallbd16b922015-03-26 17:53:15 -07003296 if check and response == main.TRUE:
3297 for i in range(10): # try 10 times then give up
Jon Hallbd16b922015-03-26 17:53:15 -07003298 status = self.appStatus( appName )
3299 if status == "ACTIVE":
3300 return main.TRUE
3301 else:
Jon Hall050e1bd2015-03-30 13:33:02 -07003302 main.log.debug( "The state of application " +
3303 appName + " is " + status )
Jon Hallbd16b922015-03-26 17:53:15 -07003304 time.sleep( 1 )
3305 return main.FALSE
3306 else: # not 'check' or command didn't succeed
3307 return response
Jon Hall146f1522015-03-24 15:33:24 -07003308 elif status == "ACTIVE":
3309 return main.TRUE
3310 elif status == "UNINSTALLED":
3311 main.log.error( self.name + ": Tried to activate the " +
3312 "application '" + appName + "' which is not " +
3313 "installed." )
3314 else:
3315 main.log.error( "Unexpected return value from appStatus: " +
3316 str( status ) )
3317 return main.ERROR
3318 except TypeError:
3319 main.log.exception( self.name + ": Object not as expected" )
3320 return main.ERROR
3321 except pexpect.EOF:
3322 main.log.error( self.name + ": EOF exception found" )
3323 main.log.error( self.name + ": " + self.handle.before )
3324 main.cleanup()
3325 main.exit()
Jon Hall77ba41c2015-04-06 10:25:40 -07003326 except Exception:
Jon Hall146f1522015-03-24 15:33:24 -07003327 main.log.exception( self.name + ": Uncaught exception!" )
3328 main.cleanup()
3329 main.exit()
3330
Jon Hallbd16b922015-03-26 17:53:15 -07003331 def deactivateApp( self, appName, check=True ):
Jon Hall146f1522015-03-24 15:33:24 -07003332 """
3333 Deactivate an app that is already activated in ONOS
Jon Hallbd16b922015-03-26 17:53:15 -07003334 appName is the hierarchical app name, not the feature name
3335 If check is True, method will check the status of the app after the
3336 command is issued
Jon Hall146f1522015-03-24 15:33:24 -07003337 Returns main.TRUE if the command was successfully sent
3338 main.FALSE if the cli responded with an error or given
3339 incorrect input
3340 """
3341 try:
3342 if not isinstance( appName, types.StringType ):
3343 main.log.error( self.name + ".deactivateApp(): appName must " +
3344 "be a string" )
3345 return main.FALSE
3346 status = self.appStatus( appName )
3347 if status == "INSTALLED":
3348 return main.TRUE
3349 elif status == "ACTIVE":
3350 response = self.app( appName, "deactivate" )
Jon Hallbd16b922015-03-26 17:53:15 -07003351 if check and response == main.TRUE:
3352 for i in range(10): # try 10 times then give up
3353 status = self.appStatus( appName )
3354 if status == "INSTALLED":
3355 return main.TRUE
3356 else:
3357 time.sleep( 1 )
3358 return main.FALSE
3359 else: # not check or command didn't succeed
3360 return response
Jon Hall146f1522015-03-24 15:33:24 -07003361 elif status == "UNINSTALLED":
3362 main.log.warn( self.name + ": Tried to deactivate the " +
3363 "application '" + appName + "' which is not " +
3364 "installed." )
3365 return main.TRUE
3366 else:
3367 main.log.error( "Unexpected return value from appStatus: " +
3368 str( status ) )
3369 return main.ERROR
3370 except TypeError:
3371 main.log.exception( self.name + ": Object not as expected" )
3372 return main.ERROR
3373 except pexpect.EOF:
3374 main.log.error( self.name + ": EOF exception found" )
3375 main.log.error( self.name + ": " + self.handle.before )
3376 main.cleanup()
3377 main.exit()
Jon Hall77ba41c2015-04-06 10:25:40 -07003378 except Exception:
Jon Hall146f1522015-03-24 15:33:24 -07003379 main.log.exception( self.name + ": Uncaught exception!" )
3380 main.cleanup()
3381 main.exit()
3382
Jon Hallbd16b922015-03-26 17:53:15 -07003383 def uninstallApp( self, appName, check=True ):
Jon Hall146f1522015-03-24 15:33:24 -07003384 """
3385 Uninstall an app that is already installed in ONOS
Jon Hallbd16b922015-03-26 17:53:15 -07003386 appName is the hierarchical app name, not the feature name
3387 If check is True, method will check the status of the app after the
3388 command is issued
Jon Hall146f1522015-03-24 15:33:24 -07003389 Returns main.TRUE if the command was successfully sent
3390 main.FALSE if the cli responded with an error or given
3391 incorrect input
3392 """
3393 # TODO: check with Thomas about the state machine for apps
3394 try:
3395 if not isinstance( appName, types.StringType ):
3396 main.log.error( self.name + ".uninstallApp(): appName must " +
3397 "be a string" )
3398 return main.FALSE
3399 status = self.appStatus( appName )
3400 if status == "INSTALLED":
3401 response = self.app( appName, "uninstall" )
Jon Hallbd16b922015-03-26 17:53:15 -07003402 if check and response == main.TRUE:
3403 for i in range(10): # try 10 times then give up
3404 status = self.appStatus( appName )
3405 if status == "UNINSTALLED":
3406 return main.TRUE
3407 else:
3408 time.sleep( 1 )
3409 return main.FALSE
3410 else: # not check or command didn't succeed
3411 return response
Jon Hall146f1522015-03-24 15:33:24 -07003412 elif status == "ACTIVE":
3413 main.log.warn( self.name + ": Tried to uninstall the " +
3414 "application '" + appName + "' which is " +
3415 "currently active." )
3416 response = self.app( appName, "uninstall" )
Jon Hallbd16b922015-03-26 17:53:15 -07003417 if check and response == main.TRUE:
3418 for i in range(10): # try 10 times then give up
3419 status = self.appStatus( appName )
3420 if status == "UNINSTALLED":
3421 return main.TRUE
3422 else:
3423 time.sleep( 1 )
3424 return main.FALSE
3425 else: # not check or command didn't succeed
3426 return response
Jon Hall146f1522015-03-24 15:33:24 -07003427 elif status == "UNINSTALLED":
3428 return main.TRUE
3429 else:
3430 main.log.error( "Unexpected return value from appStatus: " +
3431 str( status ) )
3432 return main.ERROR
3433 except TypeError:
3434 main.log.exception( self.name + ": Object not as expected" )
3435 return main.ERROR
3436 except pexpect.EOF:
3437 main.log.error( self.name + ": EOF exception found" )
3438 main.log.error( self.name + ": " + self.handle.before )
3439 main.cleanup()
3440 main.exit()
Jon Hall77ba41c2015-04-06 10:25:40 -07003441 except Exception:
Jon Hall146f1522015-03-24 15:33:24 -07003442 main.log.exception( self.name + ": Uncaught exception!" )
3443 main.cleanup()
3444 main.exit()
Jon Hallbd16b922015-03-26 17:53:15 -07003445
3446 def appIDs( self, jsonFormat=True ):
3447 """
3448 Show the mappings between app id and app names given by the 'app-ids'
3449 cli command
3450 """
3451 try:
3452 cmdStr = "app-ids"
3453 if jsonFormat:
3454 cmdStr += " -j"
Jon Hallc6358dd2015-04-10 12:44:28 -07003455 output = self.sendline( cmdStr )
Jon Hallc6793552016-01-19 14:18:37 -08003456 assert "Command not found:" not in output, output
3457 assert "Error executing command" not in output, output
Jon Hallc6358dd2015-04-10 12:44:28 -07003458 return output
Jon Hallbd16b922015-03-26 17:53:15 -07003459 except AssertionError:
Jon Hallc6793552016-01-19 14:18:37 -08003460 main.log.exception( "Error in processing onos:app-ids command." )
Jon Hallbd16b922015-03-26 17:53:15 -07003461 return None
3462 except TypeError:
3463 main.log.exception( self.name + ": Object not as expected" )
3464 return None
3465 except pexpect.EOF:
3466 main.log.error( self.name + ": EOF exception found" )
3467 main.log.error( self.name + ": " + self.handle.before )
3468 main.cleanup()
3469 main.exit()
Jon Hall77ba41c2015-04-06 10:25:40 -07003470 except Exception:
Jon Hallbd16b922015-03-26 17:53:15 -07003471 main.log.exception( self.name + ": Uncaught exception!" )
3472 main.cleanup()
3473 main.exit()
3474
3475 def appToIDCheck( self ):
3476 """
3477 This method will check that each application's ID listed in 'apps' is
3478 the same as the ID listed in 'app-ids'. The check will also check that
3479 there are no duplicate IDs issued. Note that an app ID should be
3480 a globaly unique numerical identifier for app/app-like features. Once
3481 an ID is registered, the ID is never freed up so that if an app is
3482 reinstalled it will have the same ID.
3483
3484 Returns: main.TRUE if the check passes and
3485 main.FALSE if the check fails or
3486 main.ERROR if there is some error in processing the test
3487 """
3488 try:
Jon Hall390696c2015-05-05 17:13:41 -07003489 bail = False
Jon Hallc6793552016-01-19 14:18:37 -08003490 rawJson = self.appIDs( jsonFormat=True )
3491 if rawJson:
3492 ids = json.loads( rawJson )
Jon Hall390696c2015-05-05 17:13:41 -07003493 else:
Jon Hallc6793552016-01-19 14:18:37 -08003494 main.log.error( "app-ids returned nothing:" + repr( rawJson ) )
Jon Hall390696c2015-05-05 17:13:41 -07003495 bail = True
Jon Hallc6793552016-01-19 14:18:37 -08003496 rawJson = self.apps( jsonFormat=True )
3497 if rawJson:
3498 apps = json.loads( rawJson )
Jon Hall390696c2015-05-05 17:13:41 -07003499 else:
Jon Hallc6793552016-01-19 14:18:37 -08003500 main.log.error( "apps returned nothing:" + repr( rawJson ) )
Jon Hall390696c2015-05-05 17:13:41 -07003501 bail = True
3502 if bail:
3503 return main.FALSE
Jon Hallbd16b922015-03-26 17:53:15 -07003504 result = main.TRUE
3505 for app in apps:
3506 appID = app.get( 'id' )
3507 if appID is None:
3508 main.log.error( "Error parsing app: " + str( app ) )
3509 result = main.FALSE
3510 appName = app.get( 'name' )
3511 if appName is None:
3512 main.log.error( "Error parsing app: " + str( app ) )
3513 result = main.FALSE
3514 # get the entry in ids that has the same appID
Jon Hall390696c2015-05-05 17:13:41 -07003515 current = filter( lambda item: item[ 'id' ] == appID, ids )
Jon Hall050e1bd2015-03-30 13:33:02 -07003516 # main.log.debug( "Comparing " + str( app ) + " to " +
3517 # str( current ) )
Jon Hallbd16b922015-03-26 17:53:15 -07003518 if not current: # if ids doesn't have this id
3519 result = main.FALSE
3520 main.log.error( "'app-ids' does not have the ID for " +
3521 str( appName ) + " that apps does." )
3522 elif len( current ) > 1:
3523 # there is more than one app with this ID
3524 result = main.FALSE
3525 # We will log this later in the method
3526 elif not current[0][ 'name' ] == appName:
3527 currentName = current[0][ 'name' ]
3528 result = main.FALSE
3529 main.log.error( "'app-ids' has " + str( currentName ) +
3530 " registered under id:" + str( appID ) +
3531 " but 'apps' has " + str( appName ) )
3532 else:
3533 pass # id and name match!
3534 # now make sure that app-ids has no duplicates
3535 idsList = []
3536 namesList = []
3537 for item in ids:
3538 idsList.append( item[ 'id' ] )
3539 namesList.append( item[ 'name' ] )
3540 if len( idsList ) != len( set( idsList ) ) or\
3541 len( namesList ) != len( set( namesList ) ):
3542 main.log.error( "'app-ids' has some duplicate entries: \n"
3543 + json.dumps( ids,
3544 sort_keys=True,
3545 indent=4,
3546 separators=( ',', ': ' ) ) )
3547 result = main.FALSE
3548 return result
Jon Hallc6793552016-01-19 14:18:37 -08003549 except ( TypeError, ValueError ):
3550 main.log.exception( "{}: Object not as expected: {!r}".format( self.name, rawJson ) )
Jon Hallbd16b922015-03-26 17:53:15 -07003551 return main.ERROR
3552 except pexpect.EOF:
3553 main.log.error( self.name + ": EOF exception found" )
3554 main.log.error( self.name + ": " + self.handle.before )
3555 main.cleanup()
3556 main.exit()
Jon Hall77ba41c2015-04-06 10:25:40 -07003557 except Exception:
Jon Hallbd16b922015-03-26 17:53:15 -07003558 main.log.exception( self.name + ": Uncaught exception!" )
3559 main.cleanup()
3560 main.exit()
3561
Jon Hallfb760a02015-04-13 15:35:03 -07003562 def getCfg( self, component=None, propName=None, short=False,
3563 jsonFormat=True ):
3564 """
3565 Get configuration settings from onos cli
3566 Optional arguments:
3567 component - Optionally only list configurations for a specific
3568 component. If None, all components with configurations
3569 are displayed. Case Sensitive string.
3570 propName - If component is specified, propName option will show
3571 only this specific configuration from that component.
3572 Case Sensitive string.
3573 jsonFormat - Returns output as json. Note that this will override
3574 the short option
3575 short - Short, less verbose, version of configurations.
3576 This is overridden by the json option
3577 returns:
3578 Output from cli as a string or None on error
3579 """
3580 try:
3581 baseStr = "cfg"
3582 cmdStr = " get"
3583 componentStr = ""
3584 if component:
3585 componentStr += " " + component
3586 if propName:
3587 componentStr += " " + propName
3588 if jsonFormat:
3589 baseStr += " -j"
3590 elif short:
3591 baseStr += " -s"
3592 output = self.sendline( baseStr + cmdStr + componentStr )
Jon Hallc6793552016-01-19 14:18:37 -08003593 assert "Command not found:" not in output, output
3594 assert "Error executing command" not in output, output
Jon Hallfb760a02015-04-13 15:35:03 -07003595 return output
3596 except AssertionError:
Jon Hallc6793552016-01-19 14:18:37 -08003597 main.log.exception( "Error in processing 'cfg get' command." )
Jon Hallfb760a02015-04-13 15:35:03 -07003598 return None
3599 except TypeError:
3600 main.log.exception( self.name + ": Object not as expected" )
3601 return None
3602 except pexpect.EOF:
3603 main.log.error( self.name + ": EOF exception found" )
3604 main.log.error( self.name + ": " + self.handle.before )
3605 main.cleanup()
3606 main.exit()
3607 except Exception:
3608 main.log.exception( self.name + ": Uncaught exception!" )
3609 main.cleanup()
3610 main.exit()
3611
3612 def setCfg( self, component, propName, value=None, check=True ):
3613 """
3614 Set/Unset configuration settings from ONOS cli
Jon Hall390696c2015-05-05 17:13:41 -07003615 Required arguments:
Jon Hallfb760a02015-04-13 15:35:03 -07003616 component - The case sensitive name of the component whose
3617 property is to be set
3618 propName - The case sensitive name of the property to be set/unset
Jon Hall390696c2015-05-05 17:13:41 -07003619 Optional arguments:
Jon Hallfb760a02015-04-13 15:35:03 -07003620 value - The value to set the property to. If None, will unset the
3621 property and revert it to it's default value(if applicable)
3622 check - Boolean, Check whether the option was successfully set this
3623 only applies when a value is given.
3624 returns:
3625 main.TRUE on success or main.FALSE on failure. If check is False,
3626 will return main.TRUE unless there is an error
3627 """
3628 try:
3629 baseStr = "cfg"
3630 cmdStr = " set " + str( component ) + " " + str( propName )
3631 if value is not None:
3632 cmdStr += " " + str( value )
3633 output = self.sendline( baseStr + cmdStr )
Jon Hallc6793552016-01-19 14:18:37 -08003634 assert "Command not found:" not in output, output
3635 assert "Error executing command" not in output, output
Jon Hallfb760a02015-04-13 15:35:03 -07003636 if value and check:
3637 results = self.getCfg( component=str( component ),
3638 propName=str( propName ),
3639 jsonFormat=True )
3640 # Check if current value is what we just set
3641 try:
3642 jsonOutput = json.loads( results )
3643 current = jsonOutput[ 'value' ]
Jon Hallc6793552016-01-19 14:18:37 -08003644 except ( TypeError, ValueError ):
Jon Hallfb760a02015-04-13 15:35:03 -07003645 main.log.exception( "Error parsing cfg output" )
3646 main.log.error( "output:" + repr( results ) )
3647 return main.FALSE
3648 if current == str( value ):
3649 return main.TRUE
3650 return main.FALSE
3651 return main.TRUE
3652 except AssertionError:
Jon Hallc6793552016-01-19 14:18:37 -08003653 main.log.exception( "Error in processing 'cfg set' command." )
Jon Hallfb760a02015-04-13 15:35:03 -07003654 return main.FALSE
Jon Hallc6793552016-01-19 14:18:37 -08003655 except ( TypeError, ValueError ):
3656 main.log.exception( "{}: Object not as expected: {!r}".format( self.name, results ) )
Jon Hallfb760a02015-04-13 15:35:03 -07003657 return main.FALSE
3658 except pexpect.EOF:
3659 main.log.error( self.name + ": EOF exception found" )
3660 main.log.error( self.name + ": " + self.handle.before )
3661 main.cleanup()
3662 main.exit()
3663 except Exception:
3664 main.log.exception( self.name + ": Uncaught exception!" )
3665 main.cleanup()
3666 main.exit()
3667
Jon Hall390696c2015-05-05 17:13:41 -07003668 def setTestAdd( self, setName, values ):
3669 """
3670 CLI command to add elements to a distributed set.
3671 Arguments:
3672 setName - The name of the set to add to.
3673 values - The value(s) to add to the set, space seperated.
3674 Example usages:
3675 setTestAdd( "set1", "a b c" )
3676 setTestAdd( "set2", "1" )
3677 returns:
3678 main.TRUE on success OR
3679 main.FALSE if elements were already in the set OR
3680 main.ERROR on error
3681 """
3682 try:
3683 cmdStr = "set-test-add " + str( setName ) + " " + str( values )
3684 output = self.sendline( cmdStr )
Jon Hallc6793552016-01-19 14:18:37 -08003685 assert "Command not found:" not in output, output
Jon Hallfeff3082015-05-19 10:23:26 -07003686 try:
3687 # TODO: Maybe make this less hardcoded
3688 # ConsistentMap Exceptions
3689 assert "org.onosproject.store.service" not in output
3690 # Node not leader
3691 assert "java.lang.IllegalStateException" not in output
3692 except AssertionError:
Jon Halle1a3b752015-07-22 13:02:46 -07003693 main.log.error( "Error in processing '" + cmdStr + "' " +
Jon Hallfeff3082015-05-19 10:23:26 -07003694 "command: " + str( output ) )
3695 retryTime = 30 # Conservative time, given by Madan
3696 main.log.info( "Waiting " + str( retryTime ) +
3697 "seconds before retrying." )
3698 time.sleep( retryTime ) # Due to change in mastership
3699 output = self.sendline( cmdStr )
Jon Hall390696c2015-05-05 17:13:41 -07003700 assert "Error executing command" not in output
3701 positiveMatch = "\[(.*)\] was added to the set " + str( setName )
3702 negativeMatch = "\[(.*)\] was already in set " + str( setName )
3703 main.log.info( self.name + ": " + output )
3704 if re.search( positiveMatch, output):
3705 return main.TRUE
3706 elif re.search( negativeMatch, output):
3707 return main.FALSE
3708 else:
3709 main.log.error( self.name + ": setTestAdd did not" +
3710 " match expected output" )
Jon Hall390696c2015-05-05 17:13:41 -07003711 main.log.debug( self.name + " actual: " + repr( output ) )
3712 return main.ERROR
3713 except AssertionError:
Jon Hallc6793552016-01-19 14:18:37 -08003714 main.log.exception( "Error in processing '" + cmdStr + "' command. " )
Jon Hall390696c2015-05-05 17:13:41 -07003715 return main.ERROR
3716 except TypeError:
3717 main.log.exception( self.name + ": Object not as expected" )
3718 return main.ERROR
3719 except pexpect.EOF:
3720 main.log.error( self.name + ": EOF exception found" )
3721 main.log.error( self.name + ": " + self.handle.before )
3722 main.cleanup()
3723 main.exit()
3724 except Exception:
3725 main.log.exception( self.name + ": Uncaught exception!" )
3726 main.cleanup()
3727 main.exit()
3728
3729 def setTestRemove( self, setName, values, clear=False, retain=False ):
3730 """
3731 CLI command to remove elements from a distributed set.
3732 Required arguments:
3733 setName - The name of the set to remove from.
3734 values - The value(s) to remove from the set, space seperated.
3735 Optional arguments:
3736 clear - Clear all elements from the set
3737 retain - Retain only the given values. (intersection of the
3738 original set and the given set)
3739 returns:
3740 main.TRUE on success OR
3741 main.FALSE if the set was not changed OR
3742 main.ERROR on error
3743 """
3744 try:
3745 cmdStr = "set-test-remove "
3746 if clear:
3747 cmdStr += "-c " + str( setName )
3748 elif retain:
3749 cmdStr += "-r " + str( setName ) + " " + str( values )
3750 else:
3751 cmdStr += str( setName ) + " " + str( values )
3752 output = self.sendline( cmdStr )
Jon Hallfeff3082015-05-19 10:23:26 -07003753 try:
3754 # TODO: Maybe make this less hardcoded
3755 # ConsistentMap Exceptions
3756 assert "org.onosproject.store.service" not in output
3757 # Node not leader
3758 assert "java.lang.IllegalStateException" not in output
3759 except AssertionError:
Jon Halle1a3b752015-07-22 13:02:46 -07003760 main.log.error( "Error in processing '" + cmdStr + "' " +
Jon Hallfeff3082015-05-19 10:23:26 -07003761 "command: " + str( output ) )
3762 retryTime = 30 # Conservative time, given by Madan
3763 main.log.info( "Waiting " + str( retryTime ) +
3764 "seconds before retrying." )
3765 time.sleep( retryTime ) # Due to change in mastership
3766 output = self.sendline( cmdStr )
Jon Hallc6793552016-01-19 14:18:37 -08003767 assert "Command not found:" not in output, output
3768 assert "Error executing command" not in output, output
Jon Hall390696c2015-05-05 17:13:41 -07003769 main.log.info( self.name + ": " + output )
3770 if clear:
3771 pattern = "Set " + str( setName ) + " cleared"
3772 if re.search( pattern, output ):
3773 return main.TRUE
3774 elif retain:
3775 positivePattern = str( setName ) + " was pruned to contain " +\
3776 "only elements of set \[(.*)\]"
3777 negativePattern = str( setName ) + " was not changed by " +\
3778 "retaining only elements of the set " +\
3779 "\[(.*)\]"
3780 if re.search( positivePattern, output ):
3781 return main.TRUE
3782 elif re.search( negativePattern, output ):
3783 return main.FALSE
3784 else:
3785 positivePattern = "\[(.*)\] was removed from the set " +\
3786 str( setName )
3787 if ( len( values.split() ) == 1 ):
3788 negativePattern = "\[(.*)\] was not in set " +\
3789 str( setName )
3790 else:
3791 negativePattern = "No element of \[(.*)\] was in set " +\
3792 str( setName )
3793 if re.search( positivePattern, output ):
3794 return main.TRUE
3795 elif re.search( negativePattern, output ):
3796 return main.FALSE
3797 main.log.error( self.name + ": setTestRemove did not" +
3798 " match expected output" )
3799 main.log.debug( self.name + " expected: " + pattern )
3800 main.log.debug( self.name + " actual: " + repr( output ) )
3801 return main.ERROR
3802 except AssertionError:
Jon Hallc6793552016-01-19 14:18:37 -08003803 main.log.exception( "Error in processing '" + cmdStr + "' commandr. " )
Jon Hall390696c2015-05-05 17:13:41 -07003804 return main.ERROR
3805 except TypeError:
3806 main.log.exception( self.name + ": Object not as expected" )
3807 return main.ERROR
3808 except pexpect.EOF:
3809 main.log.error( self.name + ": EOF exception found" )
3810 main.log.error( self.name + ": " + self.handle.before )
3811 main.cleanup()
3812 main.exit()
3813 except Exception:
3814 main.log.exception( self.name + ": Uncaught exception!" )
3815 main.cleanup()
3816 main.exit()
3817
3818 def setTestGet( self, setName, values="" ):
3819 """
3820 CLI command to get the elements in a distributed set.
3821 Required arguments:
3822 setName - The name of the set to remove from.
3823 Optional arguments:
3824 values - The value(s) to check if in the set, space seperated.
3825 returns:
3826 main.ERROR on error OR
3827 A list of elements in the set if no optional arguments are
3828 supplied OR
3829 A tuple containing the list then:
3830 main.FALSE if the given values are not in the set OR
3831 main.TRUE if the given values are in the set OR
3832 """
3833 try:
3834 values = str( values ).strip()
3835 setName = str( setName ).strip()
3836 length = len( values.split() )
3837 containsCheck = None
3838 # Patterns to match
3839 setPattern = "\[(.*)\]"
3840 pattern = "Items in set " + setName + ":\n" + setPattern
3841 containsTrue = "Set " + setName + " contains the value " + values
3842 containsFalse = "Set " + setName + " did not contain the value " +\
3843 values
3844 containsAllTrue = "Set " + setName + " contains the the subset " +\
3845 setPattern
3846 containsAllFalse = "Set " + setName + " did not contain the the" +\
3847 " subset " + setPattern
3848
3849 cmdStr = "set-test-get "
3850 cmdStr += setName + " " + values
3851 output = self.sendline( cmdStr )
Jon Hallfeff3082015-05-19 10:23:26 -07003852 try:
3853 # TODO: Maybe make this less hardcoded
3854 # ConsistentMap Exceptions
3855 assert "org.onosproject.store.service" not in output
3856 # Node not leader
3857 assert "java.lang.IllegalStateException" not in output
3858 except AssertionError:
Jon Halle1a3b752015-07-22 13:02:46 -07003859 main.log.error( "Error in processing '" + cmdStr + "' " +
Jon Hallfeff3082015-05-19 10:23:26 -07003860 "command: " + str( output ) )
3861 retryTime = 30 # Conservative time, given by Madan
3862 main.log.info( "Waiting " + str( retryTime ) +
3863 "seconds before retrying." )
3864 time.sleep( retryTime ) # Due to change in mastership
3865 output = self.sendline( cmdStr )
Jon Hallc6793552016-01-19 14:18:37 -08003866 assert "Command not found:" not in output, output
3867 assert "Error executing command" not in output, output
Jon Hall390696c2015-05-05 17:13:41 -07003868 main.log.info( self.name + ": " + output )
3869
3870 if length == 0:
3871 match = re.search( pattern, output )
3872 else: # if given values
3873 if length == 1: # Contains output
3874 patternTrue = pattern + "\n" + containsTrue
3875 patternFalse = pattern + "\n" + containsFalse
3876 else: # ContainsAll output
3877 patternTrue = pattern + "\n" + containsAllTrue
3878 patternFalse = pattern + "\n" + containsAllFalse
3879 matchTrue = re.search( patternTrue, output )
3880 matchFalse = re.search( patternFalse, output )
3881 if matchTrue:
3882 containsCheck = main.TRUE
3883 match = matchTrue
3884 elif matchFalse:
3885 containsCheck = main.FALSE
3886 match = matchFalse
3887 else:
3888 main.log.error( self.name + " setTestGet did not match " +\
3889 "expected output" )
3890 main.log.debug( self.name + " expected: " + pattern )
3891 main.log.debug( self.name + " actual: " + repr( output ) )
3892 match = None
3893 if match:
3894 setMatch = match.group( 1 )
3895 if setMatch == '':
3896 setList = []
3897 else:
3898 setList = setMatch.split( ", " )
3899 if length > 0:
3900 return ( setList, containsCheck )
3901 else:
3902 return setList
3903 else: # no match
3904 main.log.error( self.name + ": setTestGet did not" +
3905 " match expected output" )
3906 main.log.debug( self.name + " expected: " + pattern )
3907 main.log.debug( self.name + " actual: " + repr( output ) )
3908 return main.ERROR
3909 except AssertionError:
Jon Hallc6793552016-01-19 14:18:37 -08003910 main.log.exception( "Error in processing '" + cmdStr + "' command." )
Jon Hall390696c2015-05-05 17:13:41 -07003911 return main.ERROR
3912 except TypeError:
3913 main.log.exception( self.name + ": Object not as expected" )
3914 return main.ERROR
3915 except pexpect.EOF:
3916 main.log.error( self.name + ": EOF exception found" )
3917 main.log.error( self.name + ": " + self.handle.before )
3918 main.cleanup()
3919 main.exit()
3920 except Exception:
3921 main.log.exception( self.name + ": Uncaught exception!" )
3922 main.cleanup()
3923 main.exit()
3924
3925 def setTestSize( self, setName ):
3926 """
3927 CLI command to get the elements in a distributed set.
3928 Required arguments:
3929 setName - The name of the set to remove from.
3930 returns:
Jon Hallfeff3082015-05-19 10:23:26 -07003931 The integer value of the size returned or
Jon Hall390696c2015-05-05 17:13:41 -07003932 None on error
3933 """
3934 try:
3935 # TODO: Should this check against the number of elements returned
3936 # and then return true/false based on that?
3937 setName = str( setName ).strip()
3938 # Patterns to match
3939 setPattern = "\[(.*)\]"
3940 pattern = "There are (\d+) items in set " + setName + ":\n" +\
3941 setPattern
3942 cmdStr = "set-test-get -s "
3943 cmdStr += setName
3944 output = self.sendline( cmdStr )
Jon Hallfeff3082015-05-19 10:23:26 -07003945 try:
3946 # TODO: Maybe make this less hardcoded
3947 # ConsistentMap Exceptions
3948 assert "org.onosproject.store.service" not in output
3949 # Node not leader
3950 assert "java.lang.IllegalStateException" not in output
3951 except AssertionError:
Jon Halle1a3b752015-07-22 13:02:46 -07003952 main.log.error( "Error in processing '" + cmdStr + "' " +
Jon Hallfeff3082015-05-19 10:23:26 -07003953 "command: " + str( output ) )
3954 retryTime = 30 # Conservative time, given by Madan
3955 main.log.info( "Waiting " + str( retryTime ) +
3956 "seconds before retrying." )
3957 time.sleep( retryTime ) # Due to change in mastership
3958 output = self.sendline( cmdStr )
Jon Hallc6793552016-01-19 14:18:37 -08003959 assert "Command not found:" not in output, output
3960 assert "Error executing command" not in output, output
Jon Hall390696c2015-05-05 17:13:41 -07003961 main.log.info( self.name + ": " + output )
3962 match = re.search( pattern, output )
3963 if match:
3964 setSize = int( match.group( 1 ) )
3965 setMatch = match.group( 2 )
3966 if len( setMatch.split() ) == setSize:
3967 main.log.info( "The size returned by " + self.name +
3968 " matches the number of elements in " +
3969 "the returned set" )
3970 else:
3971 main.log.error( "The size returned by " + self.name +
3972 " does not match the number of " +
3973 "elements in the returned set." )
3974 return setSize
3975 else: # no match
3976 main.log.error( self.name + ": setTestGet did not" +
3977 " match expected output" )
3978 main.log.debug( self.name + " expected: " + pattern )
3979 main.log.debug( self.name + " actual: " + repr( output ) )
3980 return None
3981 except AssertionError:
Jon Hallc6793552016-01-19 14:18:37 -08003982 main.log.exception( "Error in processing '" + cmdStr + "' command." )
acsmarsa4a4d1e2015-07-10 16:01:24 -07003983 return None
Jon Hall390696c2015-05-05 17:13:41 -07003984 except TypeError:
3985 main.log.exception( self.name + ": Object not as expected" )
3986 return None
3987 except pexpect.EOF:
3988 main.log.error( self.name + ": EOF exception found" )
3989 main.log.error( self.name + ": " + self.handle.before )
3990 main.cleanup()
3991 main.exit()
3992 except Exception:
3993 main.log.exception( self.name + ": Uncaught exception!" )
3994 main.cleanup()
3995 main.exit()
3996
Jon Hall80daded2015-05-27 16:07:00 -07003997 def counters( self, jsonFormat=True ):
Jon Hall390696c2015-05-05 17:13:41 -07003998 """
3999 Command to list the various counters in the system.
4000 returns:
Jon Hall80daded2015-05-27 16:07:00 -07004001 if jsonFormat, a string of the json object returned by the cli
4002 command
4003 if not jsonFormat, the normal string output of the cli command
Jon Hall390696c2015-05-05 17:13:41 -07004004 None on error
4005 """
Jon Hall390696c2015-05-05 17:13:41 -07004006 try:
4007 counters = {}
4008 cmdStr = "counters"
Jon Hall80daded2015-05-27 16:07:00 -07004009 if jsonFormat:
4010 cmdStr += " -j"
Jon Hall390696c2015-05-05 17:13:41 -07004011 output = self.sendline( cmdStr )
Jon Hallc6793552016-01-19 14:18:37 -08004012 assert "Command not found:" not in output, output
4013 assert "Error executing command" not in output, output
Jon Hall390696c2015-05-05 17:13:41 -07004014 main.log.info( self.name + ": " + output )
Jon Hall80daded2015-05-27 16:07:00 -07004015 return output
Jon Hall390696c2015-05-05 17:13:41 -07004016 except AssertionError:
Jon Hallc6793552016-01-19 14:18:37 -08004017 main.log.exception( "Error in processing 'counters' command." )
Jon Hall80daded2015-05-27 16:07:00 -07004018 return None
Jon Hall390696c2015-05-05 17:13:41 -07004019 except TypeError:
4020 main.log.exception( self.name + ": Object not as expected" )
Jon Hall80daded2015-05-27 16:07:00 -07004021 return None
Jon Hall390696c2015-05-05 17:13:41 -07004022 except pexpect.EOF:
4023 main.log.error( self.name + ": EOF exception found" )
4024 main.log.error( self.name + ": " + self.handle.before )
4025 main.cleanup()
4026 main.exit()
4027 except Exception:
4028 main.log.exception( self.name + ": Uncaught exception!" )
4029 main.cleanup()
4030 main.exit()
4031
Jon Hall935db192016-04-19 00:22:04 -07004032 def counterTestAddAndGet( self, counter, delta=1 ):
Jon Hall390696c2015-05-05 17:13:41 -07004033 """
Jon Halle1a3b752015-07-22 13:02:46 -07004034 CLI command to add a delta to then get a distributed counter.
Jon Hall390696c2015-05-05 17:13:41 -07004035 Required arguments:
4036 counter - The name of the counter to increment.
4037 Optional arguments:
Jon Halle1a3b752015-07-22 13:02:46 -07004038 delta - The long to add to the counter
Jon Hall390696c2015-05-05 17:13:41 -07004039 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 "
Jon Hall390696c2015-05-05 17:13:41 -07004047 cmdStr += counter
Jon Halle1a3b752015-07-22 13:02:46 -07004048 if delta != 1:
4049 cmdStr += " " + str( delta )
Jon Hall390696c2015-05-05 17:13:41 -07004050 output = self.sendline( cmdStr )
Jon Hallfeff3082015-05-19 10:23:26 -07004051 try:
4052 # TODO: Maybe make this less hardcoded
4053 # ConsistentMap Exceptions
4054 assert "org.onosproject.store.service" not in output
4055 # Node not leader
4056 assert "java.lang.IllegalStateException" not in output
4057 except AssertionError:
Jon Halle1a3b752015-07-22 13:02:46 -07004058 main.log.error( "Error in processing '" + cmdStr + "' " +
Jon Hallfeff3082015-05-19 10:23:26 -07004059 "command: " + str( output ) )
4060 retryTime = 30 # Conservative time, given by Madan
4061 main.log.info( "Waiting " + str( retryTime ) +
4062 "seconds before retrying." )
4063 time.sleep( retryTime ) # Due to change in mastership
4064 output = self.sendline( cmdStr )
Jon Hallc6793552016-01-19 14:18:37 -08004065 assert "Command not found:" not in output, output
4066 assert "Error executing command" not in output, output
Jon Hall390696c2015-05-05 17:13:41 -07004067 main.log.info( self.name + ": " + output )
Jon Halle1a3b752015-07-22 13:02:46 -07004068 pattern = counter + " was updated to (-?\d+)"
Jon Hall390696c2015-05-05 17:13:41 -07004069 match = re.search( pattern, output )
4070 if match:
4071 return int( match.group( 1 ) )
4072 else:
Jon Halle1a3b752015-07-22 13:02:46 -07004073 main.log.error( self.name + ": counterTestAddAndGet did not" +
Jon Hall390696c2015-05-05 17:13:41 -07004074 " match expected output." )
4075 main.log.debug( self.name + " expected: " + pattern )
4076 main.log.debug( self.name + " actual: " + repr( output ) )
4077 return None
4078 except AssertionError:
Jon Hallc6793552016-01-19 14:18:37 -08004079 main.log.exception( "Error in processing '" + cmdStr + "' command." )
Jon Hall390696c2015-05-05 17:13:41 -07004080 return None
4081 except TypeError:
4082 main.log.exception( self.name + ": Object not as expected" )
4083 return None
4084 except pexpect.EOF:
4085 main.log.error( self.name + ": EOF exception found" )
4086 main.log.error( self.name + ": " + self.handle.before )
4087 main.cleanup()
4088 main.exit()
4089 except Exception:
4090 main.log.exception( self.name + ": Uncaught exception!" )
4091 main.cleanup()
4092 main.exit()
4093
Jon Hall935db192016-04-19 00:22:04 -07004094 def counterTestGetAndAdd( self, counter, delta=1 ):
Jon Halle1a3b752015-07-22 13:02:46 -07004095 """
4096 CLI command to get a distributed counter then add a delta to it.
4097 Required arguments:
4098 counter - The name of the counter to increment.
4099 Optional arguments:
4100 delta - The long to add to the counter
Jon Halle1a3b752015-07-22 13:02:46 -07004101 returns:
4102 integer value of the counter or
4103 None on Error
4104 """
4105 try:
4106 counter = str( counter )
4107 delta = int( delta )
4108 cmdStr = "counter-test-increment -g "
Jon Halle1a3b752015-07-22 13:02:46 -07004109 cmdStr += counter
4110 if delta != 1:
4111 cmdStr += " " + str( delta )
4112 output = self.sendline( cmdStr )
4113 try:
4114 # TODO: Maybe make this less hardcoded
4115 # ConsistentMap Exceptions
4116 assert "org.onosproject.store.service" not in output
4117 # Node not leader
4118 assert "java.lang.IllegalStateException" not in output
4119 except AssertionError:
4120 main.log.error( "Error in processing '" + cmdStr + "' " +
4121 "command: " + str( output ) )
4122 retryTime = 30 # Conservative time, given by Madan
4123 main.log.info( "Waiting " + str( retryTime ) +
4124 "seconds before retrying." )
4125 time.sleep( retryTime ) # Due to change in mastership
4126 output = self.sendline( cmdStr )
Jon Hallc6793552016-01-19 14:18:37 -08004127 assert "Command not found:" not in output, output
4128 assert "Error executing command" not in output, output
Jon Halle1a3b752015-07-22 13:02:46 -07004129 main.log.info( self.name + ": " + output )
4130 pattern = counter + " was updated to (-?\d+)"
4131 match = re.search( pattern, output )
4132 if match:
4133 return int( match.group( 1 ) )
4134 else:
4135 main.log.error( self.name + ": counterTestGetAndAdd did not" +
4136 " match expected output." )
4137 main.log.debug( self.name + " expected: " + pattern )
4138 main.log.debug( self.name + " actual: " + repr( output ) )
4139 return None
4140 except AssertionError:
Jon Hallc6793552016-01-19 14:18:37 -08004141 main.log.exception( "Error in processing '" + cmdStr + "' command." )
Jon Halle1a3b752015-07-22 13:02:46 -07004142 return None
4143 except TypeError:
4144 main.log.exception( self.name + ": Object not as expected" )
4145 return None
4146 except pexpect.EOF:
4147 main.log.error( self.name + ": EOF exception found" )
4148 main.log.error( self.name + ": " + self.handle.before )
4149 main.cleanup()
4150 main.exit()
4151 except Exception:
4152 main.log.exception( self.name + ": Uncaught exception!" )
4153 main.cleanup()
4154 main.exit()
4155
kelvin-onlaba297c4d2015-06-01 13:53:55 -07004156 def summary( self, jsonFormat=True ):
4157 """
4158 Description: Execute summary command in onos
4159 Returns: json object ( summary -j ), returns main.FALSE if there is
4160 no output
4161
4162 """
4163 try:
4164 cmdStr = "summary"
4165 if jsonFormat:
4166 cmdStr += " -j"
4167 handle = self.sendline( cmdStr )
Jon Hallc6793552016-01-19 14:18:37 -08004168 assert "Command not found:" not in handle, handle
Jon Hall6e709752016-02-01 13:38:46 -08004169 assert "Error:" not in handle, handle
kelvin-onlaba297c4d2015-06-01 13:53:55 -07004170 if not handle:
4171 main.log.error( self.name + ": There is no output in " +
4172 "summary command" )
4173 return main.FALSE
4174 return handle
Jon Hallc6793552016-01-19 14:18:37 -08004175 except AssertionError:
Jon Hall6e709752016-02-01 13:38:46 -08004176 main.log.exception( "{} Error in summary output:".format( self.name ) )
Jon Hallc6793552016-01-19 14:18:37 -08004177 return None
kelvin-onlaba297c4d2015-06-01 13:53:55 -07004178 except TypeError:
4179 main.log.exception( self.name + ": Object not as expected" )
4180 return None
4181 except pexpect.EOF:
4182 main.log.error( self.name + ": EOF exception found" )
4183 main.log.error( self.name + ": " + self.handle.before )
4184 main.cleanup()
4185 main.exit()
4186 except Exception:
4187 main.log.exception( self.name + ": Uncaught exception!" )
4188 main.cleanup()
4189 main.exit()
Jon Hall2a5002c2015-08-21 16:49:11 -07004190
Jon Hall935db192016-04-19 00:22:04 -07004191 def transactionalMapGet( self, keyName ):
Jon Hall2a5002c2015-08-21 16:49:11 -07004192 """
4193 CLI command to get the value of a key in a consistent map using
4194 transactions. This a test function and can only get keys from the
4195 test map hard coded into the cli command
4196 Required arguments:
4197 keyName - The name of the key to get
Jon Hall2a5002c2015-08-21 16:49:11 -07004198 returns:
4199 The string value of the key or
4200 None on Error
4201 """
4202 try:
4203 keyName = str( keyName )
4204 cmdStr = "transactional-map-test-get "
Jon Hall2a5002c2015-08-21 16:49:11 -07004205 cmdStr += keyName
4206 output = self.sendline( cmdStr )
Jon Hallc6793552016-01-19 14:18:37 -08004207 assert "Command not found:" not in output, output
Jon Hall2a5002c2015-08-21 16:49:11 -07004208 try:
4209 # TODO: Maybe make this less hardcoded
4210 # ConsistentMap Exceptions
4211 assert "org.onosproject.store.service" not in output
4212 # Node not leader
4213 assert "java.lang.IllegalStateException" not in output
4214 except AssertionError:
4215 main.log.error( "Error in processing '" + cmdStr + "' " +
4216 "command: " + str( output ) )
4217 return None
4218 pattern = "Key-value pair \(" + keyName + ", (?P<value>.+)\) found."
4219 if "Key " + keyName + " not found." in output:
4220 return None
4221 else:
4222 match = re.search( pattern, output )
4223 if match:
4224 return match.groupdict()[ 'value' ]
4225 else:
4226 main.log.error( self.name + ": transactionlMapGet did not" +
4227 " match expected output." )
4228 main.log.debug( self.name + " expected: " + pattern )
4229 main.log.debug( self.name + " actual: " + repr( output ) )
4230 return None
Jon Hallc6793552016-01-19 14:18:37 -08004231 except AssertionError:
4232 main.log.exception( "" )
4233 return None
Jon Hall2a5002c2015-08-21 16:49:11 -07004234 except TypeError:
4235 main.log.exception( self.name + ": Object not as expected" )
4236 return None
4237 except pexpect.EOF:
4238 main.log.error( self.name + ": EOF exception found" )
4239 main.log.error( self.name + ": " + self.handle.before )
4240 main.cleanup()
4241 main.exit()
4242 except Exception:
4243 main.log.exception( self.name + ": Uncaught exception!" )
4244 main.cleanup()
4245 main.exit()
4246
Jon Hall935db192016-04-19 00:22:04 -07004247 def transactionalMapPut( self, numKeys, value ):
Jon Hall2a5002c2015-08-21 16:49:11 -07004248 """
4249 CLI command to put a value into 'numKeys' number of keys in a
4250 consistent map using transactions. This a test function and can only
4251 put into keys named 'Key#' of the test map hard coded into the cli command
4252 Required arguments:
4253 numKeys - Number of keys to add the value to
4254 value - The string value to put into the keys
Jon Hall2a5002c2015-08-21 16:49:11 -07004255 returns:
4256 A dictionary whose keys are the name of the keys put into the map
4257 and the values of the keys are dictionaries whose key-values are
4258 'value': value put into map and optionaly
4259 'oldValue': Previous value in the key or
4260 None on Error
4261
4262 Example output
4263 { 'Key1': {'oldValue': 'oldTestValue', 'value': 'Testing'},
4264 'Key2': {'value': 'Testing'} }
4265 """
4266 try:
4267 numKeys = str( numKeys )
4268 value = str( value )
4269 cmdStr = "transactional-map-test-put "
Jon Hall2a5002c2015-08-21 16:49:11 -07004270 cmdStr += numKeys + " " + value
4271 output = self.sendline( cmdStr )
Jon Hallc6793552016-01-19 14:18:37 -08004272 assert "Command not found:" not in output, output
Jon Hall2a5002c2015-08-21 16:49:11 -07004273 try:
4274 # TODO: Maybe make this less hardcoded
4275 # ConsistentMap Exceptions
4276 assert "org.onosproject.store.service" not in output
4277 # Node not leader
4278 assert "java.lang.IllegalStateException" not in output
4279 except AssertionError:
4280 main.log.error( "Error in processing '" + cmdStr + "' " +
4281 "command: " + str( output ) )
4282 return None
4283 newPattern = 'Created Key (?P<key>(\w)+) with value (?P<value>(.)+)\.'
4284 updatedPattern = "Put (?P<value>(.)+) into key (?P<key>(\w)+)\. The old value was (?P<oldValue>(.)+)\."
4285 results = {}
4286 for line in output.splitlines():
4287 new = re.search( newPattern, line )
4288 updated = re.search( updatedPattern, line )
4289 if new:
4290 results[ new.groupdict()[ 'key' ] ] = { 'value': new.groupdict()[ 'value' ] }
4291 elif updated:
4292 results[ updated.groupdict()[ 'key' ] ] = { 'value': updated.groupdict()[ 'value' ],
Jon Hallc6793552016-01-19 14:18:37 -08004293 'oldValue': updated.groupdict()[ 'oldValue' ] }
Jon Hall2a5002c2015-08-21 16:49:11 -07004294 else:
4295 main.log.error( self.name + ": transactionlMapGet did not" +
4296 " match expected output." )
Jon Hallc6793552016-01-19 14:18:37 -08004297 main.log.debug( "{} expected: {!r} or {!r}".format( self.name,
4298 newPattern,
4299 updatedPattern ) )
Jon Hall2a5002c2015-08-21 16:49:11 -07004300 main.log.debug( self.name + " actual: " + repr( output ) )
4301 return results
Jon Hallc6793552016-01-19 14:18:37 -08004302 except AssertionError:
4303 main.log.exception( "" )
4304 return None
Jon Hall2a5002c2015-08-21 16:49:11 -07004305 except TypeError:
4306 main.log.exception( self.name + ": Object not as expected" )
4307 return None
4308 except pexpect.EOF:
4309 main.log.error( self.name + ": EOF exception found" )
4310 main.log.error( self.name + ": " + self.handle.before )
4311 main.cleanup()
4312 main.exit()
4313 except Exception:
4314 main.log.exception( self.name + ": Uncaught exception!" )
4315 main.cleanup()
4316 main.exit()
Jon Hallc6793552016-01-19 14:18:37 -08004317
acsmarsdaea66c2015-09-03 11:44:06 -07004318 def maps( self, jsonFormat=True ):
4319 """
4320 Description: Returns result of onos:maps
4321 Optional:
4322 * jsonFormat: enable json formatting of output
4323 """
4324 try:
4325 cmdStr = "maps"
4326 if jsonFormat:
4327 cmdStr += " -j"
4328 handle = self.sendline( cmdStr )
Jon Hallc6793552016-01-19 14:18:37 -08004329 assert "Command not found:" not in handle, handle
acsmarsdaea66c2015-09-03 11:44:06 -07004330 return handle
Jon Hallc6793552016-01-19 14:18:37 -08004331 except AssertionError:
4332 main.log.exception( "" )
4333 return None
acsmarsdaea66c2015-09-03 11:44:06 -07004334 except TypeError:
4335 main.log.exception( self.name + ": Object not as expected" )
4336 return None
4337 except pexpect.EOF:
4338 main.log.error( self.name + ": EOF exception found" )
4339 main.log.error( self.name + ": " + self.handle.before )
4340 main.cleanup()
4341 main.exit()
4342 except Exception:
4343 main.log.exception( self.name + ": Uncaught exception!" )
4344 main.cleanup()
4345 main.exit()
GlennRC050596c2015-11-18 17:06:41 -08004346
4347 def getSwController( self, uri, jsonFormat=True ):
4348 """
4349 Descrition: Gets the controller information from the device
4350 """
4351 try:
4352 cmd = "device-controllers "
4353 if jsonFormat:
4354 cmd += "-j "
4355 response = self.sendline( cmd + uri )
Jon Hallc6793552016-01-19 14:18:37 -08004356 assert "Command not found:" not in response, response
GlennRC050596c2015-11-18 17:06:41 -08004357 return response
Jon Hallc6793552016-01-19 14:18:37 -08004358 except AssertionError:
4359 main.log.exception( "" )
4360 return None
GlennRC050596c2015-11-18 17:06:41 -08004361 except TypeError:
4362 main.log.exception( self.name + ": Object not as expected" )
4363 return None
4364 except pexpect.EOF:
4365 main.log.error( self.name + ": EOF exception found" )
4366 main.log.error( self.name + ": " + self.handle.before )
4367 main.cleanup()
4368 main.exit()
4369 except Exception:
4370 main.log.exception( self.name + ": Uncaught exception!" )
4371 main.cleanup()
4372 main.exit()
4373
4374 def setSwController( self, uri, ip, proto="tcp", port="6653", jsonFormat=True ):
4375 """
4376 Descrition: sets the controller(s) for the specified device
4377
4378 Parameters:
4379 Required: uri - String: The uri of the device(switch).
4380 ip - String or List: The ip address of the controller.
4381 This parameter can be formed in a couple of different ways.
4382 VALID:
4383 10.0.0.1 - just the ip address
4384 tcp:10.0.0.1 - the protocol and the ip address
4385 tcp:10.0.0.1:6653 - the protocol and port can be specified,
4386 so that you can add controllers with different
4387 protocols and ports
4388 INVALID:
4389 10.0.0.1:6653 - this is not supported by ONOS
4390
4391 Optional: proto - The type of connection e.g. tcp, ssl. If a list of ips are given
4392 port - The port number.
4393 jsonFormat - If set ONOS will output in json NOTE: This is currently not supported
4394
4395 Returns: main.TRUE if ONOS returns without any errors, otherwise returns main.FALSE
4396 """
4397 try:
4398 cmd = "device-setcontrollers"
4399
4400 if jsonFormat:
4401 cmd += " -j"
4402 cmd += " " + uri
4403 if isinstance( ip, str ):
4404 ip = [ip]
4405 for item in ip:
4406 if ":" in item:
4407 sitem = item.split( ":" )
4408 if len(sitem) == 3:
4409 cmd += " " + item
4410 elif "." in sitem[1]:
4411 cmd += " {}:{}".format(item, port)
4412 else:
4413 main.log.error( "Malformed entry: " + item )
4414 raise TypeError
4415 else:
4416 cmd += " {}:{}:{}".format( proto, item, port )
GlennRC050596c2015-11-18 17:06:41 -08004417 response = self.sendline( cmd )
Jon Hallc6793552016-01-19 14:18:37 -08004418 assert "Command not found:" not in response, response
GlennRC050596c2015-11-18 17:06:41 -08004419 if "Error" in response:
4420 main.log.error( response )
4421 return main.FALSE
GlennRC050596c2015-11-18 17:06:41 -08004422 return main.TRUE
Jon Hallc6793552016-01-19 14:18:37 -08004423 except AssertionError:
4424 main.log.exception( "" )
4425 return None
GlennRC050596c2015-11-18 17:06:41 -08004426 except TypeError:
4427 main.log.exception( self.name + ": Object not as expected" )
4428 return main.FALSE
4429 except pexpect.EOF:
4430 main.log.error( self.name + ": EOF exception found" )
4431 main.log.error( self.name + ": " + self.handle.before )
4432 main.cleanup()
4433 main.exit()
4434 except Exception:
4435 main.log.exception( self.name + ": Uncaught exception!" )
4436 main.cleanup()
4437 main.exit()
GlennRC20fc6522015-12-23 23:26:57 -08004438
4439 def removeDevice( self, device ):
4440 '''
4441 Description:
4442 Remove a device from ONOS by passing the uri of the device(s).
4443 Parameters:
4444 device - (str or list) the id or uri of the device ex. "of:0000000000000001"
4445 Returns:
4446 Returns main.FALSE if an exception is thrown or an error is present
4447 in the response. Otherwise, returns main.TRUE.
4448 NOTE:
4449 If a host cannot be removed, then this function will return main.FALSE
4450 '''
4451 try:
4452 if type( device ) is str:
4453 device = list( device )
4454
4455 for d in device:
4456 time.sleep( 1 )
4457 response = self.sendline( "device-remove {}".format( d ) )
Jon Hallc6793552016-01-19 14:18:37 -08004458 assert "Command not found:" not in response, response
GlennRC20fc6522015-12-23 23:26:57 -08004459 if "Error" in response:
4460 main.log.warn( "Error for device: {}\nResponse: {}".format( d, response ) )
4461 return main.FALSE
GlennRC20fc6522015-12-23 23:26:57 -08004462 return main.TRUE
Jon Hallc6793552016-01-19 14:18:37 -08004463 except AssertionError:
4464 main.log.exception( "" )
4465 return main.FALSE
GlennRC20fc6522015-12-23 23:26:57 -08004466 except TypeError:
4467 main.log.exception( self.name + ": Object not as expected" )
4468 return main.FALSE
4469 except pexpect.EOF:
4470 main.log.error( self.name + ": EOF exception found" )
4471 main.log.error( self.name + ": " + self.handle.before )
4472 main.cleanup()
4473 main.exit()
4474 except Exception:
4475 main.log.exception( self.name + ": Uncaught exception!" )
4476 main.cleanup()
4477 main.exit()
4478
4479 def removeHost( self, host ):
4480 '''
4481 Description:
4482 Remove a host from ONOS by passing the id of the host(s)
4483 Parameters:
4484 hostId - (str or list) the id or mac of the host ex. "00:00:00:00:00:01"
4485 Returns:
4486 Returns main.FALSE if an exception is thrown or an error is present
4487 in the response. Otherwise, returns main.TRUE.
4488 NOTE:
4489 If a host cannot be removed, then this function will return main.FALSE
4490 '''
4491 try:
4492 if type( host ) is str:
4493 host = list( host )
4494
4495 for h in host:
4496 time.sleep( 1 )
4497 response = self.sendline( "host-remove {}".format( h ) )
Jon Hallc6793552016-01-19 14:18:37 -08004498 assert "Command not found:" not in response, response
GlennRC20fc6522015-12-23 23:26:57 -08004499 if "Error" in response:
4500 main.log.warn( "Error for host: {}\nResponse: {}".format( h, response ) )
4501 return main.FALSE
GlennRC20fc6522015-12-23 23:26:57 -08004502 return main.TRUE
Jon Hallc6793552016-01-19 14:18:37 -08004503 except AssertionError:
4504 main.log.exception( "" )
4505 return None
GlennRC20fc6522015-12-23 23:26:57 -08004506 except TypeError:
4507 main.log.exception( self.name + ": Object not as expected" )
4508 return main.FALSE
4509 except pexpect.EOF:
4510 main.log.error( self.name + ": EOF exception found" )
4511 main.log.error( self.name + ": " + self.handle.before )
4512 main.cleanup()
4513 main.exit()
4514 except Exception:
4515 main.log.exception( self.name + ": Uncaught exception!" )
4516 main.cleanup()
4517 main.exit()
GlennRCed771242016-01-13 17:02:47 -08004518
Jon Hallc6793552016-01-19 14:18:37 -08004519 def link( self, begin, end, state ):
GlennRCed771242016-01-13 17:02:47 -08004520 '''
4521 Description:
4522 Bring link down or up in the null-provider.
4523 params:
4524 begin - (string) One end of a device or switch.
4525 end - (string) the other end of the device or switch
4526 returns:
4527 main.TRUE if no exceptions were thrown and no Errors are
4528 present in the resoponse. Otherwise, returns main.FALSE
4529 '''
4530 try:
Jon Hallc6793552016-01-19 14:18:37 -08004531 cmd = "null-link null:{} null:{} {}".format( begin, end, state )
GlennRCed771242016-01-13 17:02:47 -08004532 response = self.sendline( cmd, showResponse=True )
Jon Hallc6793552016-01-19 14:18:37 -08004533 assert "Command not found:" not in response, response
GlennRCed771242016-01-13 17:02:47 -08004534 if "Error" in response or "Failure" in response:
4535 main.log.error( response )
4536 return main.FALSE
GlennRCed771242016-01-13 17:02:47 -08004537 return main.TRUE
Jon Hallc6793552016-01-19 14:18:37 -08004538 except AssertionError:
4539 main.log.exception( "" )
4540 return None
GlennRCed771242016-01-13 17:02:47 -08004541 except TypeError:
4542 main.log.exception( self.name + ": Object not as expected" )
4543 return main.FALSE
4544 except pexpect.EOF:
4545 main.log.error( self.name + ": EOF exception found" )
4546 main.log.error( self.name + ": " + self.handle.before )
4547 main.cleanup()
4548 main.exit()
4549 except Exception:
4550 main.log.exception( self.name + ": Uncaught exception!" )
4551 main.cleanup()
4552 main.exit()
4553