blob: 5b51ed743a81c1ff3156fa5b620bd64529bad71c [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:
62 if os.getenv( str( self.ip_address ) ) != None:
63 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" )
145 self.handle.expect( "\$" )
146 return main.TRUE
147 elif i == 1: # not in CLI
148 return main.TRUE
149 elif i == 3: # Timeout
150 return main.FALSE
151 else:
andrewonlab9627f432014-11-14 12:45:10 -0500152 return main.TRUE
Jon Halld4d4b372015-01-28 16:02:41 -0800153 except TypeError:
154 main.log.exception( self.name + ": Object not as expected" )
155 return None
andrewonlab38d2b4a2014-11-13 16:28:47 -0500156 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -0800157 main.log.error( self.name + ": eof exception found" )
Jon Hall61282e32015-03-19 11:34:11 -0700158 main.log.error( self.name + ": " + self.handle.before )
andrewonlab38d2b4a2014-11-13 16:28:47 -0500159 main.cleanup()
160 main.exit()
Jon Hall61282e32015-03-19 11:34:11 -0700161 except ValueError:
Jon Hall5aa168b2015-03-23 14:23:09 -0700162 main.log.error( self.name +
163 "ValueError exception in logout method" )
Jon Hallfebb1c72015-03-05 13:30:09 -0800164 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -0800165 main.log.exception( self.name + ": Uncaught exception!" )
andrewonlab38d2b4a2014-11-13 16:28:47 -0500166 main.cleanup()
167 main.exit()
168
kelvin-onlabd3b64892015-01-20 13:26:24 -0800169 def setCell( self, cellname ):
kelvin8ec71442015-01-15 16:57:00 -0800170 """
andrewonlab95ce8322014-10-13 14:12:04 -0400171 Calls 'cell <name>' to set the environment variables on ONOSbench
kelvin8ec71442015-01-15 16:57:00 -0800172
andrewonlab95ce8322014-10-13 14:12:04 -0400173 Before issuing any cli commands, set the environment variable first.
kelvin8ec71442015-01-15 16:57:00 -0800174 """
andrewonlab95ce8322014-10-13 14:12:04 -0400175 try:
176 if not cellname:
kelvin8ec71442015-01-15 16:57:00 -0800177 main.log.error( "Must define cellname" )
andrewonlab95ce8322014-10-13 14:12:04 -0400178 main.cleanup()
179 main.exit()
180 else:
kelvin8ec71442015-01-15 16:57:00 -0800181 self.handle.sendline( "cell " + str( cellname ) )
kelvin-onlabd3b64892015-01-20 13:26:24 -0800182 # Expect the cellname in the ONOSCELL variable.
kelvin8ec71442015-01-15 16:57:00 -0800183 # Note that this variable name is subject to change
andrewonlab95ce8322014-10-13 14:12:04 -0400184 # and that this driver will have to change accordingly
Cameron Franke9c94fb02015-01-21 10:20:20 -0800185 self.handle.expect(str(cellname))
andrew@onlab.usc400b112015-01-21 15:33:19 -0800186 handleBefore = self.handle.before
187 handleAfter = self.handle.after
kelvin8ec71442015-01-15 16:57:00 -0800188 # Get the rest of the handle
Cameron Franke9c94fb02015-01-21 10:20:20 -0800189 self.handle.sendline("")
190 self.handle.expect("\$")
andrew@onlab.usc400b112015-01-21 15:33:19 -0800191 handleMore = self.handle.before
andrewonlab95ce8322014-10-13 14:12:04 -0400192
kelvin-onlabd3b64892015-01-20 13:26:24 -0800193 main.log.info( "Cell call returned: " + handleBefore +
194 handleAfter + handleMore )
andrewonlab95ce8322014-10-13 14:12:04 -0400195
196 return main.TRUE
197
Jon Halld4d4b372015-01-28 16:02:41 -0800198 except TypeError:
199 main.log.exception( self.name + ": Object not as expected" )
200 return None
andrewonlab95ce8322014-10-13 14:12:04 -0400201 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -0800202 main.log.error( self.name + ": eof exception found" )
203 main.log.error( self.name + ": " + self.handle.before )
andrewonlab95ce8322014-10-13 14:12:04 -0400204 main.cleanup()
205 main.exit()
Jon Hallfebb1c72015-03-05 13:30:09 -0800206 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -0800207 main.log.exception( self.name + ": Uncaught exception!" )
andrewonlab95ce8322014-10-13 14:12:04 -0400208 main.cleanup()
209 main.exit()
kelvin8ec71442015-01-15 16:57:00 -0800210
pingping-lin57a56ce2015-05-20 16:43:48 -0700211 def startOnosCli( self, ONOSIp, karafTimeout="",
212 commandlineTimeout=10, onosStartTimeout=60 ):
kelvin8ec71442015-01-15 16:57:00 -0800213 """
Jon Hallefbd9792015-03-05 16:11:36 -0800214 karafTimeout is an optional argument. karafTimeout value passed
kelvin-onlabd3b64892015-01-20 13:26:24 -0800215 by user would be used to set the current karaf shell idle timeout.
216 Note that when ever this property is modified the shell will exit and
Hari Krishnad7b9c202015-01-05 10:38:14 -0800217 the subsequent login would reflect new idle timeout.
kelvin-onlabd3b64892015-01-20 13:26:24 -0800218 Below is an example to start a session with 60 seconds idle timeout
219 ( input value is in milliseconds ):
kelvin8ec71442015-01-15 16:57:00 -0800220
Hari Krishna25d42f72015-01-05 15:08:28 -0800221 tValue = "60000"
kelvin-onlabd3b64892015-01-20 13:26:24 -0800222 main.ONOScli1.startOnosCli( ONOSIp, karafTimeout=tValue )
kelvin8ec71442015-01-15 16:57:00 -0800223
kelvin-onlabd3b64892015-01-20 13:26:24 -0800224 Note: karafTimeout is left as str so that this could be read
225 and passed to startOnosCli from PARAMS file as str.
kelvin8ec71442015-01-15 16:57:00 -0800226 """
andrewonlab95ce8322014-10-13 14:12:04 -0400227 try:
kelvin8ec71442015-01-15 16:57:00 -0800228 self.handle.sendline( "" )
229 x = self.handle.expect( [
pingping-lin57a56ce2015-05-20 16:43:48 -0700230 "\$", "onos>" ], commandlineTimeout)
andrewonlab48829f62014-11-17 13:49:01 -0500231
232 if x == 1:
kelvin8ec71442015-01-15 16:57:00 -0800233 main.log.info( "ONOS cli is already running" )
andrewonlab48829f62014-11-17 13:49:01 -0500234 return main.TRUE
andrewonlab95ce8322014-10-13 14:12:04 -0400235
kelvin8ec71442015-01-15 16:57:00 -0800236 # Wait for onos start ( -w ) and enter onos cli
kelvin-onlabd3b64892015-01-20 13:26:24 -0800237 self.handle.sendline( "onos -w " + str( ONOSIp ) )
kelvin8ec71442015-01-15 16:57:00 -0800238 i = self.handle.expect( [
239 "onos>",
pingping-lin57a56ce2015-05-20 16:43:48 -0700240 pexpect.TIMEOUT ], onosStartTimeout )
andrewonlab2a7ea9b2014-10-24 12:21:05 -0400241
242 if i == 0:
kelvin-onlabd3b64892015-01-20 13:26:24 -0800243 main.log.info( str( ONOSIp ) + " CLI Started successfully" )
Hari Krishnae36ef212015-01-04 14:09:13 -0800244 if karafTimeout:
kelvin8ec71442015-01-15 16:57:00 -0800245 self.handle.sendline(
Hari Krishnaac4e1782015-01-26 12:09:12 -0800246 "config:property-set -p org.apache.karaf.shell\
247 sshIdleTimeout " +
kelvin8ec71442015-01-15 16:57:00 -0800248 karafTimeout )
249 self.handle.expect( "\$" )
kelvin-onlabd3b64892015-01-20 13:26:24 -0800250 self.handle.sendline( "onos -w " + str( ONOSIp ) )
kelvin8ec71442015-01-15 16:57:00 -0800251 self.handle.expect( "onos>" )
andrewonlab2a7ea9b2014-10-24 12:21:05 -0400252 return main.TRUE
253 else:
kelvin8ec71442015-01-15 16:57:00 -0800254 # If failed, send ctrl+c to process and try again
255 main.log.info( "Starting CLI failed. Retrying..." )
256 self.handle.send( "\x03" )
kelvin-onlabd3b64892015-01-20 13:26:24 -0800257 self.handle.sendline( "onos -w " + str( ONOSIp ) )
kelvin8ec71442015-01-15 16:57:00 -0800258 i = self.handle.expect( [ "onos>", pexpect.TIMEOUT ],
259 timeout=30 )
andrewonlab3a7c3c72014-10-24 17:21:03 -0400260 if i == 0:
kelvin-onlabd3b64892015-01-20 13:26:24 -0800261 main.log.info( str( ONOSIp ) + " CLI Started " +
kelvin8ec71442015-01-15 16:57:00 -0800262 "successfully after retry attempt" )
Hari Krishnae36ef212015-01-04 14:09:13 -0800263 if karafTimeout:
kelvin8ec71442015-01-15 16:57:00 -0800264 self.handle.sendline(
kelvin-onlabd3b64892015-01-20 13:26:24 -0800265 "config:property-set -p org.apache.karaf.shell\
266 sshIdleTimeout " +
kelvin8ec71442015-01-15 16:57:00 -0800267 karafTimeout )
268 self.handle.expect( "\$" )
kelvin-onlabd3b64892015-01-20 13:26:24 -0800269 self.handle.sendline( "onos -w " + str( ONOSIp ) )
kelvin8ec71442015-01-15 16:57:00 -0800270 self.handle.expect( "onos>" )
andrewonlab3a7c3c72014-10-24 17:21:03 -0400271 return main.TRUE
272 else:
kelvin8ec71442015-01-15 16:57:00 -0800273 main.log.error( "Connection to CLI " +
kelvin-onlabd3b64892015-01-20 13:26:24 -0800274 str( ONOSIp ) + " timeout" )
andrewonlab3a7c3c72014-10-24 17:21:03 -0400275 return main.FALSE
andrewonlab95ce8322014-10-13 14:12:04 -0400276
Jon Halld4d4b372015-01-28 16:02:41 -0800277 except TypeError:
278 main.log.exception( self.name + ": Object not as expected" )
279 return None
andrewonlab95ce8322014-10-13 14:12:04 -0400280 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -0800281 main.log.error( self.name + ": EOF exception found" )
282 main.log.error( self.name + ": " + self.handle.before )
andrewonlab95ce8322014-10-13 14:12:04 -0400283 main.cleanup()
284 main.exit()
Jon Hallfebb1c72015-03-05 13:30:09 -0800285 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -0800286 main.log.exception( self.name + ": Uncaught exception!" )
andrewonlab95ce8322014-10-13 14:12:04 -0400287 main.cleanup()
288 main.exit()
289
Jon Hallefbd9792015-03-05 16:11:36 -0800290 def log( self, cmdStr, level="" ):
kelvin-onlab9f541032015-02-04 16:19:53 -0800291 """
292 log the commands in the onos CLI.
kelvin-onlab338f5512015-02-06 10:53:16 -0800293 returns main.TRUE on success
Jon Hallefbd9792015-03-05 16:11:36 -0800294 returns main.FALSE if Error occurred
kelvin-onlab338f5512015-02-06 10:53:16 -0800295 Available level: DEBUG, TRACE, INFO, WARN, ERROR
296 Level defaults to INFO
kelvin-onlab9f541032015-02-04 16:19:53 -0800297 """
298 try:
kelvin-onlab338f5512015-02-06 10:53:16 -0800299 lvlStr = ""
300 if level:
301 lvlStr = "--level=" + level
302
kelvin-onlab9f541032015-02-04 16:19:53 -0800303 self.handle.sendline( "" )
Jon Hallc9eabec2015-06-10 14:33:14 -0700304 i = self.handle.expect( [ "onos>","\$", pexpect.TIMEOUT ] )
Jon Hall80daded2015-05-27 16:07:00 -0700305 if i == 1:
Jon Hallc9eabec2015-06-10 14:33:14 -0700306 main.log.error( self.name + ": onos cli session closed." )
307 main.cleanup()
308 main.exit()
309 if i == 2:
Jon Hall80daded2015-05-27 16:07:00 -0700310 self.handle.sendline( "" )
311 self.handle.expect( "onos>" )
kelvin-onlab338f5512015-02-06 10:53:16 -0800312 self.handle.sendline( "log:log " + lvlStr + " " + cmdStr )
Jon Hall390696c2015-05-05 17:13:41 -0700313 self.handle.expect( "log:log" )
kelvin-onlab9f541032015-02-04 16:19:53 -0800314 self.handle.expect( "onos>" )
kelvin-onlabfb521662015-02-27 09:52:40 -0800315
kelvin-onlab9f541032015-02-04 16:19:53 -0800316 response = self.handle.before
317 if re.search( "Error", response ):
318 return main.FALSE
319 return main.TRUE
Jon Hall80daded2015-05-27 16:07:00 -0700320 except pexpect.TIMEOUT:
321 main.log.exception( self.name + ": TIMEOUT exception found" )
322 main.cleanup()
323 main.exit()
kelvin-onlab9f541032015-02-04 16:19:53 -0800324 except pexpect.EOF:
325 main.log.error( self.name + ": EOF exception found" )
326 main.log.error( self.name + ": " + self.handle.before )
327 main.cleanup()
328 main.exit()
Jon Hallfebb1c72015-03-05 13:30:09 -0800329 except Exception:
kelvin-onlabfb521662015-02-27 09:52:40 -0800330 main.log.exception( self.name + ": Uncaught exception!" )
andrewonlab95ce8322014-10-13 14:12:04 -0400331 main.cleanup()
332 main.exit()
333
GlennRC208d4af2015-11-24 12:30:00 -0800334 def sendline( self, cmdStr, showResponse=False, debug=False ):
kelvin8ec71442015-01-15 16:57:00 -0800335 """
Jon Halle3f39ff2015-01-13 11:50:53 -0800336 Send a completely user specified string to
337 the onos> prompt. Use this function if you have
andrewonlaba18f6bf2014-10-13 19:31:54 -0400338 a very specific command to send.
Jon Halle3f39ff2015-01-13 11:50:53 -0800339
andrewonlaba18f6bf2014-10-13 19:31:54 -0400340 Warning: There are no sanity checking to commands
341 sent using this method.
kelvin8ec71442015-01-15 16:57:00 -0800342 """
andrewonlaba18f6bf2014-10-13 19:31:54 -0400343 try:
kelvin-onlab338f5512015-02-06 10:53:16 -0800344 logStr = "\"Sending CLI command: '" + cmdStr + "'\""
345 self.log( logStr )
kelvin-onlabd3b64892015-01-20 13:26:24 -0800346 self.handle.sendline( cmdStr )
Jon Hall63604932015-02-26 17:09:50 -0800347 i = self.handle.expect( ["onos>", "\$", pexpect.TIMEOUT] )
348 response = self.handle.before
349 if i == 2:
350 self.handle.sendline()
Jon Hallc6358dd2015-04-10 12:44:28 -0700351 self.handle.expect( ["\$", pexpect.TIMEOUT] )
Jon Hall63604932015-02-26 17:09:50 -0800352 response += self.handle.before
353 print response
354 try:
355 print self.handle.after
Jon Hall77ba41c2015-04-06 10:25:40 -0700356 except TypeError:
Jon Hall63604932015-02-26 17:09:50 -0800357 pass
358 # TODO: do something with i
kelvin-onlabd3b64892015-01-20 13:26:24 -0800359 main.log.info( "Command '" + str( cmdStr ) + "' sent to "
kelvin-onlab898a6c62015-01-16 14:13:53 -0800360 + self.name + "." )
Jon Hallc6358dd2015-04-10 12:44:28 -0700361 if debug:
Jon Hall390696c2015-05-05 17:13:41 -0700362 main.log.debug( self.name + ": Raw output" )
363 main.log.debug( self.name + ": " + repr( response ) )
Jon Hallc6358dd2015-04-10 12:44:28 -0700364
365 # Remove ANSI color control strings from output
kelvin-onlabd3b64892015-01-20 13:26:24 -0800366 ansiEscape = re.compile( r'\x1b[^m]*m' )
Jon Hall63604932015-02-26 17:09:50 -0800367 response = ansiEscape.sub( '', response )
Jon Hallc6358dd2015-04-10 12:44:28 -0700368 if debug:
Jon Hall390696c2015-05-05 17:13:41 -0700369 main.log.debug( self.name + ": ansiEscape output" )
370 main.log.debug( self.name + ": " + repr( response ) )
Jon Hallc6358dd2015-04-10 12:44:28 -0700371
kelvin-onlabfb521662015-02-27 09:52:40 -0800372 # Remove extra return chars that get added
Jon Hall63604932015-02-26 17:09:50 -0800373 response = re.sub( r"\s\r", "", response )
Jon Hallc6358dd2015-04-10 12:44:28 -0700374 if debug:
Jon Hall390696c2015-05-05 17:13:41 -0700375 main.log.debug( self.name + ": Removed extra returns " +
376 "from output" )
377 main.log.debug( self.name + ": " + repr( response ) )
Jon Hallc6358dd2015-04-10 12:44:28 -0700378
379 # Strip excess whitespace
Jon Hall63604932015-02-26 17:09:50 -0800380 response = response.strip()
Jon Hallc6358dd2015-04-10 12:44:28 -0700381 if debug:
Jon Hall390696c2015-05-05 17:13:41 -0700382 main.log.debug( self.name + ": parsed and stripped output" )
383 main.log.debug( self.name + ": " + repr( response ) )
Jon Hallc6358dd2015-04-10 12:44:28 -0700384
Jon Hall63604932015-02-26 17:09:50 -0800385 # parse for just the output, remove the cmd from response
Jon Hallc6358dd2015-04-10 12:44:28 -0700386 output = response.split( cmdStr.strip(), 1 )
387 if debug:
Jon Hall390696c2015-05-05 17:13:41 -0700388 main.log.debug( self.name + ": split output" )
Jon Hallc6358dd2015-04-10 12:44:28 -0700389 for r in output:
Jon Hall390696c2015-05-05 17:13:41 -0700390 main.log.debug( self.name + ": " + repr( r ) )
GlennRC85870432015-11-23 11:45:51 -0800391 output = output[1].strip()
392 if showResponse:
393 main.log.info( "Resonse from ONOS: {}".format( output ) )
394 return output
Jon Hallc6358dd2015-04-10 12:44:28 -0700395 except IndexError:
396 main.log.exception( self.name + ": Object not as expected" )
397 return None
Jon Halld4d4b372015-01-28 16:02:41 -0800398 except TypeError:
399 main.log.exception( self.name + ": Object not as expected" )
400 return None
andrewonlaba18f6bf2014-10-13 19:31:54 -0400401 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -0800402 main.log.error( self.name + ": EOF exception found" )
403 main.log.error( self.name + ": " + self.handle.before )
andrewonlaba18f6bf2014-10-13 19:31:54 -0400404 main.cleanup()
405 main.exit()
Jon Hallfebb1c72015-03-05 13:30:09 -0800406 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -0800407 main.log.exception( self.name + ": Uncaught exception!" )
andrewonlaba18f6bf2014-10-13 19:31:54 -0400408 main.cleanup()
409 main.exit()
410
kelvin8ec71442015-01-15 16:57:00 -0800411 # IMPORTANT NOTE:
412 # For all cli commands, naming convention should match
kelvin-onlabd3b64892015-01-20 13:26:24 -0800413 # the cli command changing 'a:b' with 'aB'.
414 # Ex ) onos:topology > onosTopology
415 # onos:links > onosLinks
416 # feature:list > featureList
Jon Halle3f39ff2015-01-13 11:50:53 -0800417
kelvin-onlabd3b64892015-01-20 13:26:24 -0800418 def addNode( self, nodeId, ONOSIp, tcpPort="" ):
kelvin8ec71442015-01-15 16:57:00 -0800419 """
andrewonlabc2d05aa2014-10-13 16:51:10 -0400420 Adds a new cluster node by ID and address information.
421 Required:
kelvin-onlabd3b64892015-01-20 13:26:24 -0800422 * nodeId
423 * ONOSIp
andrewonlabc2d05aa2014-10-13 16:51:10 -0400424 Optional:
kelvin-onlabd3b64892015-01-20 13:26:24 -0800425 * tcpPort
kelvin8ec71442015-01-15 16:57:00 -0800426 """
andrewonlabc2d05aa2014-10-13 16:51:10 -0400427 try:
kelvin-onlabd3b64892015-01-20 13:26:24 -0800428 cmdStr = "add-node " + str( nodeId ) + " " +\
429 str( ONOSIp ) + " " + str( tcpPort )
430 handle = self.sendline( cmdStr )
kelvin-onlab898a6c62015-01-16 14:13:53 -0800431 if re.search( "Error", handle ):
kelvin8ec71442015-01-15 16:57:00 -0800432 main.log.error( "Error in adding node" )
433 main.log.error( handle )
Jon Halle3f39ff2015-01-13 11:50:53 -0800434 return main.FALSE
andrewonlabc2d05aa2014-10-13 16:51:10 -0400435 else:
kelvin-onlabd3b64892015-01-20 13:26:24 -0800436 main.log.info( "Node " + str( ONOSIp ) + " added" )
andrewonlabc2d05aa2014-10-13 16:51:10 -0400437 return main.TRUE
Jon Halld4d4b372015-01-28 16:02:41 -0800438 except TypeError:
439 main.log.exception( self.name + ": Object not as expected" )
440 return None
andrewonlabc2d05aa2014-10-13 16:51:10 -0400441 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -0800442 main.log.error( self.name + ": EOF exception found" )
443 main.log.error( self.name + ": " + self.handle.before )
andrewonlabc2d05aa2014-10-13 16:51:10 -0400444 main.cleanup()
445 main.exit()
Jon Hallfebb1c72015-03-05 13:30:09 -0800446 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -0800447 main.log.exception( self.name + ": Uncaught exception!" )
andrewonlabc2d05aa2014-10-13 16:51:10 -0400448 main.cleanup()
449 main.exit()
450
kelvin-onlabd3b64892015-01-20 13:26:24 -0800451 def removeNode( self, nodeId ):
kelvin8ec71442015-01-15 16:57:00 -0800452 """
andrewonlab86dc3082014-10-13 18:18:38 -0400453 Removes a cluster by ID
454 Issues command: 'remove-node [<node-id>]'
455 Required:
kelvin-onlabd3b64892015-01-20 13:26:24 -0800456 * nodeId
kelvin8ec71442015-01-15 16:57:00 -0800457 """
andrewonlab86dc3082014-10-13 18:18:38 -0400458 try:
andrewonlab86dc3082014-10-13 18:18:38 -0400459
kelvin-onlabd3b64892015-01-20 13:26:24 -0800460 cmdStr = "remove-node " + str( nodeId )
Jon Hall08f61bc2015-04-13 16:00:30 -0700461 handle = self.sendline( cmdStr )
Jon Hallc6358dd2015-04-10 12:44:28 -0700462 if re.search( "Error", handle ):
463 main.log.error( "Error in removing node" )
464 main.log.error( handle )
465 return main.FALSE
466 else:
467 return main.TRUE
Jon Halld4d4b372015-01-28 16:02:41 -0800468 except TypeError:
469 main.log.exception( self.name + ": Object not as expected" )
470 return None
andrewonlab86dc3082014-10-13 18:18:38 -0400471 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -0800472 main.log.error( self.name + ": EOF exception found" )
473 main.log.error( self.name + ": " + self.handle.before )
andrewonlab86dc3082014-10-13 18:18:38 -0400474 main.cleanup()
475 main.exit()
Jon Hallfebb1c72015-03-05 13:30:09 -0800476 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -0800477 main.log.exception( self.name + ": Uncaught exception!" )
andrewonlab86dc3082014-10-13 18:18:38 -0400478 main.cleanup()
479 main.exit()
andrewonlabc2d05aa2014-10-13 16:51:10 -0400480
Jon Hall61282e32015-03-19 11:34:11 -0700481 def nodes( self, jsonFormat=True):
kelvin8ec71442015-01-15 16:57:00 -0800482 """
andrewonlab7c211572014-10-15 16:45:20 -0400483 List the nodes currently visible
484 Issues command: 'nodes'
Jon Hall61282e32015-03-19 11:34:11 -0700485 Optional argument:
486 * jsonFormat - boolean indicating if you want output in json
kelvin8ec71442015-01-15 16:57:00 -0800487 """
andrewonlab7c211572014-10-15 16:45:20 -0400488 try:
Jon Hallc6358dd2015-04-10 12:44:28 -0700489 cmdStr = "nodes"
Jon Hall61282e32015-03-19 11:34:11 -0700490 if jsonFormat:
Jon Hallc6358dd2015-04-10 12:44:28 -0700491 cmdStr += " -j"
492 output = self.sendline( cmdStr )
493 return output
Jon Halld4d4b372015-01-28 16:02:41 -0800494 except TypeError:
495 main.log.exception( self.name + ": Object not as expected" )
496 return None
andrewonlab7c211572014-10-15 16:45:20 -0400497 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -0800498 main.log.error( self.name + ": EOF exception found" )
499 main.log.error( self.name + ": " + self.handle.before )
andrewonlab7c211572014-10-15 16:45:20 -0400500 main.cleanup()
501 main.exit()
Jon Hallfebb1c72015-03-05 13:30:09 -0800502 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -0800503 main.log.exception( self.name + ": Uncaught exception!" )
andrewonlab7c211572014-10-15 16:45:20 -0400504 main.cleanup()
505 main.exit()
506
kelvin8ec71442015-01-15 16:57:00 -0800507 def topology( self ):
508 """
Hari Krishnaef1bd4e2015-03-12 16:55:30 -0700509 Definition:
Jon Hall390696c2015-05-05 17:13:41 -0700510 Returns the output of topology command.
Hari Krishnaef1bd4e2015-03-12 16:55:30 -0700511 Return:
512 topology = current ONOS topology
kelvin8ec71442015-01-15 16:57:00 -0800513 """
andrewonlab95ce8322014-10-13 14:12:04 -0400514 try:
Hari Krishnaef1bd4e2015-03-12 16:55:30 -0700515 cmdStr = "topology -j"
kelvin-onlabd3b64892015-01-20 13:26:24 -0800516 handle = self.sendline( cmdStr )
Jon Hallc6358dd2015-04-10 12:44:28 -0700517 main.log.info( cmdStr + " returned: " + str( handle ) )
andrewonlab95ce8322014-10-13 14:12:04 -0400518 return handle
Jon Halld4d4b372015-01-28 16:02:41 -0800519 except TypeError:
520 main.log.exception( self.name + ": Object not as expected" )
521 return None
andrewonlab95ce8322014-10-13 14:12:04 -0400522 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -0800523 main.log.error( self.name + ": EOF exception found" )
524 main.log.error( self.name + ": " + self.handle.before )
andrewonlab95ce8322014-10-13 14:12:04 -0400525 main.cleanup()
526 main.exit()
Jon Hallfebb1c72015-03-05 13:30:09 -0800527 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -0800528 main.log.exception( self.name + ": Uncaught exception!" )
andrewonlab95ce8322014-10-13 14:12:04 -0400529 main.cleanup()
530 main.exit()
Jon Halle3f39ff2015-01-13 11:50:53 -0800531
kelvin-onlabd3b64892015-01-20 13:26:24 -0800532 def featureInstall( self, featureStr ):
kelvin8ec71442015-01-15 16:57:00 -0800533 """
Jon Hallc6358dd2015-04-10 12:44:28 -0700534 Installs a specified feature by issuing command:
535 'feature:install <feature_str>'
536 NOTE: This is now deprecated, you should use the activateApp method
537 instead
kelvin8ec71442015-01-15 16:57:00 -0800538 """
andrewonlabc2d05aa2014-10-13 16:51:10 -0400539 try:
kelvin-onlabd3b64892015-01-20 13:26:24 -0800540 cmdStr = "feature:install " + str( featureStr )
Jon Hallc6358dd2015-04-10 12:44:28 -0700541 handle = self.sendline( cmdStr )
542 if re.search( "Error", handle ):
543 main.log.error( "Error in installing feature" )
544 main.log.error( handle )
545 return main.FALSE
546 else:
547 return main.TRUE
Jon Halld4d4b372015-01-28 16:02:41 -0800548 except TypeError:
549 main.log.exception( self.name + ": Object not as expected" )
550 return None
andrewonlabc2d05aa2014-10-13 16:51:10 -0400551 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -0800552 main.log.error( self.name + ": EOF exception found" )
553 main.log.error( self.name + ": " + self.handle.before )
554 main.log.report( "Failed to install feature" )
555 main.log.report( "Exiting test" )
andrewonlabc2d05aa2014-10-13 16:51:10 -0400556 main.cleanup()
557 main.exit()
Jon Hallfebb1c72015-03-05 13:30:09 -0800558 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -0800559 main.log.exception( self.name + ": Uncaught exception!" )
kelvin8ec71442015-01-15 16:57:00 -0800560 main.log.report( "Failed to install feature" )
561 main.log.report( "Exiting test" )
andrewonlabc2d05aa2014-10-13 16:51:10 -0400562 main.cleanup()
563 main.exit()
Jon Halle3f39ff2015-01-13 11:50:53 -0800564
kelvin-onlabd3b64892015-01-20 13:26:24 -0800565 def featureUninstall( self, featureStr ):
kelvin8ec71442015-01-15 16:57:00 -0800566 """
Jon Hallc6358dd2015-04-10 12:44:28 -0700567 Uninstalls a specified feature by issuing command:
568 'feature:uninstall <feature_str>'
569 NOTE: This is now deprecated, you should use the deactivateApp method
570 instead
kelvin8ec71442015-01-15 16:57:00 -0800571 """
andrewonlabc2d05aa2014-10-13 16:51:10 -0400572 try:
Jon Hall30b82fa2015-03-04 17:15:43 -0800573 cmdStr = 'feature:list -i | grep "' + featureStr + '"'
574 handle = self.sendline( cmdStr )
575 if handle != '':
576 cmdStr = "feature:uninstall " + str( featureStr )
Jon Hallc6358dd2015-04-10 12:44:28 -0700577 output = self.sendline( cmdStr )
Jon Hall30b82fa2015-03-04 17:15:43 -0800578 # TODO: Check for possible error responses from karaf
579 else:
Jon Hallefbd9792015-03-05 16:11:36 -0800580 main.log.info( "Feature needs to be installed before " +
581 "uninstalling it" )
Jon Hallc6358dd2015-04-10 12:44:28 -0700582 return main.TRUE
583 if re.search( "Error", output ):
584 main.log.error( "Error in uninstalling feature" )
585 main.log.error( output )
586 return main.FALSE
587 else:
588 return main.TRUE
Jon Halld4d4b372015-01-28 16:02:41 -0800589 except TypeError:
590 main.log.exception( self.name + ": Object not as expected" )
591 return None
andrewonlabc2d05aa2014-10-13 16:51:10 -0400592 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -0800593 main.log.error( self.name + ": EOF exception found" )
594 main.log.error( self.name + ": " + self.handle.before )
andrewonlabc2d05aa2014-10-13 16:51:10 -0400595 main.cleanup()
596 main.exit()
Jon Hallfebb1c72015-03-05 13:30:09 -0800597 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -0800598 main.log.exception( self.name + ": Uncaught exception!" )
andrewonlabc2d05aa2014-10-13 16:51:10 -0400599 main.cleanup()
600 main.exit()
Jon Hallffb386d2014-11-21 13:43:38 -0800601
jenkins7ead5a82015-03-13 10:28:21 -0700602 def deviceRemove( self, deviceId ):
603 """
604 Removes particular device from storage
605
606 TODO: refactor this function
607 """
608 try:
Jon Hallc6358dd2015-04-10 12:44:28 -0700609 cmdStr = "device-remove " + str( deviceId )
610 handle = self.sendline( cmdStr )
611 if re.search( "Error", handle ):
612 main.log.error( "Error in removing device" )
613 main.log.error( handle )
614 return main.FALSE
615 else:
616 return main.TRUE
jenkins7ead5a82015-03-13 10:28:21 -0700617 except TypeError:
618 main.log.exception( self.name + ": Object not as expected" )
619 return None
620 except pexpect.EOF:
621 main.log.error( self.name + ": EOF exception found" )
622 main.log.error( self.name + ": " + self.handle.before )
623 main.cleanup()
624 main.exit()
625 except Exception:
626 main.log.exception( self.name + ": Uncaught exception!" )
627 main.cleanup()
628 main.exit()
jenkins7ead5a82015-03-13 10:28:21 -0700629
kelvin-onlabd3b64892015-01-20 13:26:24 -0800630 def devices( self, jsonFormat=True ):
kelvin8ec71442015-01-15 16:57:00 -0800631 """
Jon Hall7b02d952014-10-17 20:14:54 -0400632 Lists all infrastructure devices or switches
andrewonlab86dc3082014-10-13 18:18:38 -0400633 Optional argument:
kelvin-onlabd3b64892015-01-20 13:26:24 -0800634 * jsonFormat - boolean indicating if you want output in json
kelvin8ec71442015-01-15 16:57:00 -0800635 """
andrewonlab86dc3082014-10-13 18:18:38 -0400636 try:
Jon Hallc6358dd2015-04-10 12:44:28 -0700637 cmdStr = "devices"
kelvin-onlabd3b64892015-01-20 13:26:24 -0800638 if jsonFormat:
Jon Hallc6358dd2015-04-10 12:44:28 -0700639 cmdStr += " -j"
640 handle = self.sendline( cmdStr )
641 return handle
Jon Halld4d4b372015-01-28 16:02:41 -0800642 except TypeError:
643 main.log.exception( self.name + ": Object not as expected" )
644 return None
andrewonlab7c211572014-10-15 16:45:20 -0400645 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -0800646 main.log.error( self.name + ": EOF exception found" )
647 main.log.error( self.name + ": " + self.handle.before )
andrewonlab7c211572014-10-15 16:45:20 -0400648 main.cleanup()
649 main.exit()
Jon Hallfebb1c72015-03-05 13:30:09 -0800650 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -0800651 main.log.exception( self.name + ": Uncaught exception!" )
andrewonlab7c211572014-10-15 16:45:20 -0400652 main.cleanup()
653 main.exit()
654
kelvin-onlabd3b64892015-01-20 13:26:24 -0800655 def balanceMasters( self ):
kelvin8ec71442015-01-15 16:57:00 -0800656 """
Hari Krishnaa43d4e92014-12-19 13:22:40 -0800657 This balances the devices across all controllers
658 by issuing command: 'onos> onos:balance-masters'
659 If required this could be extended to return devices balanced output.
kelvin8ec71442015-01-15 16:57:00 -0800660 """
Hari Krishnaa43d4e92014-12-19 13:22:40 -0800661 try:
kelvin-onlabd3b64892015-01-20 13:26:24 -0800662 cmdStr = "onos:balance-masters"
Jon Hallc6358dd2015-04-10 12:44:28 -0700663 handle = self.sendline( cmdStr )
664 if re.search( "Error", handle ):
665 main.log.error( "Error in balancing masters" )
666 main.log.error( handle )
667 return main.FALSE
668 else:
669 return main.TRUE
Jon Halld4d4b372015-01-28 16:02:41 -0800670 except TypeError:
671 main.log.exception( self.name + ": Object not as expected" )
672 return None
Hari Krishnaa43d4e92014-12-19 13:22:40 -0800673 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -0800674 main.log.error( self.name + ": EOF exception found" )
675 main.log.error( self.name + ": " + self.handle.before )
Hari Krishnaa43d4e92014-12-19 13:22:40 -0800676 main.cleanup()
677 main.exit()
Jon Hallfebb1c72015-03-05 13:30:09 -0800678 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -0800679 main.log.exception( self.name + ": Uncaught exception!" )
Hari Krishnaa43d4e92014-12-19 13:22:40 -0800680 main.cleanup()
681 main.exit()
682
acsmars24950022015-07-30 18:00:43 -0700683 def checkMasters( self,jsonFormat=True ):
684 """
685 Returns the output of the masters command.
686 Optional argument:
687 * jsonFormat - boolean indicating if you want output in json
688 """
689 try:
690 cmdStr = "onos:masters"
691 if jsonFormat:
692 cmdStr += " -j"
693 output = self.sendline( cmdStr )
694 return output
695 except TypeError:
696 main.log.exception( self.name + ": Object not as expected" )
697 return None
698 except pexpect.EOF:
699 main.log.error( self.name + ": EOF exception found" )
700 main.log.error( self.name + ": " + self.handle.before )
701 main.cleanup()
702 main.exit()
703 except Exception:
704 main.log.exception( self.name + ": Uncaught exception!" )
705 main.cleanup()
706 main.exit()
707
708 def checkBalanceMasters( self,jsonFormat=True ):
709 """
710 Uses the master command to check that the devices' leadership
711 is evenly divided
712
713 Dependencies: checkMasters() and summary()
714
715 Returns main.True if the devices are balanced
716 Returns main.False if the devices are unbalanced
717 Exits on Exception
718 Returns None on TypeError
719 """
720 try:
721 totalDevices = json.loads( self.summary() )[ "devices" ]
722 totalOwnedDevices = 0
723 masters = json.loads( self.checkMasters() )
724 first = masters[ 0 ][ "size" ]
725 for master in masters:
726 totalOwnedDevices += master[ "size" ]
727 if master[ "size" ] > first + 1 or master[ "size" ] < first - 1:
728 main.log.error( "Mastership not balanced" )
729 main.log.info( "\n" + self.checkMasters( False ) )
730 return main.FALSE
731 main.log.info( "Mastership balanced between " \
732 + str( len(masters) ) + " masters" )
733 return main.TRUE
734 except TypeError:
735 main.log.exception( self.name + ": Object not as expected" )
736 return None
737 except pexpect.EOF:
738 main.log.error( self.name + ": EOF exception found" )
739 main.log.error( self.name + ": " + self.handle.before )
740 main.cleanup()
741 main.exit()
742 except Exception:
743 main.log.exception( self.name + ": Uncaught exception!" )
744 main.cleanup()
745 main.exit()
746
kelvin-onlabd3b64892015-01-20 13:26:24 -0800747 def links( self, jsonFormat=True ):
kelvin8ec71442015-01-15 16:57:00 -0800748 """
Jon Halle8217482014-10-17 13:49:14 -0400749 Lists all core links
750 Optional argument:
kelvin-onlabd3b64892015-01-20 13:26:24 -0800751 * jsonFormat - boolean indicating if you want output in json
kelvin8ec71442015-01-15 16:57:00 -0800752 """
Jon Halle8217482014-10-17 13:49:14 -0400753 try:
Jon Hallc6358dd2015-04-10 12:44:28 -0700754 cmdStr = "links"
kelvin-onlabd3b64892015-01-20 13:26:24 -0800755 if jsonFormat:
Jon Hallc6358dd2015-04-10 12:44:28 -0700756 cmdStr += " -j"
757 handle = self.sendline( cmdStr )
758 return handle
Jon Halld4d4b372015-01-28 16:02:41 -0800759 except TypeError:
760 main.log.exception( self.name + ": Object not as expected" )
761 return None
Jon Halle8217482014-10-17 13:49:14 -0400762 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -0800763 main.log.error( self.name + ": EOF exception found" )
764 main.log.error( self.name + ": " + self.handle.before )
Jon Halle8217482014-10-17 13:49:14 -0400765 main.cleanup()
766 main.exit()
Jon Hallfebb1c72015-03-05 13:30:09 -0800767 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -0800768 main.log.exception( self.name + ": Uncaught exception!" )
Jon Halle8217482014-10-17 13:49:14 -0400769 main.cleanup()
770 main.exit()
771
kelvin-onlabd3b64892015-01-20 13:26:24 -0800772 def ports( self, jsonFormat=True ):
kelvin8ec71442015-01-15 16:57:00 -0800773 """
Jon Halle8217482014-10-17 13:49:14 -0400774 Lists all ports
775 Optional argument:
kelvin-onlabd3b64892015-01-20 13:26:24 -0800776 * jsonFormat - boolean indicating if you want output in json
kelvin8ec71442015-01-15 16:57:00 -0800777 """
Jon Halle8217482014-10-17 13:49:14 -0400778 try:
Jon Hallc6358dd2015-04-10 12:44:28 -0700779 cmdStr = "ports"
kelvin-onlabd3b64892015-01-20 13:26:24 -0800780 if jsonFormat:
Jon Hallc6358dd2015-04-10 12:44:28 -0700781 cmdStr += " -j"
782 handle = self.sendline( cmdStr )
783 return handle
Jon Halld4d4b372015-01-28 16:02:41 -0800784 except TypeError:
785 main.log.exception( self.name + ": Object not as expected" )
786 return None
Jon Halle8217482014-10-17 13:49:14 -0400787 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -0800788 main.log.error( self.name + ": EOF exception found" )
789 main.log.error( self.name + ": " + self.handle.before )
Jon Halle8217482014-10-17 13:49:14 -0400790 main.cleanup()
791 main.exit()
Jon Hallfebb1c72015-03-05 13:30:09 -0800792 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -0800793 main.log.exception( self.name + ": Uncaught exception!" )
Jon Halle8217482014-10-17 13:49:14 -0400794 main.cleanup()
795 main.exit()
796
kelvin-onlabd3b64892015-01-20 13:26:24 -0800797 def roles( self, jsonFormat=True ):
kelvin8ec71442015-01-15 16:57:00 -0800798 """
Jon Hall983a1702014-10-28 18:44:22 -0400799 Lists all devices and the controllers with roles assigned to them
800 Optional argument:
kelvin-onlabd3b64892015-01-20 13:26:24 -0800801 * jsonFormat - boolean indicating if you want output in json
kelvin8ec71442015-01-15 16:57:00 -0800802 """
andrewonlab7c211572014-10-15 16:45:20 -0400803 try:
Jon Hallc6358dd2015-04-10 12:44:28 -0700804 cmdStr = "roles"
kelvin-onlabd3b64892015-01-20 13:26:24 -0800805 if jsonFormat:
Jon Hallc6358dd2015-04-10 12:44:28 -0700806 cmdStr += " -j"
807 handle = self.sendline( cmdStr )
808 return handle
Jon Halld4d4b372015-01-28 16:02:41 -0800809 except TypeError:
810 main.log.exception( self.name + ": Object not as expected" )
811 return None
Jon Hall983a1702014-10-28 18:44:22 -0400812 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -0800813 main.log.error( self.name + ": EOF exception found" )
814 main.log.error( self.name + ": " + self.handle.before )
Jon Hall983a1702014-10-28 18:44:22 -0400815 main.cleanup()
816 main.exit()
Jon Hallfebb1c72015-03-05 13:30:09 -0800817 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -0800818 main.log.exception( self.name + ": Uncaught exception!" )
Jon Hall983a1702014-10-28 18:44:22 -0400819 main.cleanup()
820 main.exit()
821
kelvin-onlabd3b64892015-01-20 13:26:24 -0800822 def getRole( self, deviceId ):
kelvin-onlab898a6c62015-01-16 14:13:53 -0800823 """
Jon Halle3f39ff2015-01-13 11:50:53 -0800824 Given the a string containing the json representation of the "roles"
825 cli command and a partial or whole device id, returns a json object
826 containing the roles output for the first device whose id contains
827 "device_id"
Jon Hall983a1702014-10-28 18:44:22 -0400828
829 Returns:
Jon Halle3f39ff2015-01-13 11:50:53 -0800830 A dict of the role assignments for the given device or
831 None if no match
kelvin8ec71442015-01-15 16:57:00 -0800832 """
Jon Hall983a1702014-10-28 18:44:22 -0400833 try:
kelvin-onlabd3b64892015-01-20 13:26:24 -0800834 if deviceId is None:
Jon Hall983a1702014-10-28 18:44:22 -0400835 return None
836 else:
kelvin-onlabd3b64892015-01-20 13:26:24 -0800837 rawRoles = self.roles()
838 rolesJson = json.loads( rawRoles )
kelvin8ec71442015-01-15 16:57:00 -0800839 # search json for the device with id then return the device
kelvin-onlabd3b64892015-01-20 13:26:24 -0800840 for device in rolesJson:
kelvin8ec71442015-01-15 16:57:00 -0800841 # print device
kelvin-onlabd3b64892015-01-20 13:26:24 -0800842 if str( deviceId ) in device[ 'id' ]:
Jon Hall983a1702014-10-28 18:44:22 -0400843 return device
844 return None
Jon Halld4d4b372015-01-28 16:02:41 -0800845 except TypeError:
846 main.log.exception( self.name + ": Object not as expected" )
847 return None
andrewonlab86dc3082014-10-13 18:18:38 -0400848 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -0800849 main.log.error( self.name + ": EOF exception found" )
850 main.log.error( self.name + ": " + self.handle.before )
andrewonlab86dc3082014-10-13 18:18:38 -0400851 main.cleanup()
852 main.exit()
Jon Hallfebb1c72015-03-05 13:30:09 -0800853 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -0800854 main.log.exception( self.name + ": Uncaught exception!" )
andrewonlab86dc3082014-10-13 18:18:38 -0400855 main.cleanup()
856 main.exit()
Jon Hall94fd0472014-12-08 11:52:42 -0800857
kelvin-onlabd3b64892015-01-20 13:26:24 -0800858 def rolesNotNull( self ):
kelvin8ec71442015-01-15 16:57:00 -0800859 """
Jon Hall94fd0472014-12-08 11:52:42 -0800860 Iterates through each device and checks if there is a master assigned
861 Returns: main.TRUE if each device has a master
862 main.FALSE any device has no master
kelvin8ec71442015-01-15 16:57:00 -0800863 """
Jon Hall94fd0472014-12-08 11:52:42 -0800864 try:
kelvin-onlabd3b64892015-01-20 13:26:24 -0800865 rawRoles = self.roles()
866 rolesJson = json.loads( rawRoles )
kelvin8ec71442015-01-15 16:57:00 -0800867 # search json for the device with id then return the device
kelvin-onlabd3b64892015-01-20 13:26:24 -0800868 for device in rolesJson:
kelvin8ec71442015-01-15 16:57:00 -0800869 # print device
870 if device[ 'master' ] == "none":
871 main.log.warn( "Device has no master: " + str( device ) )
Jon Hall94fd0472014-12-08 11:52:42 -0800872 return main.FALSE
873 return main.TRUE
874
Jon Halld4d4b372015-01-28 16:02:41 -0800875 except TypeError:
876 main.log.exception( self.name + ": Object not as expected" )
877 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 Halle3f39ff2015-01-13 11:50:53 -0800896 if re.search( "Error", handle ):
kelvin8ec71442015-01-15 16:57:00 -0800897 main.log.error( "Error in getting paths" )
898 return ( handle, "Error" )
andrewonlab3e15ead2014-10-15 14:21:34 -0400899 else:
kelvin8ec71442015-01-15 16:57:00 -0800900 path = handle.split( ";" )[ 0 ]
901 cost = handle.split( ";" )[ 1 ]
902 return ( path, cost )
Jon Halld4d4b372015-01-28 16:02:41 -0800903 except TypeError:
904 main.log.exception( self.name + ": Object not as expected" )
905 return ( handle, "Error" )
andrewonlab3e15ead2014-10-15 14:21:34 -0400906 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -0800907 main.log.error( self.name + ": EOF exception found" )
908 main.log.error( self.name + ": " + self.handle.before )
andrewonlab3e15ead2014-10-15 14:21:34 -0400909 main.cleanup()
910 main.exit()
Jon Hallfebb1c72015-03-05 13:30:09 -0800911 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -0800912 main.log.exception( self.name + ": Uncaught exception!" )
andrewonlab3e15ead2014-10-15 14:21:34 -0400913 main.cleanup()
914 main.exit()
Jon Hallffb386d2014-11-21 13:43:38 -0800915
kelvin-onlabd3b64892015-01-20 13:26:24 -0800916 def hosts( self, jsonFormat=True ):
kelvin8ec71442015-01-15 16:57:00 -0800917 """
Jon Hallffb386d2014-11-21 13:43:38 -0800918 Lists all discovered hosts
Jon Hall42db6dc2014-10-24 19:03:48 -0400919 Optional argument:
kelvin-onlabd3b64892015-01-20 13:26:24 -0800920 * jsonFormat - boolean indicating if you want output in json
kelvin8ec71442015-01-15 16:57:00 -0800921 """
Jon Hall42db6dc2014-10-24 19:03:48 -0400922 try:
Jon Hallc6358dd2015-04-10 12:44:28 -0700923 cmdStr = "hosts"
kelvin-onlabd3b64892015-01-20 13:26:24 -0800924 if jsonFormat:
Jon Hallc6358dd2015-04-10 12:44:28 -0700925 cmdStr += " -j"
926 handle = self.sendline( cmdStr )
927 return handle
Jon Halld4d4b372015-01-28 16:02:41 -0800928 except TypeError:
929 main.log.exception( self.name + ": Object not as expected" )
930 return None
Jon Hall42db6dc2014-10-24 19:03:48 -0400931 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -0800932 main.log.error( self.name + ": EOF exception found" )
933 main.log.error( self.name + ": " + self.handle.before )
Jon Hall42db6dc2014-10-24 19:03:48 -0400934 main.cleanup()
935 main.exit()
Jon Hallfebb1c72015-03-05 13:30:09 -0800936 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -0800937 main.log.exception( self.name + ": Uncaught exception!" )
Jon Hall42db6dc2014-10-24 19:03:48 -0400938 main.cleanup()
939 main.exit()
940
kelvin-onlabd3b64892015-01-20 13:26:24 -0800941 def getHost( self, mac ):
kelvin8ec71442015-01-15 16:57:00 -0800942 """
Jon Hall42db6dc2014-10-24 19:03:48 -0400943 Return the first host from the hosts api whose 'id' contains 'mac'
Jon Halle3f39ff2015-01-13 11:50:53 -0800944
Jon Hallefbd9792015-03-05 16:11:36 -0800945 Note: mac must be a colon separated mac address, but could be a
Jon Halle3f39ff2015-01-13 11:50:53 -0800946 partial mac address
947
Jon Hall42db6dc2014-10-24 19:03:48 -0400948 Return None if there is no match
kelvin8ec71442015-01-15 16:57:00 -0800949 """
Jon Hall42db6dc2014-10-24 19:03:48 -0400950 try:
kelvin8ec71442015-01-15 16:57:00 -0800951 if mac is None:
Jon Hall42db6dc2014-10-24 19:03:48 -0400952 return None
953 else:
954 mac = mac
kelvin-onlabd3b64892015-01-20 13:26:24 -0800955 rawHosts = self.hosts()
956 hostsJson = json.loads( rawHosts )
kelvin8ec71442015-01-15 16:57:00 -0800957 # search json for the host with mac then return the device
kelvin-onlabd3b64892015-01-20 13:26:24 -0800958 for host in hostsJson:
kelvin8ec71442015-01-15 16:57:00 -0800959 # print "%s in %s?" % ( mac, host[ 'id' ] )
Jon Halld4d4b372015-01-28 16:02:41 -0800960 if not host:
961 pass
962 elif mac in host[ 'id' ]:
Jon Hall42db6dc2014-10-24 19:03:48 -0400963 return host
964 return None
Jon Halld4d4b372015-01-28 16:02:41 -0800965 except TypeError:
966 main.log.exception( self.name + ": Object not as expected" )
967 return None
Jon Hall42db6dc2014-10-24 19:03:48 -0400968 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -0800969 main.log.error( self.name + ": EOF exception found" )
970 main.log.error( self.name + ": " + self.handle.before )
Jon Hall42db6dc2014-10-24 19:03:48 -0400971 main.cleanup()
972 main.exit()
Jon Hallfebb1c72015-03-05 13:30:09 -0800973 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -0800974 main.log.exception( self.name + ": Uncaught exception!" )
Jon Hall42db6dc2014-10-24 19:03:48 -0400975 main.cleanup()
976 main.exit()
977
kelvin-onlabd3b64892015-01-20 13:26:24 -0800978 def getHostsId( self, hostList ):
kelvin8ec71442015-01-15 16:57:00 -0800979 """
980 Obtain list of hosts
andrewonlab3f0a4af2014-10-17 12:25:14 -0400981 Issues command: 'onos> hosts'
kelvin8ec71442015-01-15 16:57:00 -0800982
andrewonlab3f0a4af2014-10-17 12:25:14 -0400983 Required:
kelvin-onlabd3b64892015-01-20 13:26:24 -0800984 * hostList: List of hosts obtained by Mininet
andrewonlab3f0a4af2014-10-17 12:25:14 -0400985 IMPORTANT:
986 This function assumes that you started your
kelvin8ec71442015-01-15 16:57:00 -0800987 topology with the option '--mac'.
andrewonlab3f0a4af2014-10-17 12:25:14 -0400988 Furthermore, it assumes that value of VLAN is '-1'
989 Description:
kelvin8ec71442015-01-15 16:57:00 -0800990 Converts mininet hosts ( h1, h2, h3... ) into
991 ONOS format ( 00:00:00:00:00:01/-1 , ... )
992 """
andrewonlab3f0a4af2014-10-17 12:25:14 -0400993 try:
kelvin-onlabd3b64892015-01-20 13:26:24 -0800994 onosHostList = []
andrewonlab3f0a4af2014-10-17 12:25:14 -0400995
kelvin-onlabd3b64892015-01-20 13:26:24 -0800996 for host in hostList:
kelvin8ec71442015-01-15 16:57:00 -0800997 host = host.replace( "h", "" )
kelvin-onlabd3b64892015-01-20 13:26:24 -0800998 hostHex = hex( int( host ) ).zfill( 12 )
999 hostHex = str( hostHex ).replace( 'x', '0' )
1000 i = iter( str( hostHex ) )
1001 hostHex = ":".join( a + b for a, b in zip( i, i ) )
1002 hostHex = hostHex + "/-1"
1003 onosHostList.append( hostHex )
andrewonlab3f0a4af2014-10-17 12:25:14 -04001004
kelvin-onlabd3b64892015-01-20 13:26:24 -08001005 return onosHostList
andrewonlab3f0a4af2014-10-17 12:25:14 -04001006
Jon Halld4d4b372015-01-28 16:02:41 -08001007 except TypeError:
1008 main.log.exception( self.name + ": Object not as expected" )
1009 return None
andrewonlab3f0a4af2014-10-17 12:25:14 -04001010 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08001011 main.log.error( self.name + ": EOF exception found" )
1012 main.log.error( self.name + ": " + self.handle.before )
andrewonlab3f0a4af2014-10-17 12:25:14 -04001013 main.cleanup()
1014 main.exit()
Jon Hallfebb1c72015-03-05 13:30:09 -08001015 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -08001016 main.log.exception( self.name + ": Uncaught exception!" )
andrewonlab3f0a4af2014-10-17 12:25:14 -04001017 main.cleanup()
1018 main.exit()
andrewonlab3e15ead2014-10-15 14:21:34 -04001019
kelvin-onlabd3b64892015-01-20 13:26:24 -08001020 def addHostIntent( self, hostIdOne, hostIdTwo ):
kelvin8ec71442015-01-15 16:57:00 -08001021 """
andrewonlabe6745342014-10-17 14:29:13 -04001022 Required:
kelvin-onlabd3b64892015-01-20 13:26:24 -08001023 * hostIdOne: ONOS host id for host1
1024 * hostIdTwo: ONOS host id for host2
andrewonlabe6745342014-10-17 14:29:13 -04001025 Description:
Jon Hallefbd9792015-03-05 16:11:36 -08001026 Adds a host-to-host intent ( bidirectional ) by
Jon Hallb1290e82014-11-18 16:17:48 -05001027 specifying the two hosts.
kelvin-onlabfb521662015-02-27 09:52:40 -08001028 Returns:
1029 A string of the intent id or None on Error
kelvin8ec71442015-01-15 16:57:00 -08001030 """
andrewonlabe6745342014-10-17 14:29:13 -04001031 try:
kelvin-onlabd3b64892015-01-20 13:26:24 -08001032 cmdStr = "add-host-intent " + str( hostIdOne ) +\
1033 " " + str( hostIdTwo )
1034 handle = self.sendline( cmdStr )
Hari Krishnaac4e1782015-01-26 12:09:12 -08001035 if re.search( "Error", handle ):
1036 main.log.error( "Error in adding Host intent" )
Jon Hall61282e32015-03-19 11:34:11 -07001037 main.log.debug( "Response from ONOS was: " + repr( handle ) )
kelvin-onlabfb521662015-02-27 09:52:40 -08001038 return None
Hari Krishnaac4e1782015-01-26 12:09:12 -08001039 else:
1040 main.log.info( "Host intent installed between " +
kelvin-onlabfb521662015-02-27 09:52:40 -08001041 str( hostIdOne ) + " and " + str( hostIdTwo ) )
1042 match = re.search('id=0x([\da-f]+),', handle)
1043 if match:
1044 return match.group()[3:-1]
1045 else:
1046 main.log.error( "Error, intent ID not found" )
Jon Hall61282e32015-03-19 11:34:11 -07001047 main.log.debug( "Response from ONOS was: " +
1048 repr( handle ) )
kelvin-onlabfb521662015-02-27 09:52:40 -08001049 return None
Jon Halld4d4b372015-01-28 16:02:41 -08001050 except TypeError:
1051 main.log.exception( self.name + ": Object not as expected" )
1052 return None
andrewonlabe6745342014-10-17 14:29:13 -04001053 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08001054 main.log.error( self.name + ": EOF exception found" )
1055 main.log.error( self.name + ": " + self.handle.before )
andrewonlabe6745342014-10-17 14:29:13 -04001056 main.cleanup()
1057 main.exit()
Jon Hallfebb1c72015-03-05 13:30:09 -08001058 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -08001059 main.log.exception( self.name + ": Uncaught exception!" )
andrewonlabe6745342014-10-17 14:29:13 -04001060 main.cleanup()
1061 main.exit()
1062
kelvin-onlabd3b64892015-01-20 13:26:24 -08001063 def addOpticalIntent( self, ingressDevice, egressDevice ):
kelvin8ec71442015-01-15 16:57:00 -08001064 """
andrewonlab7b31d232014-10-24 13:31:47 -04001065 Required:
kelvin-onlabd3b64892015-01-20 13:26:24 -08001066 * ingressDevice: device id of ingress device
1067 * egressDevice: device id of egress device
andrewonlab7b31d232014-10-24 13:31:47 -04001068 Optional:
1069 TODO: Still needs to be implemented via dev side
kelvin-onlabfb521662015-02-27 09:52:40 -08001070 Description:
1071 Adds an optical intent by specifying an ingress and egress device
1072 Returns:
1073 A string of the intent id or None on error
kelvin-onlab898a6c62015-01-16 14:13:53 -08001074 """
andrewonlab7b31d232014-10-24 13:31:47 -04001075 try:
kelvin-onlabd3b64892015-01-20 13:26:24 -08001076 cmdStr = "add-optical-intent " + str( ingressDevice ) +\
1077 " " + str( egressDevice )
1078 handle = self.sendline( cmdStr )
kelvin-onlab898a6c62015-01-16 14:13:53 -08001079 # If error, return error message
Jon Halle3f39ff2015-01-13 11:50:53 -08001080 if re.search( "Error", handle ):
kelvin-onlabfb521662015-02-27 09:52:40 -08001081 main.log.error( "Error in adding Optical intent" )
1082 return None
andrewonlab7b31d232014-10-24 13:31:47 -04001083 else:
kelvin-onlabfb521662015-02-27 09:52:40 -08001084 main.log.info( "Optical intent installed between " +
1085 str( ingressDevice ) + " and " +
1086 str( egressDevice ) )
1087 match = re.search('id=0x([\da-f]+),', handle)
1088 if match:
1089 return match.group()[3:-1]
1090 else:
1091 main.log.error( "Error, intent ID not found" )
1092 return None
Jon Halld4d4b372015-01-28 16:02:41 -08001093 except TypeError:
1094 main.log.exception( self.name + ": Object not as expected" )
1095 return None
andrewonlab7b31d232014-10-24 13:31:47 -04001096 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08001097 main.log.error( self.name + ": EOF exception found" )
1098 main.log.error( self.name + ": " + self.handle.before )
andrewonlab7b31d232014-10-24 13:31:47 -04001099 main.cleanup()
1100 main.exit()
Jon Hallfebb1c72015-03-05 13:30:09 -08001101 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -08001102 main.log.exception( self.name + ": Uncaught exception!" )
andrewonlab7b31d232014-10-24 13:31:47 -04001103 main.cleanup()
1104 main.exit()
1105
kelvin-onlabd3b64892015-01-20 13:26:24 -08001106 def addPointIntent(
kelvin-onlab898a6c62015-01-16 14:13:53 -08001107 self,
kelvin-onlabd3b64892015-01-20 13:26:24 -08001108 ingressDevice,
1109 egressDevice,
1110 portIngress="",
1111 portEgress="",
kelvin-onlab898a6c62015-01-16 14:13:53 -08001112 ethType="",
1113 ethSrc="",
1114 ethDst="",
1115 bandwidth="",
kelvin-onlabd3b64892015-01-20 13:26:24 -08001116 lambdaAlloc=False,
kelvin-onlab898a6c62015-01-16 14:13:53 -08001117 ipProto="",
1118 ipSrc="",
1119 ipDst="",
1120 tcpSrc="",
1121 tcpDst="" ):
kelvin8ec71442015-01-15 16:57:00 -08001122 """
andrewonlab4dbb4d82014-10-17 18:22:31 -04001123 Required:
kelvin-onlabd3b64892015-01-20 13:26:24 -08001124 * ingressDevice: device id of ingress device
1125 * egressDevice: device id of egress device
andrewonlab289e4b72014-10-21 21:24:18 -04001126 Optional:
1127 * ethType: specify ethType
kelvin8ec71442015-01-15 16:57:00 -08001128 * ethSrc: specify ethSrc ( i.e. src mac addr )
1129 * ethDst: specify ethDst ( i.e. dst mac addr )
andrewonlab0dbb6ec2014-11-06 13:46:55 -05001130 * bandwidth: specify bandwidth capacity of link
kelvin-onlabd3b64892015-01-20 13:26:24 -08001131 * lambdaAlloc: if True, intent will allocate lambda
andrewonlab40ccd8b2014-11-06 16:23:34 -05001132 for the specified intent
Jon Halle3f39ff2015-01-13 11:50:53 -08001133 * ipProto: specify ip protocol
andrewonlabf77e0cb2014-11-11 17:17:59 -05001134 * ipSrc: specify ip source address
1135 * ipDst: specify ip destination address
1136 * tcpSrc: specify tcp source port
1137 * tcpDst: specify tcp destination port
andrewonlab4dbb4d82014-10-17 18:22:31 -04001138 Description:
kelvin8ec71442015-01-15 16:57:00 -08001139 Adds a point-to-point intent ( uni-directional ) by
andrewonlab289e4b72014-10-21 21:24:18 -04001140 specifying device id's and optional fields
kelvin-onlabfb521662015-02-27 09:52:40 -08001141 Returns:
1142 A string of the intent id or None on error
andrewonlab289e4b72014-10-21 21:24:18 -04001143
Jon Halle3f39ff2015-01-13 11:50:53 -08001144 NOTE: This function may change depending on the
andrewonlab4dbb4d82014-10-17 18:22:31 -04001145 options developers provide for point-to-point
1146 intent via cli
kelvin8ec71442015-01-15 16:57:00 -08001147 """
andrewonlab4dbb4d82014-10-17 18:22:31 -04001148 try:
kelvin8ec71442015-01-15 16:57:00 -08001149 # If there are no optional arguments
andrewonlab0dbb6ec2014-11-06 13:46:55 -05001150 if not ethType and not ethSrc and not ethDst\
kelvin-onlabd3b64892015-01-20 13:26:24 -08001151 and not bandwidth and not lambdaAlloc \
andrewonlabfa4ff502014-11-11 16:41:30 -05001152 and not ipProto and not ipSrc and not ipDst \
1153 and not tcpSrc and not tcpDst:
andrewonlab36af3822014-11-18 17:48:18 -05001154 cmd = "add-point-intent"
andrewonlab36af3822014-11-18 17:48:18 -05001155
andrewonlab289e4b72014-10-21 21:24:18 -04001156 else:
andrewonlab36af3822014-11-18 17:48:18 -05001157 cmd = "add-point-intent"
Jon Halle3f39ff2015-01-13 11:50:53 -08001158
andrewonlab0c0a6772014-10-22 12:31:18 -04001159 if ethType:
kelvin8ec71442015-01-15 16:57:00 -08001160 cmd += " --ethType " + str( ethType )
andrewonlab289e4b72014-10-21 21:24:18 -04001161 if ethSrc:
kelvin8ec71442015-01-15 16:57:00 -08001162 cmd += " --ethSrc " + str( ethSrc )
1163 if ethDst:
1164 cmd += " --ethDst " + str( ethDst )
andrewonlab0dbb6ec2014-11-06 13:46:55 -05001165 if bandwidth:
kelvin8ec71442015-01-15 16:57:00 -08001166 cmd += " --bandwidth " + str( bandwidth )
kelvin-onlabd3b64892015-01-20 13:26:24 -08001167 if lambdaAlloc:
andrewonlabfa4ff502014-11-11 16:41:30 -05001168 cmd += " --lambda "
1169 if ipProto:
kelvin8ec71442015-01-15 16:57:00 -08001170 cmd += " --ipProto " + str( ipProto )
andrewonlabfa4ff502014-11-11 16:41:30 -05001171 if ipSrc:
kelvin8ec71442015-01-15 16:57:00 -08001172 cmd += " --ipSrc " + str( ipSrc )
andrewonlabfa4ff502014-11-11 16:41:30 -05001173 if ipDst:
kelvin8ec71442015-01-15 16:57:00 -08001174 cmd += " --ipDst " + str( ipDst )
andrewonlabfa4ff502014-11-11 16:41:30 -05001175 if tcpSrc:
kelvin8ec71442015-01-15 16:57:00 -08001176 cmd += " --tcpSrc " + str( tcpSrc )
andrewonlabfa4ff502014-11-11 16:41:30 -05001177 if tcpDst:
kelvin8ec71442015-01-15 16:57:00 -08001178 cmd += " --tcpDst " + str( tcpDst )
andrewonlab289e4b72014-10-21 21:24:18 -04001179
kelvin8ec71442015-01-15 16:57:00 -08001180 # Check whether the user appended the port
1181 # or provided it as an input
kelvin-onlabd3b64892015-01-20 13:26:24 -08001182 if "/" in ingressDevice:
1183 cmd += " " + str( ingressDevice )
andrewonlab36af3822014-11-18 17:48:18 -05001184 else:
kelvin-onlabd3b64892015-01-20 13:26:24 -08001185 if not portIngress:
kelvin-onlabfb521662015-02-27 09:52:40 -08001186 main.log.error( "You must specify the ingress port" )
kelvin8ec71442015-01-15 16:57:00 -08001187 # TODO: perhaps more meaningful return
kelvin-onlabfb521662015-02-27 09:52:40 -08001188 # Would it make sense to throw an exception and exit
1189 # the test?
1190 return None
andrewonlab36af3822014-11-18 17:48:18 -05001191
kelvin8ec71442015-01-15 16:57:00 -08001192 cmd += " " + \
kelvin-onlabd3b64892015-01-20 13:26:24 -08001193 str( ingressDevice ) + "/" +\
1194 str( portIngress ) + " "
andrewonlab36af3822014-11-18 17:48:18 -05001195
kelvin-onlabd3b64892015-01-20 13:26:24 -08001196 if "/" in egressDevice:
1197 cmd += " " + str( egressDevice )
andrewonlab36af3822014-11-18 17:48:18 -05001198 else:
kelvin-onlabd3b64892015-01-20 13:26:24 -08001199 if not portEgress:
kelvin-onlabfb521662015-02-27 09:52:40 -08001200 main.log.error( "You must specify the egress port" )
1201 return None
Jon Halle3f39ff2015-01-13 11:50:53 -08001202
kelvin8ec71442015-01-15 16:57:00 -08001203 cmd += " " +\
kelvin-onlabd3b64892015-01-20 13:26:24 -08001204 str( egressDevice ) + "/" +\
1205 str( portEgress )
kelvin8ec71442015-01-15 16:57:00 -08001206
kelvin-onlab898a6c62015-01-16 14:13:53 -08001207 handle = self.sendline( cmd )
kelvin-onlabfb521662015-02-27 09:52:40 -08001208 # If error, return error message
kelvin-onlab898a6c62015-01-16 14:13:53 -08001209 if re.search( "Error", handle ):
kelvin8ec71442015-01-15 16:57:00 -08001210 main.log.error( "Error in adding point-to-point intent" )
kelvin-onlabfb521662015-02-27 09:52:40 -08001211 return None
andrewonlab4dbb4d82014-10-17 18:22:31 -04001212 else:
kelvin-onlabfb521662015-02-27 09:52:40 -08001213 # TODO: print out all the options in this message?
1214 main.log.info( "Point-to-point intent installed between " +
1215 str( ingressDevice ) + " and " +
1216 str( egressDevice ) )
1217 match = re.search('id=0x([\da-f]+),', handle)
1218 if match:
1219 return match.group()[3:-1]
1220 else:
1221 main.log.error( "Error, intent ID not found" )
1222 return None
Jon Halld4d4b372015-01-28 16:02:41 -08001223 except TypeError:
1224 main.log.exception( self.name + ": Object not as expected" )
1225 return None
andrewonlab4dbb4d82014-10-17 18:22:31 -04001226 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08001227 main.log.error( self.name + ": EOF exception found" )
1228 main.log.error( self.name + ": " + self.handle.before )
andrewonlab4dbb4d82014-10-17 18:22:31 -04001229 main.cleanup()
1230 main.exit()
Jon Hallfebb1c72015-03-05 13:30:09 -08001231 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -08001232 main.log.exception( self.name + ": Uncaught exception!" )
andrewonlab4dbb4d82014-10-17 18:22:31 -04001233 main.cleanup()
1234 main.exit()
1235
kelvin-onlabd3b64892015-01-20 13:26:24 -08001236 def addMultipointToSinglepointIntent(
kelvin-onlab898a6c62015-01-16 14:13:53 -08001237 self,
shahshreyac2f97072015-03-19 17:04:29 -07001238 ingressDeviceList,
kelvin-onlabd3b64892015-01-20 13:26:24 -08001239 egressDevice,
shahshreyac2f97072015-03-19 17:04:29 -07001240 portIngressList=None,
kelvin-onlabd3b64892015-01-20 13:26:24 -08001241 portEgress="",
kelvin-onlab898a6c62015-01-16 14:13:53 -08001242 ethType="",
1243 ethSrc="",
1244 ethDst="",
1245 bandwidth="",
kelvin-onlabd3b64892015-01-20 13:26:24 -08001246 lambdaAlloc=False,
kelvin-onlab898a6c62015-01-16 14:13:53 -08001247 ipProto="",
1248 ipSrc="",
1249 ipDst="",
1250 tcpSrc="",
1251 tcpDst="",
1252 setEthSrc="",
1253 setEthDst="" ):
kelvin8ec71442015-01-15 16:57:00 -08001254 """
shahshreyad0c80432014-12-04 16:56:05 -08001255 Note:
shahshreya70622b12015-03-19 17:19:00 -07001256 This function assumes the format of all ingress devices
Jon Hallbe379602015-03-24 13:39:32 -07001257 is same. That is, all ingress devices include port numbers
1258 with a "/" or all ingress devices could specify device
1259 ids and port numbers seperately.
shahshreyad0c80432014-12-04 16:56:05 -08001260 Required:
Jon Hallbe379602015-03-24 13:39:32 -07001261 * ingressDeviceList: List of device ids of ingress device
shahshreyac2f97072015-03-19 17:04:29 -07001262 ( Atleast 2 ingress devices required in the list )
kelvin-onlabd3b64892015-01-20 13:26:24 -08001263 * egressDevice: device id of egress device
shahshreyad0c80432014-12-04 16:56:05 -08001264 Optional:
1265 * ethType: specify ethType
kelvin8ec71442015-01-15 16:57:00 -08001266 * ethSrc: specify ethSrc ( i.e. src mac addr )
1267 * ethDst: specify ethDst ( i.e. dst mac addr )
shahshreyad0c80432014-12-04 16:56:05 -08001268 * bandwidth: specify bandwidth capacity of link
kelvin-onlabd3b64892015-01-20 13:26:24 -08001269 * lambdaAlloc: if True, intent will allocate lambda
shahshreyad0c80432014-12-04 16:56:05 -08001270 for the specified intent
Jon Halle3f39ff2015-01-13 11:50:53 -08001271 * ipProto: specify ip protocol
shahshreyad0c80432014-12-04 16:56:05 -08001272 * ipSrc: specify ip source address
1273 * ipDst: specify ip destination address
1274 * tcpSrc: specify tcp source port
1275 * tcpDst: specify tcp destination port
1276 * setEthSrc: action to Rewrite Source MAC Address
1277 * setEthDst: action to Rewrite Destination MAC Address
1278 Description:
kelvin8ec71442015-01-15 16:57:00 -08001279 Adds a multipoint-to-singlepoint intent ( uni-directional ) by
shahshreyad0c80432014-12-04 16:56:05 -08001280 specifying device id's and optional fields
kelvin-onlabfb521662015-02-27 09:52:40 -08001281 Returns:
1282 A string of the intent id or None on error
shahshreyad0c80432014-12-04 16:56:05 -08001283
Jon Halle3f39ff2015-01-13 11:50:53 -08001284 NOTE: This function may change depending on the
Jon Hallefbd9792015-03-05 16:11:36 -08001285 options developers provide for multipoint-to-singlepoint
shahshreyad0c80432014-12-04 16:56:05 -08001286 intent via cli
kelvin8ec71442015-01-15 16:57:00 -08001287 """
shahshreyad0c80432014-12-04 16:56:05 -08001288 try:
kelvin8ec71442015-01-15 16:57:00 -08001289 # If there are no optional arguments
shahshreyad0c80432014-12-04 16:56:05 -08001290 if not ethType and not ethSrc and not ethDst\
kelvin-onlabd3b64892015-01-20 13:26:24 -08001291 and not bandwidth and not lambdaAlloc\
Jon Halle3f39ff2015-01-13 11:50:53 -08001292 and not ipProto and not ipSrc and not ipDst\
1293 and not tcpSrc and not tcpDst and not setEthSrc\
1294 and not setEthDst:
shahshreyad0c80432014-12-04 16:56:05 -08001295 cmd = "add-multi-to-single-intent"
shahshreyad0c80432014-12-04 16:56:05 -08001296
1297 else:
1298 cmd = "add-multi-to-single-intent"
Jon Halle3f39ff2015-01-13 11:50:53 -08001299
shahshreyad0c80432014-12-04 16:56:05 -08001300 if ethType:
kelvin8ec71442015-01-15 16:57:00 -08001301 cmd += " --ethType " + str( ethType )
shahshreyad0c80432014-12-04 16:56:05 -08001302 if ethSrc:
kelvin8ec71442015-01-15 16:57:00 -08001303 cmd += " --ethSrc " + str( ethSrc )
1304 if ethDst:
1305 cmd += " --ethDst " + str( ethDst )
shahshreyad0c80432014-12-04 16:56:05 -08001306 if bandwidth:
kelvin8ec71442015-01-15 16:57:00 -08001307 cmd += " --bandwidth " + str( bandwidth )
kelvin-onlabd3b64892015-01-20 13:26:24 -08001308 if lambdaAlloc:
shahshreyad0c80432014-12-04 16:56:05 -08001309 cmd += " --lambda "
1310 if ipProto:
kelvin8ec71442015-01-15 16:57:00 -08001311 cmd += " --ipProto " + str( ipProto )
shahshreyad0c80432014-12-04 16:56:05 -08001312 if ipSrc:
kelvin8ec71442015-01-15 16:57:00 -08001313 cmd += " --ipSrc " + str( ipSrc )
shahshreyad0c80432014-12-04 16:56:05 -08001314 if ipDst:
kelvin8ec71442015-01-15 16:57:00 -08001315 cmd += " --ipDst " + str( ipDst )
shahshreyad0c80432014-12-04 16:56:05 -08001316 if tcpSrc:
kelvin8ec71442015-01-15 16:57:00 -08001317 cmd += " --tcpSrc " + str( tcpSrc )
shahshreyad0c80432014-12-04 16:56:05 -08001318 if tcpDst:
kelvin8ec71442015-01-15 16:57:00 -08001319 cmd += " --tcpDst " + str( tcpDst )
shahshreyad0c80432014-12-04 16:56:05 -08001320 if setEthSrc:
kelvin8ec71442015-01-15 16:57:00 -08001321 cmd += " --setEthSrc " + str( setEthSrc )
shahshreyad0c80432014-12-04 16:56:05 -08001322 if setEthDst:
kelvin8ec71442015-01-15 16:57:00 -08001323 cmd += " --setEthDst " + str( setEthDst )
shahshreyad0c80432014-12-04 16:56:05 -08001324
kelvin8ec71442015-01-15 16:57:00 -08001325 # Check whether the user appended the port
1326 # or provided it as an input
shahshreyac2f97072015-03-19 17:04:29 -07001327
1328 if portIngressList is None:
1329 for ingressDevice in ingressDeviceList:
1330 if "/" in ingressDevice:
1331 cmd += " " + str( ingressDevice )
1332 else:
1333 main.log.error( "You must specify " +
Jon Hallbe379602015-03-24 13:39:32 -07001334 "the ingress port" )
shahshreyac2f97072015-03-19 17:04:29 -07001335 # TODO: perhaps more meaningful return
1336 return main.FALSE
shahshreyad0c80432014-12-04 16:56:05 -08001337 else:
Jon Hall71ce4e72015-03-23 14:05:58 -07001338 if len( ingressDeviceList ) == len( portIngressList ):
Jon Hall08f61bc2015-04-13 16:00:30 -07001339 for ingressDevice, portIngress in zip( ingressDeviceList,
1340 portIngressList ):
shahshreya70622b12015-03-19 17:19:00 -07001341 cmd += " " + \
1342 str( ingressDevice ) + "/" +\
1343 str( portIngress ) + " "
kelvin-onlab38143812015-04-01 15:03:01 -07001344 else:
Jon Hall08f61bc2015-04-13 16:00:30 -07001345 main.log.error( "Device list and port list does not " +
1346 "have the same length" )
kelvin-onlab38143812015-04-01 15:03:01 -07001347 return main.FALSE
kelvin-onlabd3b64892015-01-20 13:26:24 -08001348 if "/" in egressDevice:
1349 cmd += " " + str( egressDevice )
shahshreyad0c80432014-12-04 16:56:05 -08001350 else:
kelvin-onlabd3b64892015-01-20 13:26:24 -08001351 if not portEgress:
kelvin8ec71442015-01-15 16:57:00 -08001352 main.log.error( "You must specify " +
1353 "the egress port" )
shahshreyad0c80432014-12-04 16:56:05 -08001354 return main.FALSE
Jon Halle3f39ff2015-01-13 11:50:53 -08001355
kelvin8ec71442015-01-15 16:57:00 -08001356 cmd += " " +\
kelvin-onlabd3b64892015-01-20 13:26:24 -08001357 str( egressDevice ) + "/" +\
1358 str( portEgress )
kelvin-onlab898a6c62015-01-16 14:13:53 -08001359 handle = self.sendline( cmd )
kelvin-onlabfb521662015-02-27 09:52:40 -08001360 # If error, return error message
kelvin-onlab898a6c62015-01-16 14:13:53 -08001361 if re.search( "Error", handle ):
kelvin-onlabfb521662015-02-27 09:52:40 -08001362 main.log.error( "Error in adding multipoint-to-singlepoint " +
1363 "intent" )
1364 return None
shahshreyad0c80432014-12-04 16:56:05 -08001365 else:
kelvin-onlabb9408212015-04-01 13:34:04 -07001366 match = re.search('id=0x([\da-f]+),', handle)
1367 if match:
1368 return match.group()[3:-1]
1369 else:
1370 main.log.error( "Error, intent ID not found" )
1371 return None
1372 except TypeError:
1373 main.log.exception( self.name + ": Object not as expected" )
1374 return None
1375 except pexpect.EOF:
1376 main.log.error( self.name + ": EOF exception found" )
1377 main.log.error( self.name + ": " + self.handle.before )
1378 main.cleanup()
1379 main.exit()
1380 except Exception:
1381 main.log.exception( self.name + ": Uncaught exception!" )
1382 main.cleanup()
1383 main.exit()
1384
1385 def addSinglepointToMultipointIntent(
1386 self,
1387 ingressDevice,
1388 egressDeviceList,
1389 portIngress="",
1390 portEgressList=None,
1391 ethType="",
1392 ethSrc="",
1393 ethDst="",
1394 bandwidth="",
1395 lambdaAlloc=False,
1396 ipProto="",
1397 ipSrc="",
1398 ipDst="",
1399 tcpSrc="",
1400 tcpDst="",
1401 setEthSrc="",
1402 setEthDst="" ):
1403 """
1404 Note:
1405 This function assumes the format of all egress devices
1406 is same. That is, all egress devices include port numbers
1407 with a "/" or all egress devices could specify device
1408 ids and port numbers seperately.
1409 Required:
1410 * EgressDeviceList: List of device ids of egress device
1411 ( Atleast 2 eress devices required in the list )
1412 * ingressDevice: device id of ingress device
1413 Optional:
1414 * ethType: specify ethType
1415 * ethSrc: specify ethSrc ( i.e. src mac addr )
1416 * ethDst: specify ethDst ( i.e. dst mac addr )
1417 * bandwidth: specify bandwidth capacity of link
1418 * lambdaAlloc: if True, intent will allocate lambda
1419 for the specified intent
1420 * ipProto: specify ip protocol
1421 * ipSrc: specify ip source address
1422 * ipDst: specify ip destination address
1423 * tcpSrc: specify tcp source port
1424 * tcpDst: specify tcp destination port
1425 * setEthSrc: action to Rewrite Source MAC Address
1426 * setEthDst: action to Rewrite Destination MAC Address
1427 Description:
1428 Adds a singlepoint-to-multipoint intent ( uni-directional ) by
1429 specifying device id's and optional fields
1430 Returns:
1431 A string of the intent id or None on error
1432
1433 NOTE: This function may change depending on the
1434 options developers provide for singlepoint-to-multipoint
1435 intent via cli
1436 """
1437 try:
1438 # If there are no optional arguments
1439 if not ethType and not ethSrc and not ethDst\
1440 and not bandwidth and not lambdaAlloc\
1441 and not ipProto and not ipSrc and not ipDst\
1442 and not tcpSrc and not tcpDst and not setEthSrc\
1443 and not setEthDst:
1444 cmd = "add-single-to-multi-intent"
1445
1446 else:
1447 cmd = "add-single-to-multi-intent"
1448
1449 if ethType:
1450 cmd += " --ethType " + str( ethType )
1451 if ethSrc:
1452 cmd += " --ethSrc " + str( ethSrc )
1453 if ethDst:
1454 cmd += " --ethDst " + str( ethDst )
1455 if bandwidth:
1456 cmd += " --bandwidth " + str( bandwidth )
1457 if lambdaAlloc:
1458 cmd += " --lambda "
1459 if ipProto:
1460 cmd += " --ipProto " + str( ipProto )
1461 if ipSrc:
1462 cmd += " --ipSrc " + str( ipSrc )
1463 if ipDst:
1464 cmd += " --ipDst " + str( ipDst )
1465 if tcpSrc:
1466 cmd += " --tcpSrc " + str( tcpSrc )
1467 if tcpDst:
1468 cmd += " --tcpDst " + str( tcpDst )
1469 if setEthSrc:
1470 cmd += " --setEthSrc " + str( setEthSrc )
1471 if setEthDst:
1472 cmd += " --setEthDst " + str( setEthDst )
1473
1474 # Check whether the user appended the port
1475 # or provided it as an input
Jon Hall08f61bc2015-04-13 16:00:30 -07001476
kelvin-onlabb9408212015-04-01 13:34:04 -07001477 if "/" in ingressDevice:
1478 cmd += " " + str( ingressDevice )
1479 else:
1480 if not portIngress:
1481 main.log.error( "You must specify " +
1482 "the Ingress port" )
1483 return main.FALSE
1484
1485 cmd += " " +\
1486 str( ingressDevice ) + "/" +\
1487 str( portIngress )
1488
1489 if portEgressList is None:
1490 for egressDevice in egressDeviceList:
1491 if "/" in egressDevice:
1492 cmd += " " + str( egressDevice )
1493 else:
1494 main.log.error( "You must specify " +
1495 "the egress port" )
1496 # TODO: perhaps more meaningful return
1497 return main.FALSE
1498 else:
1499 if len( egressDeviceList ) == len( portEgressList ):
Jon Hall08f61bc2015-04-13 16:00:30 -07001500 for egressDevice, portEgress in zip( egressDeviceList,
1501 portEgressList ):
kelvin-onlabb9408212015-04-01 13:34:04 -07001502 cmd += " " + \
1503 str( egressDevice ) + "/" +\
1504 str( portEgress )
kelvin-onlab38143812015-04-01 15:03:01 -07001505 else:
Jon Hall08f61bc2015-04-13 16:00:30 -07001506 main.log.error( "Device list and port list does not " +
1507 "have the same length" )
kelvin-onlab38143812015-04-01 15:03:01 -07001508 return main.FALSE
kelvin-onlabb9408212015-04-01 13:34:04 -07001509 handle = self.sendline( cmd )
1510 # If error, return error message
1511 if re.search( "Error", handle ):
1512 main.log.error( "Error in adding singlepoint-to-multipoint " +
1513 "intent" )
shahshreyac2f97072015-03-19 17:04:29 -07001514 return None
kelvin-onlabb9408212015-04-01 13:34:04 -07001515 else:
1516 match = re.search('id=0x([\da-f]+),', handle)
1517 if match:
1518 return match.group()[3:-1]
1519 else:
1520 main.log.error( "Error, intent ID not found" )
1521 return None
Jon Halld4d4b372015-01-28 16:02:41 -08001522 except TypeError:
1523 main.log.exception( self.name + ": Object not as expected" )
1524 return None
shahshreyad0c80432014-12-04 16:56:05 -08001525 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08001526 main.log.error( self.name + ": EOF exception found" )
1527 main.log.error( self.name + ": " + self.handle.before )
shahshreyad0c80432014-12-04 16:56:05 -08001528 main.cleanup()
1529 main.exit()
Jon Hallfebb1c72015-03-05 13:30:09 -08001530 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -08001531 main.log.exception( self.name + ": Uncaught exception!" )
shahshreyad0c80432014-12-04 16:56:05 -08001532 main.cleanup()
1533 main.exit()
1534
Hari Krishna9e232602015-04-13 17:29:08 -07001535 def addMplsIntent(
1536 self,
1537 ingressDevice,
1538 egressDevice,
Hari Krishna87a17f12015-04-13 17:42:23 -07001539 ingressPort="",
1540 egressPort="",
Hari Krishna9e232602015-04-13 17:29:08 -07001541 ethType="",
1542 ethSrc="",
1543 ethDst="",
1544 bandwidth="",
1545 lambdaAlloc=False,
1546 ipProto="",
1547 ipSrc="",
1548 ipDst="",
1549 tcpSrc="",
1550 tcpDst="",
Hari Krishna87a17f12015-04-13 17:42:23 -07001551 ingressLabel="",
Hari Krishnadfff6672015-04-13 17:53:27 -07001552 egressLabel="",
Hari Krishna9e232602015-04-13 17:29:08 -07001553 priority=""):
1554 """
1555 Required:
1556 * ingressDevice: device id of ingress device
1557 * egressDevice: device id of egress device
1558 Optional:
1559 * ethType: specify ethType
1560 * ethSrc: specify ethSrc ( i.e. src mac addr )
1561 * ethDst: specify ethDst ( i.e. dst mac addr )
1562 * bandwidth: specify bandwidth capacity of link
1563 * lambdaAlloc: if True, intent will allocate lambda
1564 for the specified intent
1565 * ipProto: specify ip protocol
1566 * ipSrc: specify ip source address
1567 * ipDst: specify ip destination address
1568 * tcpSrc: specify tcp source port
1569 * tcpDst: specify tcp destination port
1570 * ingressLabel: Ingress MPLS label
1571 * egressLabel: Egress MPLS label
1572 Description:
1573 Adds MPLS intent by
1574 specifying device id's and optional fields
1575 Returns:
1576 A string of the intent id or None on error
1577
1578 NOTE: This function may change depending on the
1579 options developers provide for MPLS
1580 intent via cli
1581 """
1582 try:
1583 # If there are no optional arguments
1584 if not ethType and not ethSrc and not ethDst\
1585 and not bandwidth and not lambdaAlloc \
1586 and not ipProto and not ipSrc and not ipDst \
1587 and not tcpSrc and not tcpDst and not ingressLabel \
1588 and not egressLabel:
1589 cmd = "add-mpls-intent"
1590
1591 else:
1592 cmd = "add-mpls-intent"
1593
1594 if ethType:
1595 cmd += " --ethType " + str( ethType )
1596 if ethSrc:
1597 cmd += " --ethSrc " + str( ethSrc )
1598 if ethDst:
1599 cmd += " --ethDst " + str( ethDst )
1600 if bandwidth:
1601 cmd += " --bandwidth " + str( bandwidth )
1602 if lambdaAlloc:
1603 cmd += " --lambda "
1604 if ipProto:
1605 cmd += " --ipProto " + str( ipProto )
1606 if ipSrc:
1607 cmd += " --ipSrc " + str( ipSrc )
1608 if ipDst:
1609 cmd += " --ipDst " + str( ipDst )
1610 if tcpSrc:
1611 cmd += " --tcpSrc " + str( tcpSrc )
1612 if tcpDst:
1613 cmd += " --tcpDst " + str( tcpDst )
1614 if ingressLabel:
1615 cmd += " --ingressLabel " + str( ingressLabel )
1616 if egressLabel:
1617 cmd += " --egressLabel " + str( egressLabel )
1618 if priority:
1619 cmd += " --priority " + str( priority )
1620
1621 # Check whether the user appended the port
1622 # or provided it as an input
1623 if "/" in ingressDevice:
1624 cmd += " " + str( ingressDevice )
1625 else:
Hari Krishna87a17f12015-04-13 17:42:23 -07001626 if not ingressPort:
Hari Krishna9e232602015-04-13 17:29:08 -07001627 main.log.error( "You must specify the ingress port" )
1628 return None
1629
1630 cmd += " " + \
1631 str( ingressDevice ) + "/" +\
Hari Krishna87a17f12015-04-13 17:42:23 -07001632 str( ingressPort ) + " "
Hari Krishna9e232602015-04-13 17:29:08 -07001633
1634 if "/" in egressDevice:
1635 cmd += " " + str( egressDevice )
1636 else:
Hari Krishna87a17f12015-04-13 17:42:23 -07001637 if not egressPort:
Hari Krishna9e232602015-04-13 17:29:08 -07001638 main.log.error( "You must specify the egress port" )
1639 return None
1640
1641 cmd += " " +\
1642 str( egressDevice ) + "/" +\
Hari Krishna87a17f12015-04-13 17:42:23 -07001643 str( egressPort )
Hari Krishna9e232602015-04-13 17:29:08 -07001644
1645 handle = self.sendline( cmd )
1646 # If error, return error message
1647 if re.search( "Error", handle ):
1648 main.log.error( "Error in adding mpls intent" )
1649 return None
1650 else:
1651 # TODO: print out all the options in this message?
1652 main.log.info( "MPLS intent installed between " +
1653 str( ingressDevice ) + " and " +
1654 str( egressDevice ) )
1655 match = re.search('id=0x([\da-f]+),', handle)
1656 if match:
1657 return match.group()[3:-1]
1658 else:
1659 main.log.error( "Error, intent ID not found" )
1660 return None
1661 except TypeError:
1662 main.log.exception( self.name + ": Object not as expected" )
1663 return None
1664 except pexpect.EOF:
1665 main.log.error( self.name + ": EOF exception found" )
1666 main.log.error( self.name + ": " + self.handle.before )
1667 main.cleanup()
1668 main.exit()
1669 except Exception:
1670 main.log.exception( self.name + ": Uncaught exception!" )
1671 main.cleanup()
1672 main.exit()
1673
Jon Hallefbd9792015-03-05 16:11:36 -08001674 def removeIntent( self, intentId, app='org.onosproject.cli',
1675 purge=False, sync=False ):
kelvin-onlab898a6c62015-01-16 14:13:53 -08001676 """
shahshreya1c818fc2015-02-26 13:44:08 -08001677 Remove intent for specified application id and intent id
Jon Hall61282e32015-03-19 11:34:11 -07001678 Optional args:-
shahshreya1c818fc2015-02-26 13:44:08 -08001679 -s or --sync: Waits for the removal before returning
Jon Hall61282e32015-03-19 11:34:11 -07001680 -p or --purge: Purge the intent from the store after removal
1681
Jon Halle3f39ff2015-01-13 11:50:53 -08001682 Returns:
1683 main.False on error and
1684 cli output otherwise
kelvin-onlab898a6c62015-01-16 14:13:53 -08001685 """
andrewonlab9a50dfe2014-10-17 17:22:31 -04001686 try:
Jon Hallc6358dd2015-04-10 12:44:28 -07001687 cmdStr = "remove-intent"
shahshreya1c818fc2015-02-26 13:44:08 -08001688 if purge:
1689 cmdStr += " -p"
1690 if sync:
1691 cmdStr += " -s"
1692
1693 cmdStr += " " + app + " " + str( intentId )
kelvin-onlabd3b64892015-01-20 13:26:24 -08001694 handle = self.sendline( cmdStr )
Jon Halle3f39ff2015-01-13 11:50:53 -08001695 if re.search( "Error", handle ):
kelvin-onlab898a6c62015-01-16 14:13:53 -08001696 main.log.error( "Error in removing intent" )
Jon Halle3f39ff2015-01-13 11:50:53 -08001697 return main.FALSE
andrewonlab9a50dfe2014-10-17 17:22:31 -04001698 else:
Jon Halle3f39ff2015-01-13 11:50:53 -08001699 # TODO: Should this be main.TRUE
1700 return handle
Jon Halld4d4b372015-01-28 16:02:41 -08001701 except TypeError:
1702 main.log.exception( self.name + ": Object not as expected" )
1703 return None
andrewonlab9a50dfe2014-10-17 17:22:31 -04001704 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08001705 main.log.error( self.name + ": EOF exception found" )
1706 main.log.error( self.name + ": " + self.handle.before )
andrewonlab9a50dfe2014-10-17 17:22:31 -04001707 main.cleanup()
1708 main.exit()
Jon Hallfebb1c72015-03-05 13:30:09 -08001709 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -08001710 main.log.exception( self.name + ": Uncaught exception!" )
andrewonlab9a50dfe2014-10-17 17:22:31 -04001711 main.cleanup()
1712 main.exit()
1713
Hari Krishnaacabd5a2015-07-01 17:10:19 -07001714 def purgeWithdrawnIntents( self ):
Hari Krishna0ce0e152015-06-23 09:55:29 -07001715 """
1716 Purges all WITHDRAWN Intents
1717 """
1718 try:
1719 cmdStr = "purge-intents"
1720 handle = self.sendline( cmdStr )
1721 if re.search( "Error", handle ):
1722 main.log.error( "Error in purging intents" )
1723 return main.FALSE
1724 else:
1725 return main.TRUE
1726 except TypeError:
1727 main.log.exception( self.name + ": Object not as expected" )
1728 return None
1729 except pexpect.EOF:
1730 main.log.error( self.name + ": EOF exception found" )
1731 main.log.error( self.name + ": " + self.handle.before )
1732 main.cleanup()
1733 main.exit()
1734 except Exception:
1735 main.log.exception( self.name + ": Uncaught exception!" )
1736 main.cleanup()
1737 main.exit()
1738
kelvin-onlabd3b64892015-01-20 13:26:24 -08001739 def routes( self, jsonFormat=False ):
kelvin8ec71442015-01-15 16:57:00 -08001740 """
kelvin-onlab898a6c62015-01-16 14:13:53 -08001741 NOTE: This method should be used after installing application:
1742 onos-app-sdnip
pingping-lin8b306ac2014-11-17 18:13:51 -08001743 Optional:
kelvin-onlabd3b64892015-01-20 13:26:24 -08001744 * jsonFormat: enable output formatting in json
pingping-lin8b306ac2014-11-17 18:13:51 -08001745 Description:
1746 Obtain all routes in the system
kelvin8ec71442015-01-15 16:57:00 -08001747 """
pingping-lin8b306ac2014-11-17 18:13:51 -08001748 try:
Jon Hallc6358dd2015-04-10 12:44:28 -07001749 cmdStr = "routes"
kelvin-onlabd3b64892015-01-20 13:26:24 -08001750 if jsonFormat:
Jon Hallc6358dd2015-04-10 12:44:28 -07001751 cmdStr += " -j"
1752 handle = self.sendline( cmdStr )
pingping-lin8b306ac2014-11-17 18:13:51 -08001753 return handle
Jon Halld4d4b372015-01-28 16:02:41 -08001754 except TypeError:
1755 main.log.exception( self.name + ": Object not as expected" )
1756 return None
pingping-lin8b306ac2014-11-17 18:13:51 -08001757 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08001758 main.log.error( self.name + ": EOF exception found" )
1759 main.log.error( self.name + ": " + self.handle.before )
pingping-lin8b306ac2014-11-17 18:13:51 -08001760 main.cleanup()
1761 main.exit()
Jon Hallfebb1c72015-03-05 13:30:09 -08001762 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -08001763 main.log.exception( self.name + ": Uncaught exception!" )
pingping-lin8b306ac2014-11-17 18:13:51 -08001764 main.cleanup()
1765 main.exit()
1766
pingping-lin54b03372015-08-13 14:43:10 -07001767 def ipv4RouteNumber( self ):
1768 """
1769 NOTE: This method should be used after installing application:
1770 onos-app-sdnip
1771 Description:
1772 Obtain the total IPv4 routes number in the system
1773 """
1774 try:
1775 cmdStr = "routes -s -j"
1776 handle = self.sendline( cmdStr )
1777 jsonResult = json.loads( handle )
1778 return jsonResult['totalRoutes4']
1779
1780 except TypeError:
1781 main.log.exception( self.name + ": Object not as expected" )
1782 return None
1783 except pexpect.EOF:
1784 main.log.error( self.name + ": EOF exception found" )
1785 main.log.error( self.name + ": " + self.handle.before )
1786 main.cleanup()
1787 main.exit()
1788 except Exception:
1789 main.log.exception( self.name + ": Uncaught exception!" )
1790 main.cleanup()
1791 main.exit()
1792
pingping-lin8244a3b2015-09-16 13:36:56 -07001793 def intents( self, jsonFormat = True, summary = False, **intentargs):
kelvin8ec71442015-01-15 16:57:00 -08001794 """
andrewonlab377693f2014-10-21 16:00:30 -04001795 Optional:
kelvin-onlabd3b64892015-01-20 13:26:24 -08001796 * jsonFormat: enable output formatting in json
pingping-lin8244a3b2015-09-16 13:36:56 -07001797 * summary: whether only output the intent summary
1798 * type: only output a certain type of intent
1799 This options is valid only when jsonFormat is true and summary is
1800 true
andrewonlabe6745342014-10-17 14:29:13 -04001801 Description:
pingping-lin8244a3b2015-09-16 13:36:56 -07001802 Obtain intents
kelvin-onlab898a6c62015-01-16 14:13:53 -08001803 """
andrewonlabe6745342014-10-17 14:29:13 -04001804 try:
Jon Hallc6358dd2015-04-10 12:44:28 -07001805 cmdStr = "intents"
pingping-lin8244a3b2015-09-16 13:36:56 -07001806 if summary:
1807 cmdStr += " -s"
kelvin-onlabd3b64892015-01-20 13:26:24 -08001808 if jsonFormat:
Jon Hallc6358dd2015-04-10 12:44:28 -07001809 cmdStr += " -j"
1810 handle = self.sendline( cmdStr )
pingping-lin8244a3b2015-09-16 13:36:56 -07001811 args = utilities.parse_args( [ "TYPE" ], **intentargs )
acsmars5b5fbaf2015-09-18 10:38:20 -07001812 if "TYPE" in args.keys():
1813 type = args[ "TYPE" ]
1814 else:
1815 type = ""
pingping-lin8244a3b2015-09-16 13:36:56 -07001816 if jsonFormat and summary and ( type != "" ):
1817 jsonResult = json.loads( handle )
1818 if type in jsonResult.keys():
1819 return jsonResult[ type ]
1820 else:
1821 main.log.error( "unknown TYPE, return all types of intents" )
1822 return handle
1823 else:
1824 return handle
pingping-lin54b03372015-08-13 14:43:10 -07001825
1826 except TypeError:
1827 main.log.exception( self.name + ": Object not as expected" )
1828 return None
1829 except pexpect.EOF:
1830 main.log.error( self.name + ": EOF exception found" )
1831 main.log.error( self.name + ": " + self.handle.before )
1832 main.cleanup()
1833 main.exit()
1834 except Exception:
1835 main.log.exception( self.name + ": Uncaught exception!" )
1836 main.cleanup()
1837 main.exit()
1838
pingping-lin8244a3b2015-09-16 13:36:56 -07001839
kelvin-onlab54400a92015-02-26 18:05:51 -08001840 def getIntentState(self, intentsId, intentsJson=None):
1841 """
kelvin-onlab54400a92015-02-26 18:05:51 -08001842 Check intent state.
1843 Accepts a single intent ID (string type) or a list of intent IDs.
1844 Returns the state(string type) of the id if a single intent ID is
1845 accepted.
Jon Hallefbd9792015-03-05 16:11:36 -08001846 Returns a dictionary with intent IDs as the key and its
1847 corresponding states as the values
kelvin-onlabfb521662015-02-27 09:52:40 -08001848 Parameters:
kelvin-onlab54400a92015-02-26 18:05:51 -08001849 intentId: intent ID (string type)
1850 intentsJson: parsed json object from the onos:intents api
1851 Returns:
1852 state = An intent's state- INSTALL,WITHDRAWN etc.
1853 stateDict = Dictionary of intent's state. intent ID as the keys and
1854 state as the values.
1855 """
kelvin-onlab54400a92015-02-26 18:05:51 -08001856 try:
1857 state = "State is Undefined"
1858 if not intentsJson:
Jon Hallefbd9792015-03-05 16:11:36 -08001859 intentsJsonTemp = json.loads( self.intents() )
kelvin-onlab54400a92015-02-26 18:05:51 -08001860 else:
Jon Hallefbd9792015-03-05 16:11:36 -08001861 intentsJsonTemp = json.loads( intentsJson )
1862 if isinstance( intentsId, types.StringType ):
kelvin-onlab54400a92015-02-26 18:05:51 -08001863 for intent in intentsJsonTemp:
kelvin-onlabc2dcd3f2015-04-09 16:40:02 -07001864 if intentsId == intent[ 'id' ]:
1865 state = intent[ 'state' ]
kelvin-onlab54400a92015-02-26 18:05:51 -08001866 return state
Jon Hallefbd9792015-03-05 16:11:36 -08001867 main.log.info( "Cannot find intent ID" + str( intentsId ) +
1868 " on the list" )
kelvin-onlab54400a92015-02-26 18:05:51 -08001869 return state
Jon Hallefbd9792015-03-05 16:11:36 -08001870 elif isinstance( intentsId, types.ListType ):
kelvin-onlab07dbd012015-03-04 16:29:39 -08001871 dictList = []
kelvin-onlabc2dcd3f2015-04-09 16:40:02 -07001872 for i in xrange( len( intentsId ) ):
kelvin-onlab07dbd012015-03-04 16:29:39 -08001873 stateDict = {}
kelvin-onlab54400a92015-02-26 18:05:51 -08001874 for intents in intentsJsonTemp:
kelvin-onlabc2dcd3f2015-04-09 16:40:02 -07001875 if intentsId[ i ] == intents[ 'id' ]:
1876 stateDict[ 'state' ] = intents[ 'state' ]
1877 stateDict[ 'id' ] = intentsId[ i ]
Jon Hallefbd9792015-03-05 16:11:36 -08001878 dictList.append( stateDict )
kelvin-onlab54400a92015-02-26 18:05:51 -08001879 break
Jon Hallefbd9792015-03-05 16:11:36 -08001880 if len( intentsId ) != len( dictList ):
1881 main.log.info( "Cannot find some of the intent ID state" )
kelvin-onlab07dbd012015-03-04 16:29:39 -08001882 return dictList
kelvin-onlab54400a92015-02-26 18:05:51 -08001883 else:
kelvin-onlabc2dcd3f2015-04-09 16:40:02 -07001884 main.log.info( "Invalid intents ID entry" )
kelvin-onlab54400a92015-02-26 18:05:51 -08001885 return None
kelvin-onlab54400a92015-02-26 18:05:51 -08001886 except TypeError:
1887 main.log.exception( self.name + ": Object not as expected" )
1888 return None
1889 except pexpect.EOF:
1890 main.log.error( self.name + ": EOF exception found" )
1891 main.log.error( self.name + ": " + self.handle.before )
1892 main.cleanup()
1893 main.exit()
Jon Hallfebb1c72015-03-05 13:30:09 -08001894 except Exception:
kelvin-onlab54400a92015-02-26 18:05:51 -08001895 main.log.exception( self.name + ": Uncaught exception!" )
andrewonlabe6745342014-10-17 14:29:13 -04001896 main.cleanup()
1897 main.exit()
Jon Hall390696c2015-05-05 17:13:41 -07001898
kelvin-onlabf512e942015-06-08 19:42:59 -07001899 def checkIntentState( self, intentsId, expectedState='INSTALLED' ):
kelvin-onlabc2dcd3f2015-04-09 16:40:02 -07001900 """
1901 Description:
1902 Check intents state
1903 Required:
1904 intentsId - List of intents ID to be checked
1905 Optional:
kelvin-onlabf512e942015-06-08 19:42:59 -07001906 expectedState - Check the expected state(s) of each intents
1907 state in the list.
1908 *NOTE: You can pass in a list of expected state,
1909 Eg: expectedState = [ 'INSTALLED' , 'INSTALLING' ]
kelvin-onlabc2dcd3f2015-04-09 16:40:02 -07001910 Return:
kelvin-onlabf512e942015-06-08 19:42:59 -07001911 Returns main.TRUE only if all intent are the same as expected states
1912 , otherwise, returns main.FALSE.
kelvin-onlabc2dcd3f2015-04-09 16:40:02 -07001913 """
1914 try:
1915 # Generating a dictionary: intent id as a key and state as value
kelvin-onlabf512e942015-06-08 19:42:59 -07001916 returnValue = main.TRUE
kelvin-onlabc2dcd3f2015-04-09 16:40:02 -07001917 intentsDict = self.getIntentState( intentsId )
kelvin-onlabf512e942015-06-08 19:42:59 -07001918
Jon Hall390696c2015-05-05 17:13:41 -07001919 #print "len of intentsDict ", str( len( intentsDict ) )
kelvin-onlabc2dcd3f2015-04-09 16:40:02 -07001920 if len( intentsId ) != len( intentsDict ):
1921 main.log.info( self.name + "There is something wrong " +
1922 "getting intents state" )
1923 return main.FALSE
kelvin-onlabf512e942015-06-08 19:42:59 -07001924
1925 if isinstance( expectedState, types.StringType ):
1926 for intents in intentsDict:
1927 if intents.get( 'state' ) != expectedState:
kelvin-onlaba297c4d2015-06-01 13:53:55 -07001928 main.log.debug( self.name + " : Intent ID - " +
1929 intents.get( 'id' ) +
kelvin-onlabf512e942015-06-08 19:42:59 -07001930 " actual state = " +
1931 intents.get( 'state' )
1932 + " does not equal expected state = "
1933 + expectedState )
kelvin-onlaba297c4d2015-06-01 13:53:55 -07001934 returnValue = main.FALSE
kelvin-onlabf512e942015-06-08 19:42:59 -07001935
1936 elif isinstance( expectedState, types.ListType ):
1937 for intents in intentsDict:
1938 if not any( state == intents.get( 'state' ) for state in
1939 expectedState ):
1940 main.log.debug( self.name + " : Intent ID - " +
1941 intents.get( 'id' ) +
1942 " actual state = " +
1943 intents.get( 'state' ) +
1944 " does not equal expected states = "
1945 + str( expectedState ) )
1946 returnValue = main.FALSE
1947
kelvin-onlabc2dcd3f2015-04-09 16:40:02 -07001948 if returnValue == main.TRUE:
1949 main.log.info( self.name + ": All " +
1950 str( len( intentsDict ) ) +
kelvin-onlabf512e942015-06-08 19:42:59 -07001951 " intents are in " + str( expectedState ) +
1952 " state" )
kelvin-onlabc2dcd3f2015-04-09 16:40:02 -07001953 return returnValue
1954 except TypeError:
1955 main.log.exception( self.name + ": Object not as expected" )
1956 return None
1957 except pexpect.EOF:
1958 main.log.error( self.name + ": EOF exception found" )
1959 main.log.error( self.name + ": " + self.handle.before )
1960 main.cleanup()
1961 main.exit()
1962 except Exception:
1963 main.log.exception( self.name + ": Uncaught exception!" )
1964 main.cleanup()
1965 main.exit()
andrewonlabe6745342014-10-17 14:29:13 -04001966
kelvin-onlabd3b64892015-01-20 13:26:24 -08001967 def flows( self, jsonFormat=True ):
kelvin8ec71442015-01-15 16:57:00 -08001968 """
Shreya Shah0f01c812014-10-26 20:15:28 -04001969 Optional:
kelvin-onlabd3b64892015-01-20 13:26:24 -08001970 * jsonFormat: enable output formatting in json
Shreya Shah0f01c812014-10-26 20:15:28 -04001971 Description:
Jon Halle3f39ff2015-01-13 11:50:53 -08001972 Obtain flows currently installed
kelvin-onlab898a6c62015-01-16 14:13:53 -08001973 """
Shreya Shah0f01c812014-10-26 20:15:28 -04001974 try:
Jon Hallc6358dd2015-04-10 12:44:28 -07001975 cmdStr = "flows"
kelvin-onlabd3b64892015-01-20 13:26:24 -08001976 if jsonFormat:
Jon Hallc6358dd2015-04-10 12:44:28 -07001977 cmdStr += " -j"
1978 handle = self.sendline( cmdStr )
Jon Hall61282e32015-03-19 11:34:11 -07001979 if re.search( "Error:", handle ):
kelvin-onlaba297c4d2015-06-01 13:53:55 -07001980 main.log.error( self.name + ": flows() response: " +
kelvin-onlab898a6c62015-01-16 14:13:53 -08001981 str( handle ) )
Shreya Shah0f01c812014-10-26 20:15:28 -04001982 return handle
Jon Halld4d4b372015-01-28 16:02:41 -08001983 except TypeError:
1984 main.log.exception( self.name + ": Object not as expected" )
1985 return None
Shreya Shah0f01c812014-10-26 20:15:28 -04001986 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08001987 main.log.error( self.name + ": EOF exception found" )
1988 main.log.error( self.name + ": " + self.handle.before )
Shreya Shah0f01c812014-10-26 20:15:28 -04001989 main.cleanup()
1990 main.exit()
Jon Hallfebb1c72015-03-05 13:30:09 -08001991 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -08001992 main.log.exception( self.name + ": Uncaught exception!" )
Shreya Shah0f01c812014-10-26 20:15:28 -04001993 main.cleanup()
1994 main.exit()
1995
pingping-linbab7f8a2015-09-21 17:33:36 -07001996 def checkFlowsState( self, isPENDING_ADD = True ):
kelvin-onlab4df89f22015-04-13 18:10:23 -07001997 """
1998 Description:
1999 Check the if all the current flows are in ADDED state or
2000 PENDING_ADD state
pingping-linbab7f8a2015-09-21 17:33:36 -07002001 Optional:
2002 * isPENDING_ADD: whether the PENDING_ADD is also a correct status
kelvin-onlab4df89f22015-04-13 18:10:23 -07002003 Return:
2004 returnValue - Returns main.TRUE only if all flows are in
pingping-linbab7f8a2015-09-21 17:33:36 -07002005 ADDED state or PENDING_ADD if the PENDING_ADD
2006 parameter is set true, return main.FALSE otherwise.
kelvin-onlab4df89f22015-04-13 18:10:23 -07002007 """
2008 try:
2009 tempFlows = json.loads( self.flows() )
kelvin-onlabf0594d72015-05-19 17:25:12 -07002010 #print tempFlows[0]
kelvin-onlab4df89f22015-04-13 18:10:23 -07002011 returnValue = main.TRUE
kelvin-onlabf0594d72015-05-19 17:25:12 -07002012
pingping-linbab7f8a2015-09-21 17:33:36 -07002013 if isPENDING_ADD:
2014 for device in tempFlows:
2015 for flow in device.get( 'flows' ):
2016 if flow.get( 'state' ) != 'ADDED' and \
2017 flow.get( 'state' ) != 'PENDING_ADD':
kelvin-onlabf2ec6e02015-05-27 14:15:28 -07002018
pingping-linbab7f8a2015-09-21 17:33:36 -07002019 main.log.info( self.name + ": flow Id: " +
2020 str( flow.get( 'groupId' ) ) +
2021 " | state:" +
2022 str( flow.get( 'state' ) ) )
2023 returnValue = main.FALSE
2024 else:
2025 for device in tempFlows:
2026 for flow in device.get( 'flows' ):
2027 if flow.get( 'state' ) != 'ADDED':
2028
2029 main.log.info( self.name + ": flow Id: " +
2030 str( flow.get( 'groupId' ) ) +
2031 " | state:" +
2032 str( flow.get( 'state' ) ) )
2033 returnValue = main.FALSE
kelvin-onlabf0594d72015-05-19 17:25:12 -07002034
kelvin-onlab4df89f22015-04-13 18:10:23 -07002035 return returnValue
2036 except TypeError:
2037 main.log.exception( self.name + ": Object not as expected" )
2038 return None
2039 except pexpect.EOF:
2040 main.log.error( self.name + ": EOF exception found" )
2041 main.log.error( self.name + ": " + self.handle.before )
2042 main.cleanup()
2043 main.exit()
2044 except Exception:
2045 main.log.exception( self.name + ": Uncaught exception!" )
2046 main.cleanup()
2047 main.exit()
2048
kelvin-onlabd3b64892015-01-20 13:26:24 -08002049 def pushTestIntents( self, dpidSrc, dpidDst, numIntents,
Jon Hallefbd9792015-03-05 16:11:36 -08002050 numMult="", appId="", report=True ):
kelvin8ec71442015-01-15 16:57:00 -08002051 """
andrewonlab87852b02014-11-19 18:44:19 -05002052 Description:
Jon Halle3f39ff2015-01-13 11:50:53 -08002053 Push a number of intents in a batch format to
andrewonlab87852b02014-11-19 18:44:19 -05002054 a specific point-to-point intent definition
2055 Required:
kelvin-onlabd3b64892015-01-20 13:26:24 -08002056 * dpidSrc: specify source dpid
2057 * dpidDst: specify destination dpid
2058 * numIntents: specify number of intents to push
andrewonlab87852b02014-11-19 18:44:19 -05002059 Optional:
kelvin-onlabd3b64892015-01-20 13:26:24 -08002060 * numMult: number multiplier for multiplying
andrewonlabb66dfa12014-12-02 15:51:10 -05002061 the number of intents specified
kelvin-onlabd3b64892015-01-20 13:26:24 -08002062 * appId: specify the application id init to further
andrewonlabb66dfa12014-12-02 15:51:10 -05002063 modularize the intents
andrewonlab87852b02014-11-19 18:44:19 -05002064 * report: default True, returns latency information
kelvin8ec71442015-01-15 16:57:00 -08002065 """
andrewonlab87852b02014-11-19 18:44:19 -05002066 try:
kelvin8ec71442015-01-15 16:57:00 -08002067 cmd = "push-test-intents " +\
kelvin-onlabd3b64892015-01-20 13:26:24 -08002068 str( dpidSrc ) + " " + str( dpidDst ) + " " +\
2069 str( numIntents )
2070 if numMult:
2071 cmd += " " + str( numMult )
2072 # If app id is specified, then numMult
kelvin8ec71442015-01-15 16:57:00 -08002073 # must exist because of the way this command
kelvin-onlabd3b64892015-01-20 13:26:24 -08002074 if appId:
2075 cmd += " " + str( appId )
kelvin-onlab898a6c62015-01-16 14:13:53 -08002076 handle = self.sendline( cmd )
andrewonlab87852b02014-11-19 18:44:19 -05002077 if report:
kelvin-onlabd3b64892015-01-20 13:26:24 -08002078 latResult = []
kelvin8ec71442015-01-15 16:57:00 -08002079 main.log.info( handle )
2080 # Split result by newline
2081 newline = handle.split( "\r\r\n" )
2082 # Ignore the first object of list, which is empty
2083 newline = newline[ 1: ]
2084 # Some sloppy parsing method to get the latency
andrewonlabb66dfa12014-12-02 15:51:10 -05002085 for result in newline:
kelvin8ec71442015-01-15 16:57:00 -08002086 result = result.split( ": " )
2087 # Append the first result of second parse
kelvin-onlabd3b64892015-01-20 13:26:24 -08002088 latResult.append( result[ 1 ].split( " " )[ 0 ] )
2089 main.log.info( latResult )
2090 return latResult
andrewonlab87852b02014-11-19 18:44:19 -05002091 else:
2092 return main.TRUE
Jon Halld4d4b372015-01-28 16:02:41 -08002093 except TypeError:
2094 main.log.exception( self.name + ": Object not as expected" )
2095 return None
andrewonlab87852b02014-11-19 18:44:19 -05002096 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08002097 main.log.error( self.name + ": EOF exception found" )
2098 main.log.error( self.name + ": " + self.handle.before )
andrewonlab87852b02014-11-19 18:44:19 -05002099 main.cleanup()
2100 main.exit()
Jon Hallfebb1c72015-03-05 13:30:09 -08002101 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -08002102 main.log.exception( self.name + ": Uncaught exception!" )
andrewonlab87852b02014-11-19 18:44:19 -05002103 main.cleanup()
2104 main.exit()
2105
kelvin-onlabd3b64892015-01-20 13:26:24 -08002106 def intentsEventsMetrics( self, jsonFormat=True ):
kelvin8ec71442015-01-15 16:57:00 -08002107 """
Jon Halle3f39ff2015-01-13 11:50:53 -08002108 Description:Returns topology metrics
andrewonlab0dbb6ec2014-11-06 13:46:55 -05002109 Optional:
kelvin-onlabd3b64892015-01-20 13:26:24 -08002110 * jsonFormat: enable json formatting of output
kelvin8ec71442015-01-15 16:57:00 -08002111 """
andrewonlab0dbb6ec2014-11-06 13:46:55 -05002112 try:
Jon Hallc6358dd2015-04-10 12:44:28 -07002113 cmdStr = "intents-events-metrics"
kelvin-onlabd3b64892015-01-20 13:26:24 -08002114 if jsonFormat:
Jon Hallc6358dd2015-04-10 12:44:28 -07002115 cmdStr += " -j"
2116 handle = self.sendline( cmdStr )
andrewonlab0dbb6ec2014-11-06 13:46:55 -05002117 return handle
Jon Halld4d4b372015-01-28 16:02:41 -08002118 except TypeError:
2119 main.log.exception( self.name + ": Object not as expected" )
2120 return None
andrewonlab0dbb6ec2014-11-06 13:46:55 -05002121 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08002122 main.log.error( self.name + ": EOF exception found" )
2123 main.log.error( self.name + ": " + self.handle.before )
andrewonlab0dbb6ec2014-11-06 13:46:55 -05002124 main.cleanup()
2125 main.exit()
Jon Hallfebb1c72015-03-05 13:30:09 -08002126 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -08002127 main.log.exception( self.name + ": Uncaught exception!" )
andrewonlab0dbb6ec2014-11-06 13:46:55 -05002128 main.cleanup()
2129 main.exit()
Shreya Shah0f01c812014-10-26 20:15:28 -04002130
kelvin-onlabd3b64892015-01-20 13:26:24 -08002131 def topologyEventsMetrics( self, jsonFormat=True ):
kelvin8ec71442015-01-15 16:57:00 -08002132 """
2133 Description:Returns topology metrics
andrewonlab867212a2014-10-22 20:13:38 -04002134 Optional:
kelvin-onlabd3b64892015-01-20 13:26:24 -08002135 * jsonFormat: enable json formatting of output
kelvin8ec71442015-01-15 16:57:00 -08002136 """
andrewonlab867212a2014-10-22 20:13:38 -04002137 try:
Jon Hallc6358dd2015-04-10 12:44:28 -07002138 cmdStr = "topology-events-metrics"
kelvin-onlabd3b64892015-01-20 13:26:24 -08002139 if jsonFormat:
Jon Hallc6358dd2015-04-10 12:44:28 -07002140 cmdStr += " -j"
2141 handle = self.sendline( cmdStr )
jenkins7ead5a82015-03-13 10:28:21 -07002142 if handle:
2143 return handle
Jon Hallc6358dd2015-04-10 12:44:28 -07002144 elif jsonFormat:
Jon Hallbe379602015-03-24 13:39:32 -07002145 # Return empty json
jenkins7ead5a82015-03-13 10:28:21 -07002146 return '{}'
Jon Hallc6358dd2015-04-10 12:44:28 -07002147 else:
2148 return handle
Jon Halld4d4b372015-01-28 16:02:41 -08002149 except TypeError:
2150 main.log.exception( self.name + ": Object not as expected" )
2151 return None
andrewonlab867212a2014-10-22 20:13:38 -04002152 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08002153 main.log.error( self.name + ": EOF exception found" )
2154 main.log.error( self.name + ": " + self.handle.before )
andrewonlab867212a2014-10-22 20:13:38 -04002155 main.cleanup()
2156 main.exit()
Jon Hallfebb1c72015-03-05 13:30:09 -08002157 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -08002158 main.log.exception( self.name + ": Uncaught exception!" )
andrewonlab867212a2014-10-22 20:13:38 -04002159 main.cleanup()
2160 main.exit()
2161
kelvin8ec71442015-01-15 16:57:00 -08002162 # Wrapper functions ****************
2163 # Wrapper functions use existing driver
2164 # functions and extends their use case.
2165 # For example, we may use the output of
2166 # a normal driver function, and parse it
2167 # using a wrapper function
andrewonlabc2d05aa2014-10-13 16:51:10 -04002168
kelvin-onlabd3b64892015-01-20 13:26:24 -08002169 def getAllIntentsId( self ):
kelvin8ec71442015-01-15 16:57:00 -08002170 """
andrewonlab9a50dfe2014-10-17 17:22:31 -04002171 Description:
2172 Obtain all intent id's in a list
kelvin8ec71442015-01-15 16:57:00 -08002173 """
andrewonlab9a50dfe2014-10-17 17:22:31 -04002174 try:
kelvin8ec71442015-01-15 16:57:00 -08002175 # Obtain output of intents function
kelvin-onlabfb521662015-02-27 09:52:40 -08002176 intentsStr = self.intents(jsonFormat=False)
kelvin-onlabd3b64892015-01-20 13:26:24 -08002177 intentIdList = []
andrewonlab9a50dfe2014-10-17 17:22:31 -04002178
kelvin8ec71442015-01-15 16:57:00 -08002179 # Parse the intents output for ID's
kelvin-onlabd3b64892015-01-20 13:26:24 -08002180 intentsList = [ s.strip() for s in intentsStr.splitlines() ]
2181 for intents in intentsList:
kelvin-onlabfb521662015-02-27 09:52:40 -08002182 match = re.search('id=0x([\da-f]+),', intents)
2183 if match:
2184 tmpId = match.group()[3:-1]
2185 intentIdList.append( tmpId )
kelvin-onlabd3b64892015-01-20 13:26:24 -08002186 return intentIdList
andrewonlab9a50dfe2014-10-17 17:22:31 -04002187
Jon Halld4d4b372015-01-28 16:02:41 -08002188 except TypeError:
2189 main.log.exception( self.name + ": Object not as expected" )
2190 return None
andrewonlab9a50dfe2014-10-17 17:22:31 -04002191 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08002192 main.log.error( self.name + ": EOF exception found" )
2193 main.log.error( self.name + ": " + self.handle.before )
andrewonlab9a50dfe2014-10-17 17:22:31 -04002194 main.cleanup()
2195 main.exit()
Jon Hallfebb1c72015-03-05 13:30:09 -08002196 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -08002197 main.log.exception( self.name + ": Uncaught exception!" )
andrewonlab9a50dfe2014-10-17 17:22:31 -04002198 main.cleanup()
2199 main.exit()
2200
Jon Hall30b82fa2015-03-04 17:15:43 -08002201 def FlowAddedCount( self, deviceId ):
2202 """
2203 Determine the number of flow rules for the given device id that are
2204 in the added state
2205 """
2206 try:
2207 cmdStr = "flows any " + str( deviceId ) + " | " +\
2208 "grep 'state=ADDED' | wc -l"
2209 handle = self.sendline( cmdStr )
2210 return handle
2211 except pexpect.EOF:
2212 main.log.error( self.name + ": EOF exception found" )
2213 main.log.error( self.name + ": " + self.handle.before )
2214 main.cleanup()
2215 main.exit()
Jon Hallfebb1c72015-03-05 13:30:09 -08002216 except Exception:
Jon Hall30b82fa2015-03-04 17:15:43 -08002217 main.log.exception( self.name + ": Uncaught exception!" )
andrewonlab95ce8322014-10-13 14:12:04 -04002218 main.cleanup()
2219 main.exit()
2220
kelvin-onlabd3b64892015-01-20 13:26:24 -08002221 def getAllDevicesId( self ):
kelvin8ec71442015-01-15 16:57:00 -08002222 """
andrewonlab7e4d2d32014-10-15 13:23:21 -04002223 Use 'devices' function to obtain list of all devices
2224 and parse the result to obtain a list of all device
2225 id's. Returns this list. Returns empty list if no
2226 devices exist
kelvin8ec71442015-01-15 16:57:00 -08002227 List is ordered sequentially
2228
andrewonlab3e15ead2014-10-15 14:21:34 -04002229 This function may be useful if you are not sure of the
kelvin8ec71442015-01-15 16:57:00 -08002230 device id, and wish to execute other commands using
andrewonlab3e15ead2014-10-15 14:21:34 -04002231 the ids. By obtaining the list of device ids on the fly,
2232 you can iterate through the list to get mastership, etc.
kelvin8ec71442015-01-15 16:57:00 -08002233 """
andrewonlab7e4d2d32014-10-15 13:23:21 -04002234 try:
kelvin8ec71442015-01-15 16:57:00 -08002235 # Call devices and store result string
kelvin-onlabd3b64892015-01-20 13:26:24 -08002236 devicesStr = self.devices( jsonFormat=False )
2237 idList = []
kelvin8ec71442015-01-15 16:57:00 -08002238
kelvin-onlabd3b64892015-01-20 13:26:24 -08002239 if not devicesStr:
kelvin8ec71442015-01-15 16:57:00 -08002240 main.log.info( "There are no devices to get id from" )
kelvin-onlabd3b64892015-01-20 13:26:24 -08002241 return idList
kelvin8ec71442015-01-15 16:57:00 -08002242
2243 # Split the string into list by comma
kelvin-onlabd3b64892015-01-20 13:26:24 -08002244 deviceList = devicesStr.split( "," )
kelvin8ec71442015-01-15 16:57:00 -08002245 # Get temporary list of all arguments with string 'id='
kelvin-onlabd3b64892015-01-20 13:26:24 -08002246 tempList = [ dev for dev in deviceList if "id=" in dev ]
kelvin8ec71442015-01-15 16:57:00 -08002247 # Split list further into arguments before and after string
2248 # 'id='. Get the latter portion ( the actual device id ) and
kelvin-onlabd3b64892015-01-20 13:26:24 -08002249 # append to idList
2250 for arg in tempList:
2251 idList.append( arg.split( "id=" )[ 1 ] )
2252 return idList
andrewonlab7e4d2d32014-10-15 13:23:21 -04002253
Jon Halld4d4b372015-01-28 16:02:41 -08002254 except TypeError:
2255 main.log.exception( self.name + ": Object not as expected" )
2256 return None
andrewonlab7e4d2d32014-10-15 13:23:21 -04002257 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08002258 main.log.error( self.name + ": EOF exception found" )
2259 main.log.error( self.name + ": " + self.handle.before )
andrewonlab7e4d2d32014-10-15 13:23:21 -04002260 main.cleanup()
2261 main.exit()
Jon Hallfebb1c72015-03-05 13:30:09 -08002262 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -08002263 main.log.exception( self.name + ": Uncaught exception!" )
andrewonlab7e4d2d32014-10-15 13:23:21 -04002264 main.cleanup()
2265 main.exit()
2266
kelvin-onlabd3b64892015-01-20 13:26:24 -08002267 def getAllNodesId( self ):
kelvin8ec71442015-01-15 16:57:00 -08002268 """
andrewonlab7c211572014-10-15 16:45:20 -04002269 Uses 'nodes' function to obtain list of all nodes
2270 and parse the result of nodes to obtain just the
kelvin8ec71442015-01-15 16:57:00 -08002271 node id's.
andrewonlab7c211572014-10-15 16:45:20 -04002272 Returns:
2273 list of node id's
kelvin8ec71442015-01-15 16:57:00 -08002274 """
andrewonlab7c211572014-10-15 16:45:20 -04002275 try:
Jon Hall5aa168b2015-03-23 14:23:09 -07002276 nodesStr = self.nodes( jsonFormat=True )
kelvin-onlabd3b64892015-01-20 13:26:24 -08002277 idList = []
Jon Hall5aa168b2015-03-23 14:23:09 -07002278 # Sample nodesStr output
2279 # id=local, address=127.0.0.1:9876, state=ACTIVE *
kelvin-onlabd3b64892015-01-20 13:26:24 -08002280 if not nodesStr:
kelvin8ec71442015-01-15 16:57:00 -08002281 main.log.info( "There are no nodes to get id from" )
kelvin-onlabd3b64892015-01-20 13:26:24 -08002282 return idList
Jon Hall5aa168b2015-03-23 14:23:09 -07002283 nodesJson = json.loads( nodesStr )
2284 idList = [ node.get('id') for node in nodesJson ]
kelvin-onlabd3b64892015-01-20 13:26:24 -08002285 return idList
kelvin8ec71442015-01-15 16:57:00 -08002286
Jon Halld4d4b372015-01-28 16:02:41 -08002287 except TypeError:
2288 main.log.exception( self.name + ": Object not as expected" )
2289 return None
andrewonlab7c211572014-10-15 16:45:20 -04002290 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08002291 main.log.error( self.name + ": EOF exception found" )
2292 main.log.error( self.name + ": " + self.handle.before )
andrewonlab7c211572014-10-15 16:45:20 -04002293 main.cleanup()
2294 main.exit()
Jon Hallfebb1c72015-03-05 13:30:09 -08002295 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -08002296 main.log.exception( self.name + ": Uncaught exception!" )
andrewonlab7c211572014-10-15 16:45:20 -04002297 main.cleanup()
2298 main.exit()
andrewonlab7e4d2d32014-10-15 13:23:21 -04002299
kelvin-onlabd3b64892015-01-20 13:26:24 -08002300 def getDevice( self, dpid=None ):
kelvin8ec71442015-01-15 16:57:00 -08002301 """
Jon Halla91c4dc2014-10-22 12:57:04 -04002302 Return the first device from the devices api whose 'id' contains 'dpid'
2303 Return None if there is no match
kelvin8ec71442015-01-15 16:57:00 -08002304 """
Jon Halla91c4dc2014-10-22 12:57:04 -04002305 try:
kelvin8ec71442015-01-15 16:57:00 -08002306 if dpid is None:
Jon Halla91c4dc2014-10-22 12:57:04 -04002307 return None
2308 else:
kelvin8ec71442015-01-15 16:57:00 -08002309 dpid = dpid.replace( ':', '' )
kelvin-onlabd3b64892015-01-20 13:26:24 -08002310 rawDevices = self.devices()
2311 devicesJson = json.loads( rawDevices )
kelvin8ec71442015-01-15 16:57:00 -08002312 # search json for the device with dpid then return the device
kelvin-onlabd3b64892015-01-20 13:26:24 -08002313 for device in devicesJson:
kelvin8ec71442015-01-15 16:57:00 -08002314 # print "%s in %s?" % ( dpid, device[ 'id' ] )
2315 if dpid in device[ 'id' ]:
Jon Halla91c4dc2014-10-22 12:57:04 -04002316 return device
2317 return None
Jon Halld4d4b372015-01-28 16:02:41 -08002318 except TypeError:
2319 main.log.exception( self.name + ": Object not as expected" )
2320 return None
Jon Halla91c4dc2014-10-22 12:57:04 -04002321 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08002322 main.log.error( self.name + ": EOF exception found" )
2323 main.log.error( self.name + ": " + self.handle.before )
Jon Halla91c4dc2014-10-22 12:57:04 -04002324 main.cleanup()
2325 main.exit()
Jon Hallfebb1c72015-03-05 13:30:09 -08002326 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -08002327 main.log.exception( self.name + ": Uncaught exception!" )
Jon Halla91c4dc2014-10-22 12:57:04 -04002328 main.cleanup()
2329 main.exit()
2330
kelvin-onlabd3b64892015-01-20 13:26:24 -08002331 def checkStatus( self, ip, numoswitch, numolink, logLevel="info" ):
kelvin8ec71442015-01-15 16:57:00 -08002332 """
Jon Hallefbd9792015-03-05 16:11:36 -08002333 Checks the number of switches & links that ONOS sees against the
kelvin8ec71442015-01-15 16:57:00 -08002334 supplied values. By default this will report to main.log, but the
Jon Hallefbd9792015-03-05 16:11:36 -08002335 log level can be specified.
kelvin8ec71442015-01-15 16:57:00 -08002336
Jon Hall42db6dc2014-10-24 19:03:48 -04002337 Params: ip = ip used for the onos cli
2338 numoswitch = expected number of switches
Jon Hallefbd9792015-03-05 16:11:36 -08002339 numolink = expected number of links
kelvin-onlabd3b64892015-01-20 13:26:24 -08002340 logLevel = level to log to. Currently accepts
2341 'info', 'warn' and 'report'
Jon Hall42db6dc2014-10-24 19:03:48 -04002342
2343
kelvin-onlabd3b64892015-01-20 13:26:24 -08002344 logLevel can
Jon Hall42db6dc2014-10-24 19:03:48 -04002345
Jon Hallefbd9792015-03-05 16:11:36 -08002346 Returns: main.TRUE if the number of switches and links are correct,
2347 main.FALSE if the number of switches and links is incorrect,
Jon Hall42db6dc2014-10-24 19:03:48 -04002348 and main.ERROR otherwise
kelvin8ec71442015-01-15 16:57:00 -08002349 """
Jon Hall42db6dc2014-10-24 19:03:48 -04002350 try:
kelvin-onlabd3b64892015-01-20 13:26:24 -08002351 topology = self.getTopology( ip )
Jon Hall42db6dc2014-10-24 19:03:48 -04002352 if topology == {}:
2353 return main.ERROR
2354 output = ""
kelvin8ec71442015-01-15 16:57:00 -08002355 # Is the number of switches is what we expected
2356 devices = topology.get( 'devices', False )
2357 links = topology.get( 'links', False )
kelvin-onlabfb521662015-02-27 09:52:40 -08002358 if devices is False or links is False:
Jon Hall42db6dc2014-10-24 19:03:48 -04002359 return main.ERROR
kelvin-onlabd3b64892015-01-20 13:26:24 -08002360 switchCheck = ( int( devices ) == int( numoswitch ) )
kelvin8ec71442015-01-15 16:57:00 -08002361 # Is the number of links is what we expected
kelvin-onlabd3b64892015-01-20 13:26:24 -08002362 linkCheck = ( int( links ) == int( numolink ) )
2363 if ( switchCheck and linkCheck ):
kelvin8ec71442015-01-15 16:57:00 -08002364 # We expected the correct numbers
Jon Hallefbd9792015-03-05 16:11:36 -08002365 output += "The number of links and switches match " +\
2366 "what was expected"
Jon Hall42db6dc2014-10-24 19:03:48 -04002367 result = main.TRUE
2368 else:
Jon Hallefbd9792015-03-05 16:11:36 -08002369 output += "The number of links and switches does not match " +\
2370 "what was expected"
Jon Hall42db6dc2014-10-24 19:03:48 -04002371 result = main.FALSE
kelvin-onlabd3b64892015-01-20 13:26:24 -08002372 output = output + "\n ONOS sees %i devices (%i expected) \
2373 and %i links (%i expected)" % (
2374 int( devices ), int( numoswitch ), int( links ),
2375 int( numolink ) )
2376 if logLevel == "report":
kelvin8ec71442015-01-15 16:57:00 -08002377 main.log.report( output )
kelvin-onlabd3b64892015-01-20 13:26:24 -08002378 elif logLevel == "warn":
kelvin8ec71442015-01-15 16:57:00 -08002379 main.log.warn( output )
Jon Hall42db6dc2014-10-24 19:03:48 -04002380 else:
Jon Hall390696c2015-05-05 17:13:41 -07002381 main.log.info( self.name + ": " + output )
kelvin8ec71442015-01-15 16:57:00 -08002382 return result
Jon Halld4d4b372015-01-28 16:02:41 -08002383 except TypeError:
2384 main.log.exception( self.name + ": Object not as expected" )
2385 return None
Jon Hall42db6dc2014-10-24 19:03:48 -04002386 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08002387 main.log.error( self.name + ": EOF exception found" )
2388 main.log.error( self.name + ": " + self.handle.before )
Jon Hall42db6dc2014-10-24 19:03:48 -04002389 main.cleanup()
2390 main.exit()
Jon Hallfebb1c72015-03-05 13:30:09 -08002391 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -08002392 main.log.exception( self.name + ": Uncaught exception!" )
Jon Hall42db6dc2014-10-24 19:03:48 -04002393 main.cleanup()
2394 main.exit()
Jon Hall1c9e8732014-10-27 19:29:27 -04002395
kelvin-onlabd3b64892015-01-20 13:26:24 -08002396 def deviceRole( self, deviceId, onosNode, role="master" ):
kelvin8ec71442015-01-15 16:57:00 -08002397 """
Jon Hall1c9e8732014-10-27 19:29:27 -04002398 Calls the device-role cli command.
kelvin-onlabd3b64892015-01-20 13:26:24 -08002399 deviceId must be the id of a device as seen in the onos devices command
2400 onosNode is the ip of one of the onos nodes in the cluster
Jon Hall1c9e8732014-10-27 19:29:27 -04002401 role must be either master, standby, or none
2402
Jon Halle3f39ff2015-01-13 11:50:53 -08002403 Returns:
2404 main.TRUE or main.FALSE based on argument verification and
2405 main.ERROR if command returns and error
kelvin-onlab898a6c62015-01-16 14:13:53 -08002406 """
Jon Hall1c9e8732014-10-27 19:29:27 -04002407 try:
Jon Halle3f39ff2015-01-13 11:50:53 -08002408 if role.lower() == "master" or role.lower() == "standby" or\
Jon Hall1c9e8732014-10-27 19:29:27 -04002409 role.lower() == "none":
kelvin-onlabd3b64892015-01-20 13:26:24 -08002410 cmdStr = "device-role " +\
2411 str( deviceId ) + " " +\
2412 str( onosNode ) + " " +\
kelvin-onlab898a6c62015-01-16 14:13:53 -08002413 str( role )
kelvin-onlabd3b64892015-01-20 13:26:24 -08002414 handle = self.sendline( cmdStr )
kelvin-onlab898a6c62015-01-16 14:13:53 -08002415 if re.search( "Error", handle ):
2416 # end color output to escape any colours
2417 # from the cli
kelvin8ec71442015-01-15 16:57:00 -08002418 main.log.error( self.name + ": " +
kelvin-onlab898a6c62015-01-16 14:13:53 -08002419 handle + '\033[0m' )
kelvin8ec71442015-01-15 16:57:00 -08002420 return main.ERROR
kelvin8ec71442015-01-15 16:57:00 -08002421 return main.TRUE
Jon Hall1c9e8732014-10-27 19:29:27 -04002422 else:
kelvin-onlab898a6c62015-01-16 14:13:53 -08002423 main.log.error( "Invalid 'role' given to device_role(). " +
2424 "Value was '" + str(role) + "'." )
Jon Hall1c9e8732014-10-27 19:29:27 -04002425 return main.FALSE
Jon Halld4d4b372015-01-28 16:02:41 -08002426 except TypeError:
2427 main.log.exception( self.name + ": Object not as expected" )
2428 return None
Jon Hall1c9e8732014-10-27 19:29:27 -04002429 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08002430 main.log.error( self.name + ": EOF exception found" )
2431 main.log.error( self.name + ": " + self.handle.before )
Jon Hall1c9e8732014-10-27 19:29:27 -04002432 main.cleanup()
2433 main.exit()
Jon Hallfebb1c72015-03-05 13:30:09 -08002434 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -08002435 main.log.exception( self.name + ": Uncaught exception!" )
Jon Hall1c9e8732014-10-27 19:29:27 -04002436 main.cleanup()
2437 main.exit()
2438
kelvin-onlabd3b64892015-01-20 13:26:24 -08002439 def clusters( self, jsonFormat=True ):
kelvin8ec71442015-01-15 16:57:00 -08002440 """
Jon Hall73cf9cc2014-11-20 22:28:38 -08002441 Lists all clusters
Jon Hallffb386d2014-11-21 13:43:38 -08002442 Optional argument:
kelvin-onlabd3b64892015-01-20 13:26:24 -08002443 * jsonFormat - boolean indicating if you want output in json
kelvin8ec71442015-01-15 16:57:00 -08002444 """
Jon Hall73cf9cc2014-11-20 22:28:38 -08002445 try:
Jon Hallc6358dd2015-04-10 12:44:28 -07002446 cmdStr = "clusters"
kelvin-onlabd3b64892015-01-20 13:26:24 -08002447 if jsonFormat:
Jon Hallc6358dd2015-04-10 12:44:28 -07002448 cmdStr += " -j"
2449 handle = self.sendline( cmdStr )
2450 return handle
Jon Halld4d4b372015-01-28 16:02:41 -08002451 except TypeError:
2452 main.log.exception( self.name + ": Object not as expected" )
2453 return None
Jon Hall73cf9cc2014-11-20 22:28:38 -08002454 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08002455 main.log.error( self.name + ": EOF exception found" )
2456 main.log.error( self.name + ": " + self.handle.before )
Jon Hall73cf9cc2014-11-20 22:28:38 -08002457 main.cleanup()
2458 main.exit()
Jon Hallfebb1c72015-03-05 13:30:09 -08002459 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -08002460 main.log.exception( self.name + ": Uncaught exception!" )
Jon Hall73cf9cc2014-11-20 22:28:38 -08002461 main.cleanup()
2462 main.exit()
2463
kelvin-onlabd3b64892015-01-20 13:26:24 -08002464 def electionTestLeader( self ):
kelvin-onlab898a6c62015-01-16 14:13:53 -08002465 """
Jon Halle3f39ff2015-01-13 11:50:53 -08002466 CLI command to get the current leader for the Election test application
2467 NOTE: Requires installation of the onos-app-election feature
2468 Returns: Node IP of the leader if one exists
2469 None if none exists
2470 Main.FALSE on error
kelvin-onlab898a6c62015-01-16 14:13:53 -08002471 """
Jon Hall94fd0472014-12-08 11:52:42 -08002472 try:
kelvin-onlabd3b64892015-01-20 13:26:24 -08002473 cmdStr = "election-test-leader"
2474 response = self.sendline( cmdStr )
Jon Halle3f39ff2015-01-13 11:50:53 -08002475 # Leader
2476 leaderPattern = "The\scurrent\sleader\sfor\sthe\sElection\s" +\
kelvin-onlab898a6c62015-01-16 14:13:53 -08002477 "app\sis\s(?P<node>.+)\."
kelvin-onlabd3b64892015-01-20 13:26:24 -08002478 nodeSearch = re.search( leaderPattern, response )
2479 if nodeSearch:
2480 node = nodeSearch.group( 'node' )
Jon Halle3f39ff2015-01-13 11:50:53 -08002481 main.log.info( "Election-test-leader on " + str( self.name ) +
kelvin-onlab898a6c62015-01-16 14:13:53 -08002482 " found " + node + " as the leader" )
Jon Hall94fd0472014-12-08 11:52:42 -08002483 return node
Jon Halle3f39ff2015-01-13 11:50:53 -08002484 # no leader
2485 nullPattern = "There\sis\scurrently\sno\sleader\selected\sfor\s" +\
kelvin-onlab898a6c62015-01-16 14:13:53 -08002486 "the\sElection\sapp"
kelvin-onlabd3b64892015-01-20 13:26:24 -08002487 nullSearch = re.search( nullPattern, response )
2488 if nullSearch:
Jon Halle3f39ff2015-01-13 11:50:53 -08002489 main.log.info( "Election-test-leader found no leader on " +
kelvin-onlab898a6c62015-01-16 14:13:53 -08002490 self.name )
Jon Hall94fd0472014-12-08 11:52:42 -08002491 return None
kelvin-onlab898a6c62015-01-16 14:13:53 -08002492 # error
Jon Halle3f39ff2015-01-13 11:50:53 -08002493 errorPattern = "Command\snot\sfound"
kelvin-onlab898a6c62015-01-16 14:13:53 -08002494 if re.search( errorPattern, response ):
2495 main.log.error( "Election app is not loaded on " + self.name )
Jon Halle3f39ff2015-01-13 11:50:53 -08002496 # TODO: Should this be main.ERROR?
Jon Hall669173b2014-12-17 11:36:30 -08002497 return main.FALSE
2498 else:
Jon Hall390696c2015-05-05 17:13:41 -07002499 main.log.error( "Error in electionTestLeader on " + self.name +
2500 ": " + "unexpected response" )
kelvin8ec71442015-01-15 16:57:00 -08002501 main.log.error( repr( response ) )
Jon Hall669173b2014-12-17 11:36:30 -08002502 return main.FALSE
Jon Halld4d4b372015-01-28 16:02:41 -08002503 except TypeError:
2504 main.log.exception( self.name + ": Object not as expected" )
2505 return main.FALSE
Jon Hall94fd0472014-12-08 11:52:42 -08002506 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08002507 main.log.error( self.name + ": EOF exception found" )
2508 main.log.error( self.name + ": " + self.handle.before )
Jon Hall94fd0472014-12-08 11:52:42 -08002509 main.cleanup()
2510 main.exit()
Jon Hallfebb1c72015-03-05 13:30:09 -08002511 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -08002512 main.log.exception( self.name + ": Uncaught exception!" )
Jon Hall94fd0472014-12-08 11:52:42 -08002513 main.cleanup()
2514 main.exit()
2515
kelvin-onlabd3b64892015-01-20 13:26:24 -08002516 def electionTestRun( self ):
kelvin-onlab898a6c62015-01-16 14:13:53 -08002517 """
Jon Halle3f39ff2015-01-13 11:50:53 -08002518 CLI command to run for leadership of the Election test application.
2519 NOTE: Requires installation of the onos-app-election feature
2520 Returns: Main.TRUE on success
2521 Main.FALSE on error
kelvin-onlab898a6c62015-01-16 14:13:53 -08002522 """
Jon Hall94fd0472014-12-08 11:52:42 -08002523 try:
kelvin-onlabd3b64892015-01-20 13:26:24 -08002524 cmdStr = "election-test-run"
2525 response = self.sendline( cmdStr )
kelvin-onlab898a6c62015-01-16 14:13:53 -08002526 # success
Jon Halle3f39ff2015-01-13 11:50:53 -08002527 successPattern = "Entering\sleadership\selections\sfor\sthe\s" +\
kelvin-onlab898a6c62015-01-16 14:13:53 -08002528 "Election\sapp."
Jon Halle3f39ff2015-01-13 11:50:53 -08002529 search = re.search( successPattern, response )
Jon Hall94fd0472014-12-08 11:52:42 -08002530 if search:
Jon Halle3f39ff2015-01-13 11:50:53 -08002531 main.log.info( self.name + " entering leadership elections " +
kelvin-onlab898a6c62015-01-16 14:13:53 -08002532 "for the Election app." )
Jon Hall94fd0472014-12-08 11:52:42 -08002533 return main.TRUE
kelvin-onlab898a6c62015-01-16 14:13:53 -08002534 # error
Jon Halle3f39ff2015-01-13 11:50:53 -08002535 errorPattern = "Command\snot\sfound"
2536 if re.search( errorPattern, response ):
2537 main.log.error( "Election app is not loaded on " + self.name )
Jon Hall669173b2014-12-17 11:36:30 -08002538 return main.FALSE
2539 else:
Jon Hall390696c2015-05-05 17:13:41 -07002540 main.log.error( "Error in electionTestRun on " + self.name +
2541 ": " + "unexpected response" )
Jon Halle3f39ff2015-01-13 11:50:53 -08002542 main.log.error( repr( response ) )
Jon Hall669173b2014-12-17 11:36:30 -08002543 return main.FALSE
Jon Halld4d4b372015-01-28 16:02:41 -08002544 except TypeError:
2545 main.log.exception( self.name + ": Object not as expected" )
2546 return main.FALSE
Jon Hall94fd0472014-12-08 11:52:42 -08002547 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08002548 main.log.error( self.name + ": EOF exception found" )
2549 main.log.error( self.name + ": " + self.handle.before )
Jon Hall94fd0472014-12-08 11:52:42 -08002550 main.cleanup()
2551 main.exit()
Jon Hallfebb1c72015-03-05 13:30:09 -08002552 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -08002553 main.log.exception( self.name + ": Uncaught exception!" )
Jon Hall94fd0472014-12-08 11:52:42 -08002554 main.cleanup()
2555 main.exit()
2556
kelvin-onlabd3b64892015-01-20 13:26:24 -08002557 def electionTestWithdraw( self ):
kelvin8ec71442015-01-15 16:57:00 -08002558 """
Jon Hall94fd0472014-12-08 11:52:42 -08002559 * CLI command to withdraw the local node from leadership election for
2560 * the Election test application.
2561 #NOTE: Requires installation of the onos-app-election feature
2562 Returns: Main.TRUE on success
2563 Main.FALSE on error
kelvin8ec71442015-01-15 16:57:00 -08002564 """
Jon Hall94fd0472014-12-08 11:52:42 -08002565 try:
kelvin-onlabd3b64892015-01-20 13:26:24 -08002566 cmdStr = "election-test-withdraw"
2567 response = self.sendline( cmdStr )
kelvin-onlab898a6c62015-01-16 14:13:53 -08002568 # success
Jon Halle3f39ff2015-01-13 11:50:53 -08002569 successPattern = "Withdrawing\sfrom\sleadership\selections\sfor" +\
kelvin-onlab898a6c62015-01-16 14:13:53 -08002570 "\sthe\sElection\sapp."
Jon Halle3f39ff2015-01-13 11:50:53 -08002571 if re.search( successPattern, response ):
2572 main.log.info( self.name + " withdrawing from leadership " +
kelvin-onlab898a6c62015-01-16 14:13:53 -08002573 "elections for the Election app." )
Jon Hall94fd0472014-12-08 11:52:42 -08002574 return main.TRUE
kelvin-onlab898a6c62015-01-16 14:13:53 -08002575 # error
Jon Halle3f39ff2015-01-13 11:50:53 -08002576 errorPattern = "Command\snot\sfound"
2577 if re.search( errorPattern, response ):
2578 main.log.error( "Election app is not loaded on " + self.name )
Jon Hall669173b2014-12-17 11:36:30 -08002579 return main.FALSE
2580 else:
Jon Hall390696c2015-05-05 17:13:41 -07002581 main.log.error( "Error in electionTestWithdraw on " +
2582 self.name + ": " + "unexpected response" )
Jon Halle3f39ff2015-01-13 11:50:53 -08002583 main.log.error( repr( response ) )
Jon Hall669173b2014-12-17 11:36:30 -08002584 return main.FALSE
Jon Halld4d4b372015-01-28 16:02:41 -08002585 except TypeError:
2586 main.log.exception( self.name + ": Object not as expected" )
2587 return main.FALSE
Jon Hall94fd0472014-12-08 11:52:42 -08002588 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08002589 main.log.error( self.name + ": EOF exception found" )
2590 main.log.error( self.name + ": " + self.handle.before )
Jon Hall94fd0472014-12-08 11:52:42 -08002591 main.cleanup()
2592 main.exit()
Jon Hallfebb1c72015-03-05 13:30:09 -08002593 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -08002594 main.log.exception( self.name + ": Uncaught exception!" )
Jon Hall94fd0472014-12-08 11:52:42 -08002595 main.cleanup()
2596 main.exit()
Jon Hall1c9e8732014-10-27 19:29:27 -04002597
kelvin8ec71442015-01-15 16:57:00 -08002598 def getDevicePortsEnabledCount( self, dpid ):
2599 """
Hari Krishnaa43d4e92014-12-19 13:22:40 -08002600 Get the count of all enabled ports on a particular device/switch
kelvin8ec71442015-01-15 16:57:00 -08002601 """
Hari Krishnaa43d4e92014-12-19 13:22:40 -08002602 try:
Jon Halle3f39ff2015-01-13 11:50:53 -08002603 dpid = str( dpid )
kelvin-onlabd3b64892015-01-20 13:26:24 -08002604 cmdStr = "onos:ports -e " + dpid + " | wc -l"
2605 output = self.sendline( cmdStr )
Jon Halle3f39ff2015-01-13 11:50:53 -08002606 if re.search( "No such device", output ):
2607 main.log.error( "Error in getting ports" )
2608 return ( output, "Error" )
Hari Krishnaa43d4e92014-12-19 13:22:40 -08002609 else:
Jon Halle3f39ff2015-01-13 11:50:53 -08002610 return output
Jon Halld4d4b372015-01-28 16:02:41 -08002611 except TypeError:
2612 main.log.exception( self.name + ": Object not as expected" )
2613 return ( output, "Error" )
Hari Krishnaa43d4e92014-12-19 13:22:40 -08002614 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08002615 main.log.error( self.name + ": EOF exception found" )
2616 main.log.error( self.name + ": " + self.handle.before )
Hari Krishnaa43d4e92014-12-19 13:22:40 -08002617 main.cleanup()
2618 main.exit()
Jon Hallfebb1c72015-03-05 13:30:09 -08002619 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -08002620 main.log.exception( self.name + ": Uncaught exception!" )
Hari Krishnaa43d4e92014-12-19 13:22:40 -08002621 main.cleanup()
2622 main.exit()
2623
kelvin8ec71442015-01-15 16:57:00 -08002624 def getDeviceLinksActiveCount( self, dpid ):
2625 """
Hari Krishnaa43d4e92014-12-19 13:22:40 -08002626 Get the count of all enabled ports on a particular device/switch
kelvin8ec71442015-01-15 16:57:00 -08002627 """
Hari Krishnaa43d4e92014-12-19 13:22:40 -08002628 try:
kelvin-onlab898a6c62015-01-16 14:13:53 -08002629 dpid = str( dpid )
kelvin-onlabd3b64892015-01-20 13:26:24 -08002630 cmdStr = "onos:links " + dpid + " | grep ACTIVE | wc -l"
2631 output = self.sendline( cmdStr )
Jon Halle3f39ff2015-01-13 11:50:53 -08002632 if re.search( "No such device", output ):
kelvin-onlab898a6c62015-01-16 14:13:53 -08002633 main.log.error( "Error in getting ports " )
2634 return ( output, "Error " )
Hari Krishnaa43d4e92014-12-19 13:22:40 -08002635 else:
Jon Halle3f39ff2015-01-13 11:50:53 -08002636 return output
Jon Halld4d4b372015-01-28 16:02:41 -08002637 except TypeError:
2638 main.log.exception( self.name + ": Object not as expected" )
2639 return ( output, "Error " )
Hari Krishnaa43d4e92014-12-19 13:22:40 -08002640 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08002641 main.log.error( self.name + ": EOF exception found" )
2642 main.log.error( self.name + ": " + self.handle.before )
Hari Krishnaa43d4e92014-12-19 13:22:40 -08002643 main.cleanup()
2644 main.exit()
Jon Hallfebb1c72015-03-05 13:30:09 -08002645 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -08002646 main.log.exception( self.name + ": Uncaught exception!" )
Hari Krishnaa43d4e92014-12-19 13:22:40 -08002647 main.cleanup()
2648 main.exit()
2649
kelvin8ec71442015-01-15 16:57:00 -08002650 def getAllIntentIds( self ):
2651 """
Hari Krishnaa43d4e92014-12-19 13:22:40 -08002652 Return a list of all Intent IDs
kelvin8ec71442015-01-15 16:57:00 -08002653 """
Hari Krishnaa43d4e92014-12-19 13:22:40 -08002654 try:
kelvin-onlabd3b64892015-01-20 13:26:24 -08002655 cmdStr = "onos:intents | grep id="
2656 output = self.sendline( cmdStr )
Jon Halle3f39ff2015-01-13 11:50:53 -08002657 if re.search( "Error", output ):
2658 main.log.error( "Error in getting ports" )
2659 return ( output, "Error" )
Hari Krishnaa43d4e92014-12-19 13:22:40 -08002660 else:
Jon Halle3f39ff2015-01-13 11:50:53 -08002661 return output
Jon Halld4d4b372015-01-28 16:02:41 -08002662 except TypeError:
2663 main.log.exception( self.name + ": Object not as expected" )
2664 return ( output, "Error" )
Hari Krishnaa43d4e92014-12-19 13:22:40 -08002665 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08002666 main.log.error( self.name + ": EOF exception found" )
2667 main.log.error( self.name + ": " + self.handle.before )
Hari Krishnaa43d4e92014-12-19 13:22:40 -08002668 main.cleanup()
2669 main.exit()
Jon Hallfebb1c72015-03-05 13:30:09 -08002670 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -08002671 main.log.exception( self.name + ": Uncaught exception!" )
2672 main.cleanup()
2673 main.exit()
2674
Jon Hall73509952015-02-24 16:42:56 -08002675 def intentSummary( self ):
2676 """
Jon Hallefbd9792015-03-05 16:11:36 -08002677 Returns a dictionary containing the current intent states and the count
Jon Hall73509952015-02-24 16:42:56 -08002678 """
2679 try:
2680 intents = self.intents( )
Jon Hall08f61bc2015-04-13 16:00:30 -07002681 states = []
Jon Hall5aa168b2015-03-23 14:23:09 -07002682 for intent in json.loads( intents ):
Jon Hall08f61bc2015-04-13 16:00:30 -07002683 states.append( intent.get( 'state', None ) )
2684 out = [ ( i, states.count( i ) ) for i in set( states ) ]
Jon Hall63604932015-02-26 17:09:50 -08002685 main.log.info( dict( out ) )
Jon Hall73509952015-02-24 16:42:56 -08002686 return dict( out )
2687 except TypeError:
2688 main.log.exception( self.name + ": Object not as expected" )
2689 return None
2690 except pexpect.EOF:
2691 main.log.error( self.name + ": EOF exception found" )
2692 main.log.error( self.name + ": " + self.handle.before )
2693 main.cleanup()
2694 main.exit()
Jon Hallfebb1c72015-03-05 13:30:09 -08002695 except Exception:
Jon Hall73509952015-02-24 16:42:56 -08002696 main.log.exception( self.name + ": Uncaught exception!" )
2697 main.cleanup()
2698 main.exit()
Jon Hall63604932015-02-26 17:09:50 -08002699
Jon Hall61282e32015-03-19 11:34:11 -07002700 def leaders( self, jsonFormat=True ):
Jon Hall63604932015-02-26 17:09:50 -08002701 """
2702 Returns the output of the leaders command.
Jon Hall61282e32015-03-19 11:34:11 -07002703 Optional argument:
2704 * jsonFormat - boolean indicating if you want output in json
Jon Hall63604932015-02-26 17:09:50 -08002705 """
Jon Hall63604932015-02-26 17:09:50 -08002706 try:
Jon Hallc6358dd2015-04-10 12:44:28 -07002707 cmdStr = "onos:leaders"
Jon Hall61282e32015-03-19 11:34:11 -07002708 if jsonFormat:
Jon Hallc6358dd2015-04-10 12:44:28 -07002709 cmdStr += " -j"
2710 output = self.sendline( cmdStr )
2711 return output
Jon Hall63604932015-02-26 17:09:50 -08002712 except TypeError:
2713 main.log.exception( self.name + ": Object not as expected" )
2714 return None
Hari Krishnaa43d4e92014-12-19 13:22:40 -08002715 except pexpect.EOF:
2716 main.log.error( self.name + ": EOF exception found" )
2717 main.log.error( self.name + ": " + self.handle.before )
2718 main.cleanup()
2719 main.exit()
Jon Hall77ba41c2015-04-06 10:25:40 -07002720 except Exception:
Jon Hall63604932015-02-26 17:09:50 -08002721 main.log.exception( self.name + ": Uncaught exception!" )
Hari Krishnaa43d4e92014-12-19 13:22:40 -08002722 main.cleanup()
2723 main.exit()
Jon Hall63604932015-02-26 17:09:50 -08002724
acsmarsa4a4d1e2015-07-10 16:01:24 -07002725 def leaderCandidates( self, jsonFormat=True ):
2726 """
2727 Returns the output of the leaders -c command.
2728 Optional argument:
2729 * jsonFormat - boolean indicating if you want output in json
2730 """
2731 try:
2732 cmdStr = "onos:leaders -c"
2733 if jsonFormat:
2734 cmdStr += " -j"
2735 output = self.sendline( cmdStr )
2736 return output
2737 except TypeError:
2738 main.log.exception( self.name + ": Object not as expected" )
2739 return None
2740 except pexpect.EOF:
2741 main.log.error( self.name + ": EOF exception found" )
2742 main.log.error( self.name + ": " + self.handle.before )
2743 main.cleanup()
2744 main.exit()
2745 except Exception:
2746 main.log.exception( self.name + ": Uncaught exception!" )
2747 main.cleanup()
2748 main.exit()
2749
2750 def specificLeaderCandidate(self,topic):
2751 """
2752 Returns a list in format [leader,candidate1,candidate2,...] for a given
2753 topic parameter and an empty list if the topic doesn't exist
2754 If no leader is elected leader in the returned list will be "none"
2755 Returns None if there is a type error processing the json object
2756 """
2757 try:
2758 cmdStr = "onos:leaders -c -j"
2759 output = self.sendline( cmdStr )
2760 output = json.loads(output)
2761 results = []
2762 for dict in output:
2763 if dict["topic"] == topic:
2764 leader = dict["leader"]
2765 candidates = re.split(", ",dict["candidates"][1:-1])
2766 results.append(leader)
2767 results.extend(candidates)
2768 return results
2769 except TypeError:
2770 main.log.exception( self.name + ": Object not as expected" )
2771 return None
2772 except pexpect.EOF:
2773 main.log.error( self.name + ": EOF exception found" )
2774 main.log.error( self.name + ": " + self.handle.before )
2775 main.cleanup()
2776 main.exit()
2777 except Exception:
2778 main.log.exception( self.name + ": Uncaught exception!" )
2779 main.cleanup()
2780 main.exit()
2781
Jon Hall61282e32015-03-19 11:34:11 -07002782 def pendingMap( self, jsonFormat=True ):
Jon Hall63604932015-02-26 17:09:50 -08002783 """
2784 Returns the output of the intent Pending map.
2785 """
Jon Hall63604932015-02-26 17:09:50 -08002786 try:
Jon Hallc6358dd2015-04-10 12:44:28 -07002787 cmdStr = "onos:intents -p"
Jon Hall61282e32015-03-19 11:34:11 -07002788 if jsonFormat:
Jon Hallc6358dd2015-04-10 12:44:28 -07002789 cmdStr += " -j"
2790 output = self.sendline( cmdStr )
2791 return output
Jon Hall63604932015-02-26 17:09:50 -08002792 except TypeError:
2793 main.log.exception( self.name + ": Object not as expected" )
2794 return None
2795 except pexpect.EOF:
2796 main.log.error( self.name + ": EOF exception found" )
2797 main.log.error( self.name + ": " + self.handle.before )
2798 main.cleanup()
2799 main.exit()
Jon Hall77ba41c2015-04-06 10:25:40 -07002800 except Exception:
Jon Hall63604932015-02-26 17:09:50 -08002801 main.log.exception( self.name + ": Uncaught exception!" )
2802 main.cleanup()
2803 main.exit()
2804
Jon Hall61282e32015-03-19 11:34:11 -07002805 def partitions( self, jsonFormat=True ):
Jon Hall63604932015-02-26 17:09:50 -08002806 """
2807 Returns the output of the raft partitions command for ONOS.
2808 """
Jon Hall61282e32015-03-19 11:34:11 -07002809 # Sample JSON
2810 # {
2811 # "leader": "tcp://10.128.30.11:7238",
2812 # "members": [
2813 # "tcp://10.128.30.11:7238",
2814 # "tcp://10.128.30.17:7238",
2815 # "tcp://10.128.30.13:7238",
2816 # ],
2817 # "name": "p1",
2818 # "term": 3
2819 # },
Jon Hall63604932015-02-26 17:09:50 -08002820 try:
Jon Hallc6358dd2015-04-10 12:44:28 -07002821 cmdStr = "onos:partitions"
Jon Hall61282e32015-03-19 11:34:11 -07002822 if jsonFormat:
Jon Hallc6358dd2015-04-10 12:44:28 -07002823 cmdStr += " -j"
2824 output = self.sendline( cmdStr )
2825 return output
Jon Hall63604932015-02-26 17:09:50 -08002826 except TypeError:
2827 main.log.exception( self.name + ": Object not as expected" )
2828 return None
2829 except pexpect.EOF:
2830 main.log.error( self.name + ": EOF exception found" )
2831 main.log.error( self.name + ": " + self.handle.before )
2832 main.cleanup()
2833 main.exit()
Jon Hall77ba41c2015-04-06 10:25:40 -07002834 except Exception:
Jon Hall63604932015-02-26 17:09:50 -08002835 main.log.exception( self.name + ": Uncaught exception!" )
2836 main.cleanup()
2837 main.exit()
2838
Jon Hallbe379602015-03-24 13:39:32 -07002839 def apps( self, jsonFormat=True ):
2840 """
2841 Returns the output of the apps command for ONOS. This command lists
2842 information about installed ONOS applications
2843 """
2844 # Sample JSON object
2845 # [{"name":"org.onosproject.openflow","id":0,"version":"1.2.0",
2846 # "description":"ONOS OpenFlow protocol southbound providers",
2847 # "origin":"ON.Lab","permissions":"[]","featuresRepo":"",
2848 # "features":"[onos-openflow]","state":"ACTIVE"}]
2849 try:
Jon Hallc6358dd2015-04-10 12:44:28 -07002850 cmdStr = "onos:apps"
Jon Hallbe379602015-03-24 13:39:32 -07002851 if jsonFormat:
Jon Hallc6358dd2015-04-10 12:44:28 -07002852 cmdStr += " -j"
2853 output = self.sendline( cmdStr )
2854 assert "Error executing command" not in output
2855 return output
Jon Hallbe379602015-03-24 13:39:32 -07002856 # FIXME: look at specific exceptions/Errors
2857 except AssertionError:
2858 main.log.error( "Error in processing onos:app command: " +
2859 str( output ) )
2860 return None
2861 except TypeError:
2862 main.log.exception( self.name + ": Object not as expected" )
2863 return None
2864 except pexpect.EOF:
2865 main.log.error( self.name + ": EOF exception found" )
2866 main.log.error( self.name + ": " + self.handle.before )
2867 main.cleanup()
2868 main.exit()
Jon Hall77ba41c2015-04-06 10:25:40 -07002869 except Exception:
Jon Hallbe379602015-03-24 13:39:32 -07002870 main.log.exception( self.name + ": Uncaught exception!" )
2871 main.cleanup()
2872 main.exit()
2873
Jon Hall146f1522015-03-24 15:33:24 -07002874 def appStatus( self, appName ):
2875 """
2876 Uses the onos:apps cli command to return the status of an application.
2877 Returns:
2878 "ACTIVE" - If app is installed and activated
2879 "INSTALLED" - If app is installed and deactivated
2880 "UNINSTALLED" - If app is not installed
2881 None - on error
2882 """
Jon Hall146f1522015-03-24 15:33:24 -07002883 try:
2884 if not isinstance( appName, types.StringType ):
2885 main.log.error( self.name + ".appStatus(): appName must be" +
2886 " a string" )
2887 return None
2888 output = self.apps( jsonFormat=True )
2889 appsJson = json.loads( output )
2890 state = None
2891 for app in appsJson:
2892 if appName == app.get('name'):
2893 state = app.get('state')
2894 break
2895 if state == "ACTIVE" or state == "INSTALLED":
2896 return state
2897 elif state is None:
2898 return "UNINSTALLED"
2899 elif state:
2900 main.log.error( "Unexpected state from 'onos:apps': " +
2901 str( state ) )
2902 return state
2903 except TypeError:
2904 main.log.exception( self.name + ": Object not as expected" )
2905 return None
2906 except pexpect.EOF:
2907 main.log.error( self.name + ": EOF exception found" )
2908 main.log.error( self.name + ": " + self.handle.before )
2909 main.cleanup()
2910 main.exit()
Jon Hall77ba41c2015-04-06 10:25:40 -07002911 except Exception:
Jon Hall146f1522015-03-24 15:33:24 -07002912 main.log.exception( self.name + ": Uncaught exception!" )
2913 main.cleanup()
2914 main.exit()
2915
Jon Hallbe379602015-03-24 13:39:32 -07002916 def app( self, appName, option ):
2917 """
2918 Interacts with the app command for ONOS. This command manages
2919 application inventory.
2920 """
Jon Hallbe379602015-03-24 13:39:32 -07002921 try:
Jon Hallbd16b922015-03-26 17:53:15 -07002922 # Validate argument types
2923 valid = True
2924 if not isinstance( appName, types.StringType ):
2925 main.log.error( self.name + ".app(): appName must be a " +
2926 "string" )
2927 valid = False
2928 if not isinstance( option, types.StringType ):
2929 main.log.error( self.name + ".app(): option must be a string" )
2930 valid = False
2931 if not valid:
2932 return main.FALSE
2933 # Validate Option
2934 option = option.lower()
2935 # NOTE: Install may become a valid option
2936 if option == "activate":
2937 pass
2938 elif option == "deactivate":
2939 pass
2940 elif option == "uninstall":
2941 pass
2942 else:
2943 # Invalid option
2944 main.log.error( "The ONOS app command argument only takes " +
2945 "the values: (activate|deactivate|uninstall)" +
2946 "; was given '" + option + "'")
2947 return main.FALSE
Jon Hall146f1522015-03-24 15:33:24 -07002948 cmdStr = "onos:app " + option + " " + appName
Jon Hallbe379602015-03-24 13:39:32 -07002949 output = self.sendline( cmdStr )
Jon Hallbe379602015-03-24 13:39:32 -07002950 if "Error executing command" in output:
2951 main.log.error( "Error in processing onos:app command: " +
2952 str( output ) )
Jon Hall146f1522015-03-24 15:33:24 -07002953 return main.FALSE
Jon Hallbe379602015-03-24 13:39:32 -07002954 elif "No such application" in output:
2955 main.log.error( "The application '" + appName +
2956 "' is not installed in ONOS" )
Jon Hall146f1522015-03-24 15:33:24 -07002957 return main.FALSE
2958 elif "Command not found:" in output:
2959 main.log.error( "Error in processing onos:app command: " +
2960 str( output ) )
2961 return main.FALSE
Jon Hallbd16b922015-03-26 17:53:15 -07002962 elif "Unsupported command:" in output:
2963 main.log.error( "Incorrect command given to 'app': " +
2964 str( output ) )
Jon Hallbe379602015-03-24 13:39:32 -07002965 # NOTE: we may need to add more checks here
Jon Hallbd16b922015-03-26 17:53:15 -07002966 # else: Command was successful
Jon Hall08f61bc2015-04-13 16:00:30 -07002967 # main.log.debug( "app response: " + repr( output ) )
Jon Hallbe379602015-03-24 13:39:32 -07002968 return main.TRUE
2969 except TypeError:
2970 main.log.exception( self.name + ": Object not as expected" )
2971 return main.ERROR
2972 except pexpect.EOF:
2973 main.log.error( self.name + ": EOF exception found" )
2974 main.log.error( self.name + ": " + self.handle.before )
2975 main.cleanup()
2976 main.exit()
Jon Hall77ba41c2015-04-06 10:25:40 -07002977 except Exception:
Jon Hallbe379602015-03-24 13:39:32 -07002978 main.log.exception( self.name + ": Uncaught exception!" )
2979 main.cleanup()
2980 main.exit()
Jon Hall146f1522015-03-24 15:33:24 -07002981
Jon Hallbd16b922015-03-26 17:53:15 -07002982 def activateApp( self, appName, check=True ):
Jon Hall146f1522015-03-24 15:33:24 -07002983 """
2984 Activate an app that is already installed in ONOS
Jon Hallbd16b922015-03-26 17:53:15 -07002985 appName is the hierarchical app name, not the feature name
2986 If check is True, method will check the status of the app after the
2987 command is issued
Jon Hall146f1522015-03-24 15:33:24 -07002988 Returns main.TRUE if the command was successfully sent
2989 main.FALSE if the cli responded with an error or given
2990 incorrect input
2991 """
2992 try:
2993 if not isinstance( appName, types.StringType ):
2994 main.log.error( self.name + ".activateApp(): appName must be" +
2995 " a string" )
2996 return main.FALSE
2997 status = self.appStatus( appName )
2998 if status == "INSTALLED":
2999 response = self.app( appName, "activate" )
Jon Hallbd16b922015-03-26 17:53:15 -07003000 if check and response == main.TRUE:
3001 for i in range(10): # try 10 times then give up
3002 # TODO: Check with Thomas about this delay
3003 status = self.appStatus( appName )
3004 if status == "ACTIVE":
3005 return main.TRUE
3006 else:
Jon Hall050e1bd2015-03-30 13:33:02 -07003007 main.log.debug( "The state of application " +
3008 appName + " is " + status )
Jon Hallbd16b922015-03-26 17:53:15 -07003009 time.sleep( 1 )
3010 return main.FALSE
3011 else: # not 'check' or command didn't succeed
3012 return response
Jon Hall146f1522015-03-24 15:33:24 -07003013 elif status == "ACTIVE":
3014 return main.TRUE
3015 elif status == "UNINSTALLED":
3016 main.log.error( self.name + ": Tried to activate the " +
3017 "application '" + appName + "' which is not " +
3018 "installed." )
3019 else:
3020 main.log.error( "Unexpected return value from appStatus: " +
3021 str( status ) )
3022 return main.ERROR
3023 except TypeError:
3024 main.log.exception( self.name + ": Object not as expected" )
3025 return main.ERROR
3026 except pexpect.EOF:
3027 main.log.error( self.name + ": EOF exception found" )
3028 main.log.error( self.name + ": " + self.handle.before )
3029 main.cleanup()
3030 main.exit()
Jon Hall77ba41c2015-04-06 10:25:40 -07003031 except Exception:
Jon Hall146f1522015-03-24 15:33:24 -07003032 main.log.exception( self.name + ": Uncaught exception!" )
3033 main.cleanup()
3034 main.exit()
3035
Jon Hallbd16b922015-03-26 17:53:15 -07003036 def deactivateApp( self, appName, check=True ):
Jon Hall146f1522015-03-24 15:33:24 -07003037 """
3038 Deactivate an app that is already activated in ONOS
Jon Hallbd16b922015-03-26 17:53:15 -07003039 appName is the hierarchical app name, not the feature name
3040 If check is True, method will check the status of the app after the
3041 command is issued
Jon Hall146f1522015-03-24 15:33:24 -07003042 Returns main.TRUE if the command was successfully sent
3043 main.FALSE if the cli responded with an error or given
3044 incorrect input
3045 """
3046 try:
3047 if not isinstance( appName, types.StringType ):
3048 main.log.error( self.name + ".deactivateApp(): appName must " +
3049 "be a string" )
3050 return main.FALSE
3051 status = self.appStatus( appName )
3052 if status == "INSTALLED":
3053 return main.TRUE
3054 elif status == "ACTIVE":
3055 response = self.app( appName, "deactivate" )
Jon Hallbd16b922015-03-26 17:53:15 -07003056 if check and response == main.TRUE:
3057 for i in range(10): # try 10 times then give up
3058 status = self.appStatus( appName )
3059 if status == "INSTALLED":
3060 return main.TRUE
3061 else:
3062 time.sleep( 1 )
3063 return main.FALSE
3064 else: # not check or command didn't succeed
3065 return response
Jon Hall146f1522015-03-24 15:33:24 -07003066 elif status == "UNINSTALLED":
3067 main.log.warn( self.name + ": Tried to deactivate the " +
3068 "application '" + appName + "' which is not " +
3069 "installed." )
3070 return main.TRUE
3071 else:
3072 main.log.error( "Unexpected return value from appStatus: " +
3073 str( status ) )
3074 return main.ERROR
3075 except TypeError:
3076 main.log.exception( self.name + ": Object not as expected" )
3077 return main.ERROR
3078 except pexpect.EOF:
3079 main.log.error( self.name + ": EOF exception found" )
3080 main.log.error( self.name + ": " + self.handle.before )
3081 main.cleanup()
3082 main.exit()
Jon Hall77ba41c2015-04-06 10:25:40 -07003083 except Exception:
Jon Hall146f1522015-03-24 15:33:24 -07003084 main.log.exception( self.name + ": Uncaught exception!" )
3085 main.cleanup()
3086 main.exit()
3087
Jon Hallbd16b922015-03-26 17:53:15 -07003088 def uninstallApp( self, appName, check=True ):
Jon Hall146f1522015-03-24 15:33:24 -07003089 """
3090 Uninstall an app that is already installed in ONOS
Jon Hallbd16b922015-03-26 17:53:15 -07003091 appName is the hierarchical app name, not the feature name
3092 If check is True, method will check the status of the app after the
3093 command is issued
Jon Hall146f1522015-03-24 15:33:24 -07003094 Returns main.TRUE if the command was successfully sent
3095 main.FALSE if the cli responded with an error or given
3096 incorrect input
3097 """
3098 # TODO: check with Thomas about the state machine for apps
3099 try:
3100 if not isinstance( appName, types.StringType ):
3101 main.log.error( self.name + ".uninstallApp(): appName must " +
3102 "be a string" )
3103 return main.FALSE
3104 status = self.appStatus( appName )
3105 if status == "INSTALLED":
3106 response = self.app( appName, "uninstall" )
Jon Hallbd16b922015-03-26 17:53:15 -07003107 if check and response == main.TRUE:
3108 for i in range(10): # try 10 times then give up
3109 status = self.appStatus( appName )
3110 if status == "UNINSTALLED":
3111 return main.TRUE
3112 else:
3113 time.sleep( 1 )
3114 return main.FALSE
3115 else: # not check or command didn't succeed
3116 return response
Jon Hall146f1522015-03-24 15:33:24 -07003117 elif status == "ACTIVE":
3118 main.log.warn( self.name + ": Tried to uninstall the " +
3119 "application '" + appName + "' which is " +
3120 "currently active." )
3121 response = self.app( appName, "uninstall" )
Jon Hallbd16b922015-03-26 17:53:15 -07003122 if check and response == main.TRUE:
3123 for i in range(10): # try 10 times then give up
3124 status = self.appStatus( appName )
3125 if status == "UNINSTALLED":
3126 return main.TRUE
3127 else:
3128 time.sleep( 1 )
3129 return main.FALSE
3130 else: # not check or command didn't succeed
3131 return response
Jon Hall146f1522015-03-24 15:33:24 -07003132 elif status == "UNINSTALLED":
3133 return main.TRUE
3134 else:
3135 main.log.error( "Unexpected return value from appStatus: " +
3136 str( status ) )
3137 return main.ERROR
3138 except TypeError:
3139 main.log.exception( self.name + ": Object not as expected" )
3140 return main.ERROR
3141 except pexpect.EOF:
3142 main.log.error( self.name + ": EOF exception found" )
3143 main.log.error( self.name + ": " + self.handle.before )
3144 main.cleanup()
3145 main.exit()
Jon Hall77ba41c2015-04-06 10:25:40 -07003146 except Exception:
Jon Hall146f1522015-03-24 15:33:24 -07003147 main.log.exception( self.name + ": Uncaught exception!" )
3148 main.cleanup()
3149 main.exit()
Jon Hallbd16b922015-03-26 17:53:15 -07003150
3151 def appIDs( self, jsonFormat=True ):
3152 """
3153 Show the mappings between app id and app names given by the 'app-ids'
3154 cli command
3155 """
3156 try:
3157 cmdStr = "app-ids"
3158 if jsonFormat:
3159 cmdStr += " -j"
Jon Hallc6358dd2015-04-10 12:44:28 -07003160 output = self.sendline( cmdStr )
3161 assert "Error executing command" not in output
3162 return output
Jon Hallbd16b922015-03-26 17:53:15 -07003163 except AssertionError:
3164 main.log.error( "Error in processing onos:app-ids command: " +
3165 str( output ) )
3166 return None
3167 except TypeError:
3168 main.log.exception( self.name + ": Object not as expected" )
3169 return None
3170 except pexpect.EOF:
3171 main.log.error( self.name + ": EOF exception found" )
3172 main.log.error( self.name + ": " + self.handle.before )
3173 main.cleanup()
3174 main.exit()
Jon Hall77ba41c2015-04-06 10:25:40 -07003175 except Exception:
Jon Hallbd16b922015-03-26 17:53:15 -07003176 main.log.exception( self.name + ": Uncaught exception!" )
3177 main.cleanup()
3178 main.exit()
3179
3180 def appToIDCheck( self ):
3181 """
3182 This method will check that each application's ID listed in 'apps' is
3183 the same as the ID listed in 'app-ids'. The check will also check that
3184 there are no duplicate IDs issued. Note that an app ID should be
3185 a globaly unique numerical identifier for app/app-like features. Once
3186 an ID is registered, the ID is never freed up so that if an app is
3187 reinstalled it will have the same ID.
3188
3189 Returns: main.TRUE if the check passes and
3190 main.FALSE if the check fails or
3191 main.ERROR if there is some error in processing the test
3192 """
3193 try:
Jon Hall390696c2015-05-05 17:13:41 -07003194 bail = False
3195 ids = self.appIDs( jsonFormat=True )
3196 if ids:
3197 ids = json.loads( ids )
3198 else:
3199 main.log.error( "app-ids returned nothing:" + repr( ids ) )
3200 bail = True
3201 apps = self.apps( jsonFormat=True )
3202 if apps:
3203 apps = json.loads( apps )
3204 else:
3205 main.log.error( "apps returned nothing:" + repr( apps ) )
3206 bail = True
3207 if bail:
3208 return main.FALSE
Jon Hallbd16b922015-03-26 17:53:15 -07003209 result = main.TRUE
3210 for app in apps:
3211 appID = app.get( 'id' )
3212 if appID is None:
3213 main.log.error( "Error parsing app: " + str( app ) )
3214 result = main.FALSE
3215 appName = app.get( 'name' )
3216 if appName is None:
3217 main.log.error( "Error parsing app: " + str( app ) )
3218 result = main.FALSE
3219 # get the entry in ids that has the same appID
Jon Hall390696c2015-05-05 17:13:41 -07003220 current = filter( lambda item: item[ 'id' ] == appID, ids )
Jon Hall050e1bd2015-03-30 13:33:02 -07003221 # main.log.debug( "Comparing " + str( app ) + " to " +
3222 # str( current ) )
Jon Hallbd16b922015-03-26 17:53:15 -07003223 if not current: # if ids doesn't have this id
3224 result = main.FALSE
3225 main.log.error( "'app-ids' does not have the ID for " +
3226 str( appName ) + " that apps does." )
3227 elif len( current ) > 1:
3228 # there is more than one app with this ID
3229 result = main.FALSE
3230 # We will log this later in the method
3231 elif not current[0][ 'name' ] == appName:
3232 currentName = current[0][ 'name' ]
3233 result = main.FALSE
3234 main.log.error( "'app-ids' has " + str( currentName ) +
3235 " registered under id:" + str( appID ) +
3236 " but 'apps' has " + str( appName ) )
3237 else:
3238 pass # id and name match!
3239 # now make sure that app-ids has no duplicates
3240 idsList = []
3241 namesList = []
3242 for item in ids:
3243 idsList.append( item[ 'id' ] )
3244 namesList.append( item[ 'name' ] )
3245 if len( idsList ) != len( set( idsList ) ) or\
3246 len( namesList ) != len( set( namesList ) ):
3247 main.log.error( "'app-ids' has some duplicate entries: \n"
3248 + json.dumps( ids,
3249 sort_keys=True,
3250 indent=4,
3251 separators=( ',', ': ' ) ) )
3252 result = main.FALSE
3253 return result
3254 except ( ValueError, TypeError ):
3255 main.log.exception( self.name + ": Object not as expected" )
3256 return main.ERROR
3257 except pexpect.EOF:
3258 main.log.error( self.name + ": EOF exception found" )
3259 main.log.error( self.name + ": " + self.handle.before )
3260 main.cleanup()
3261 main.exit()
Jon Hall77ba41c2015-04-06 10:25:40 -07003262 except Exception:
Jon Hallbd16b922015-03-26 17:53:15 -07003263 main.log.exception( self.name + ": Uncaught exception!" )
3264 main.cleanup()
3265 main.exit()
3266
Jon Hallfb760a02015-04-13 15:35:03 -07003267 def getCfg( self, component=None, propName=None, short=False,
3268 jsonFormat=True ):
3269 """
3270 Get configuration settings from onos cli
3271 Optional arguments:
3272 component - Optionally only list configurations for a specific
3273 component. If None, all components with configurations
3274 are displayed. Case Sensitive string.
3275 propName - If component is specified, propName option will show
3276 only this specific configuration from that component.
3277 Case Sensitive string.
3278 jsonFormat - Returns output as json. Note that this will override
3279 the short option
3280 short - Short, less verbose, version of configurations.
3281 This is overridden by the json option
3282 returns:
3283 Output from cli as a string or None on error
3284 """
3285 try:
3286 baseStr = "cfg"
3287 cmdStr = " get"
3288 componentStr = ""
3289 if component:
3290 componentStr += " " + component
3291 if propName:
3292 componentStr += " " + propName
3293 if jsonFormat:
3294 baseStr += " -j"
3295 elif short:
3296 baseStr += " -s"
3297 output = self.sendline( baseStr + cmdStr + componentStr )
3298 assert "Error executing command" not in output
3299 return output
3300 except AssertionError:
3301 main.log.error( "Error in processing 'cfg get' command: " +
3302 str( output ) )
3303 return None
3304 except TypeError:
3305 main.log.exception( self.name + ": Object not as expected" )
3306 return None
3307 except pexpect.EOF:
3308 main.log.error( self.name + ": EOF exception found" )
3309 main.log.error( self.name + ": " + self.handle.before )
3310 main.cleanup()
3311 main.exit()
3312 except Exception:
3313 main.log.exception( self.name + ": Uncaught exception!" )
3314 main.cleanup()
3315 main.exit()
3316
3317 def setCfg( self, component, propName, value=None, check=True ):
3318 """
3319 Set/Unset configuration settings from ONOS cli
Jon Hall390696c2015-05-05 17:13:41 -07003320 Required arguments:
Jon Hallfb760a02015-04-13 15:35:03 -07003321 component - The case sensitive name of the component whose
3322 property is to be set
3323 propName - The case sensitive name of the property to be set/unset
Jon Hall390696c2015-05-05 17:13:41 -07003324 Optional arguments:
Jon Hallfb760a02015-04-13 15:35:03 -07003325 value - The value to set the property to. If None, will unset the
3326 property and revert it to it's default value(if applicable)
3327 check - Boolean, Check whether the option was successfully set this
3328 only applies when a value is given.
3329 returns:
3330 main.TRUE on success or main.FALSE on failure. If check is False,
3331 will return main.TRUE unless there is an error
3332 """
3333 try:
3334 baseStr = "cfg"
3335 cmdStr = " set " + str( component ) + " " + str( propName )
3336 if value is not None:
3337 cmdStr += " " + str( value )
3338 output = self.sendline( baseStr + cmdStr )
3339 assert "Error executing command" not in output
3340 if value and check:
3341 results = self.getCfg( component=str( component ),
3342 propName=str( propName ),
3343 jsonFormat=True )
3344 # Check if current value is what we just set
3345 try:
3346 jsonOutput = json.loads( results )
3347 current = jsonOutput[ 'value' ]
3348 except ( ValueError, TypeError ):
3349 main.log.exception( "Error parsing cfg output" )
3350 main.log.error( "output:" + repr( results ) )
3351 return main.FALSE
3352 if current == str( value ):
3353 return main.TRUE
3354 return main.FALSE
3355 return main.TRUE
3356 except AssertionError:
3357 main.log.error( "Error in processing 'cfg set' command: " +
3358 str( output ) )
3359 return main.FALSE
3360 except TypeError:
3361 main.log.exception( self.name + ": Object not as expected" )
3362 return main.FALSE
3363 except pexpect.EOF:
3364 main.log.error( self.name + ": EOF exception found" )
3365 main.log.error( self.name + ": " + self.handle.before )
3366 main.cleanup()
3367 main.exit()
3368 except Exception:
3369 main.log.exception( self.name + ": Uncaught exception!" )
3370 main.cleanup()
3371 main.exit()
3372
Jon Hall390696c2015-05-05 17:13:41 -07003373 def setTestAdd( self, setName, values ):
3374 """
3375 CLI command to add elements to a distributed set.
3376 Arguments:
3377 setName - The name of the set to add to.
3378 values - The value(s) to add to the set, space seperated.
3379 Example usages:
3380 setTestAdd( "set1", "a b c" )
3381 setTestAdd( "set2", "1" )
3382 returns:
3383 main.TRUE on success OR
3384 main.FALSE if elements were already in the set OR
3385 main.ERROR on error
3386 """
3387 try:
3388 cmdStr = "set-test-add " + str( setName ) + " " + str( values )
3389 output = self.sendline( cmdStr )
Jon Hallfeff3082015-05-19 10:23:26 -07003390 try:
3391 # TODO: Maybe make this less hardcoded
3392 # ConsistentMap Exceptions
3393 assert "org.onosproject.store.service" not in output
3394 # Node not leader
3395 assert "java.lang.IllegalStateException" not in output
3396 except AssertionError:
Jon Halle1a3b752015-07-22 13:02:46 -07003397 main.log.error( "Error in processing '" + cmdStr + "' " +
Jon Hallfeff3082015-05-19 10:23:26 -07003398 "command: " + str( output ) )
3399 retryTime = 30 # Conservative time, given by Madan
3400 main.log.info( "Waiting " + str( retryTime ) +
3401 "seconds before retrying." )
3402 time.sleep( retryTime ) # Due to change in mastership
3403 output = self.sendline( cmdStr )
Jon Hall390696c2015-05-05 17:13:41 -07003404 assert "Error executing command" not in output
3405 positiveMatch = "\[(.*)\] was added to the set " + str( setName )
3406 negativeMatch = "\[(.*)\] was already in set " + str( setName )
3407 main.log.info( self.name + ": " + output )
3408 if re.search( positiveMatch, output):
3409 return main.TRUE
3410 elif re.search( negativeMatch, output):
3411 return main.FALSE
3412 else:
3413 main.log.error( self.name + ": setTestAdd did not" +
3414 " match expected output" )
Jon Hall390696c2015-05-05 17:13:41 -07003415 main.log.debug( self.name + " actual: " + repr( output ) )
3416 return main.ERROR
3417 except AssertionError:
Jon Halle1a3b752015-07-22 13:02:46 -07003418 main.log.error( "Error in processing '" + cmdStr + "' command: " +
Jon Hall390696c2015-05-05 17:13:41 -07003419 str( output ) )
3420 return main.ERROR
3421 except TypeError:
3422 main.log.exception( self.name + ": Object not as expected" )
3423 return main.ERROR
3424 except pexpect.EOF:
3425 main.log.error( self.name + ": EOF exception found" )
3426 main.log.error( self.name + ": " + self.handle.before )
3427 main.cleanup()
3428 main.exit()
3429 except Exception:
3430 main.log.exception( self.name + ": Uncaught exception!" )
3431 main.cleanup()
3432 main.exit()
3433
3434 def setTestRemove( self, setName, values, clear=False, retain=False ):
3435 """
3436 CLI command to remove elements from a distributed set.
3437 Required arguments:
3438 setName - The name of the set to remove from.
3439 values - The value(s) to remove from the set, space seperated.
3440 Optional arguments:
3441 clear - Clear all elements from the set
3442 retain - Retain only the given values. (intersection of the
3443 original set and the given set)
3444 returns:
3445 main.TRUE on success OR
3446 main.FALSE if the set was not changed OR
3447 main.ERROR on error
3448 """
3449 try:
3450 cmdStr = "set-test-remove "
3451 if clear:
3452 cmdStr += "-c " + str( setName )
3453 elif retain:
3454 cmdStr += "-r " + str( setName ) + " " + str( values )
3455 else:
3456 cmdStr += str( setName ) + " " + str( values )
3457 output = self.sendline( cmdStr )
Jon Hallfeff3082015-05-19 10:23:26 -07003458 try:
3459 # TODO: Maybe make this less hardcoded
3460 # ConsistentMap Exceptions
3461 assert "org.onosproject.store.service" not in output
3462 # Node not leader
3463 assert "java.lang.IllegalStateException" not in output
3464 except AssertionError:
Jon Halle1a3b752015-07-22 13:02:46 -07003465 main.log.error( "Error in processing '" + cmdStr + "' " +
Jon Hallfeff3082015-05-19 10:23:26 -07003466 "command: " + str( output ) )
3467 retryTime = 30 # Conservative time, given by Madan
3468 main.log.info( "Waiting " + str( retryTime ) +
3469 "seconds before retrying." )
3470 time.sleep( retryTime ) # Due to change in mastership
3471 output = self.sendline( cmdStr )
Jon Hall390696c2015-05-05 17:13:41 -07003472 assert "Error executing command" not in output
3473 main.log.info( self.name + ": " + output )
3474 if clear:
3475 pattern = "Set " + str( setName ) + " cleared"
3476 if re.search( pattern, output ):
3477 return main.TRUE
3478 elif retain:
3479 positivePattern = str( setName ) + " was pruned to contain " +\
3480 "only elements of set \[(.*)\]"
3481 negativePattern = str( setName ) + " was not changed by " +\
3482 "retaining only elements of the set " +\
3483 "\[(.*)\]"
3484 if re.search( positivePattern, output ):
3485 return main.TRUE
3486 elif re.search( negativePattern, output ):
3487 return main.FALSE
3488 else:
3489 positivePattern = "\[(.*)\] was removed from the set " +\
3490 str( setName )
3491 if ( len( values.split() ) == 1 ):
3492 negativePattern = "\[(.*)\] was not in set " +\
3493 str( setName )
3494 else:
3495 negativePattern = "No element of \[(.*)\] was in set " +\
3496 str( setName )
3497 if re.search( positivePattern, output ):
3498 return main.TRUE
3499 elif re.search( negativePattern, output ):
3500 return main.FALSE
3501 main.log.error( self.name + ": setTestRemove did not" +
3502 " match expected output" )
3503 main.log.debug( self.name + " expected: " + pattern )
3504 main.log.debug( self.name + " actual: " + repr( output ) )
3505 return main.ERROR
3506 except AssertionError:
Jon Halle1a3b752015-07-22 13:02:46 -07003507 main.log.error( "Error in processing '" + cmdStr + "' command: " +
Jon Hall390696c2015-05-05 17:13:41 -07003508 str( output ) )
3509 return main.ERROR
3510 except TypeError:
3511 main.log.exception( self.name + ": Object not as expected" )
3512 return main.ERROR
3513 except pexpect.EOF:
3514 main.log.error( self.name + ": EOF exception found" )
3515 main.log.error( self.name + ": " + self.handle.before )
3516 main.cleanup()
3517 main.exit()
3518 except Exception:
3519 main.log.exception( self.name + ": Uncaught exception!" )
3520 main.cleanup()
3521 main.exit()
3522
3523 def setTestGet( self, setName, values="" ):
3524 """
3525 CLI command to get the elements in a distributed set.
3526 Required arguments:
3527 setName - The name of the set to remove from.
3528 Optional arguments:
3529 values - The value(s) to check if in the set, space seperated.
3530 returns:
3531 main.ERROR on error OR
3532 A list of elements in the set if no optional arguments are
3533 supplied OR
3534 A tuple containing the list then:
3535 main.FALSE if the given values are not in the set OR
3536 main.TRUE if the given values are in the set OR
3537 """
3538 try:
3539 values = str( values ).strip()
3540 setName = str( setName ).strip()
3541 length = len( values.split() )
3542 containsCheck = None
3543 # Patterns to match
3544 setPattern = "\[(.*)\]"
3545 pattern = "Items in set " + setName + ":\n" + setPattern
3546 containsTrue = "Set " + setName + " contains the value " + values
3547 containsFalse = "Set " + setName + " did not contain the value " +\
3548 values
3549 containsAllTrue = "Set " + setName + " contains the the subset " +\
3550 setPattern
3551 containsAllFalse = "Set " + setName + " did not contain the the" +\
3552 " subset " + setPattern
3553
3554 cmdStr = "set-test-get "
3555 cmdStr += setName + " " + values
3556 output = self.sendline( cmdStr )
Jon Hallfeff3082015-05-19 10:23:26 -07003557 try:
3558 # TODO: Maybe make this less hardcoded
3559 # ConsistentMap Exceptions
3560 assert "org.onosproject.store.service" not in output
3561 # Node not leader
3562 assert "java.lang.IllegalStateException" not in output
3563 except AssertionError:
Jon Halle1a3b752015-07-22 13:02:46 -07003564 main.log.error( "Error in processing '" + cmdStr + "' " +
Jon Hallfeff3082015-05-19 10:23:26 -07003565 "command: " + str( output ) )
3566 retryTime = 30 # Conservative time, given by Madan
3567 main.log.info( "Waiting " + str( retryTime ) +
3568 "seconds before retrying." )
3569 time.sleep( retryTime ) # Due to change in mastership
3570 output = self.sendline( cmdStr )
Jon Hall390696c2015-05-05 17:13:41 -07003571 assert "Error executing command" not in output
3572 main.log.info( self.name + ": " + output )
3573
3574 if length == 0:
3575 match = re.search( pattern, output )
3576 else: # if given values
3577 if length == 1: # Contains output
3578 patternTrue = pattern + "\n" + containsTrue
3579 patternFalse = pattern + "\n" + containsFalse
3580 else: # ContainsAll output
3581 patternTrue = pattern + "\n" + containsAllTrue
3582 patternFalse = pattern + "\n" + containsAllFalse
3583 matchTrue = re.search( patternTrue, output )
3584 matchFalse = re.search( patternFalse, output )
3585 if matchTrue:
3586 containsCheck = main.TRUE
3587 match = matchTrue
3588 elif matchFalse:
3589 containsCheck = main.FALSE
3590 match = matchFalse
3591 else:
3592 main.log.error( self.name + " setTestGet did not match " +\
3593 "expected output" )
3594 main.log.debug( self.name + " expected: " + pattern )
3595 main.log.debug( self.name + " actual: " + repr( output ) )
3596 match = None
3597 if match:
3598 setMatch = match.group( 1 )
3599 if setMatch == '':
3600 setList = []
3601 else:
3602 setList = setMatch.split( ", " )
3603 if length > 0:
3604 return ( setList, containsCheck )
3605 else:
3606 return setList
3607 else: # no match
3608 main.log.error( self.name + ": setTestGet did not" +
3609 " match expected output" )
3610 main.log.debug( self.name + " expected: " + pattern )
3611 main.log.debug( self.name + " actual: " + repr( output ) )
3612 return main.ERROR
3613 except AssertionError:
Jon Halle1a3b752015-07-22 13:02:46 -07003614 main.log.error( "Error in processing '" + cmdStr + "' command: " +
Jon Hall390696c2015-05-05 17:13:41 -07003615 str( output ) )
3616 return main.ERROR
3617 except TypeError:
3618 main.log.exception( self.name + ": Object not as expected" )
3619 return main.ERROR
3620 except pexpect.EOF:
3621 main.log.error( self.name + ": EOF exception found" )
3622 main.log.error( self.name + ": " + self.handle.before )
3623 main.cleanup()
3624 main.exit()
3625 except Exception:
3626 main.log.exception( self.name + ": Uncaught exception!" )
3627 main.cleanup()
3628 main.exit()
3629
3630 def setTestSize( self, setName ):
3631 """
3632 CLI command to get the elements in a distributed set.
3633 Required arguments:
3634 setName - The name of the set to remove from.
3635 returns:
Jon Hallfeff3082015-05-19 10:23:26 -07003636 The integer value of the size returned or
Jon Hall390696c2015-05-05 17:13:41 -07003637 None on error
3638 """
3639 try:
3640 # TODO: Should this check against the number of elements returned
3641 # and then return true/false based on that?
3642 setName = str( setName ).strip()
3643 # Patterns to match
3644 setPattern = "\[(.*)\]"
3645 pattern = "There are (\d+) items in set " + setName + ":\n" +\
3646 setPattern
3647 cmdStr = "set-test-get -s "
3648 cmdStr += setName
3649 output = self.sendline( cmdStr )
Jon Hallfeff3082015-05-19 10:23:26 -07003650 try:
3651 # TODO: Maybe make this less hardcoded
3652 # ConsistentMap Exceptions
3653 assert "org.onosproject.store.service" not in output
3654 # Node not leader
3655 assert "java.lang.IllegalStateException" not in output
3656 except AssertionError:
Jon Halle1a3b752015-07-22 13:02:46 -07003657 main.log.error( "Error in processing '" + cmdStr + "' " +
Jon Hallfeff3082015-05-19 10:23:26 -07003658 "command: " + str( output ) )
3659 retryTime = 30 # Conservative time, given by Madan
3660 main.log.info( "Waiting " + str( retryTime ) +
3661 "seconds before retrying." )
3662 time.sleep( retryTime ) # Due to change in mastership
3663 output = self.sendline( cmdStr )
Jon Hall390696c2015-05-05 17:13:41 -07003664 assert "Error executing command" not in output
3665 main.log.info( self.name + ": " + output )
3666 match = re.search( pattern, output )
3667 if match:
3668 setSize = int( match.group( 1 ) )
3669 setMatch = match.group( 2 )
3670 if len( setMatch.split() ) == setSize:
3671 main.log.info( "The size returned by " + self.name +
3672 " matches the number of elements in " +
3673 "the returned set" )
3674 else:
3675 main.log.error( "The size returned by " + self.name +
3676 " does not match the number of " +
3677 "elements in the returned set." )
3678 return setSize
3679 else: # no match
3680 main.log.error( self.name + ": setTestGet did not" +
3681 " match expected output" )
3682 main.log.debug( self.name + " expected: " + pattern )
3683 main.log.debug( self.name + " actual: " + repr( output ) )
3684 return None
3685 except AssertionError:
Jon Halle1a3b752015-07-22 13:02:46 -07003686 main.log.error( "Error in processing '" + cmdStr + "' command: " +
Jon Hall390696c2015-05-05 17:13:41 -07003687 str( output ) )
acsmarsa4a4d1e2015-07-10 16:01:24 -07003688 return None
Jon Hall390696c2015-05-05 17:13:41 -07003689 except TypeError:
3690 main.log.exception( self.name + ": Object not as expected" )
3691 return None
3692 except pexpect.EOF:
3693 main.log.error( self.name + ": EOF exception found" )
3694 main.log.error( self.name + ": " + self.handle.before )
3695 main.cleanup()
3696 main.exit()
3697 except Exception:
3698 main.log.exception( self.name + ": Uncaught exception!" )
3699 main.cleanup()
3700 main.exit()
3701
Jon Hall80daded2015-05-27 16:07:00 -07003702 def counters( self, jsonFormat=True ):
Jon Hall390696c2015-05-05 17:13:41 -07003703 """
3704 Command to list the various counters in the system.
3705 returns:
Jon Hall80daded2015-05-27 16:07:00 -07003706 if jsonFormat, a string of the json object returned by the cli
3707 command
3708 if not jsonFormat, the normal string output of the cli command
Jon Hall390696c2015-05-05 17:13:41 -07003709 None on error
3710 """
Jon Hall390696c2015-05-05 17:13:41 -07003711 try:
3712 counters = {}
3713 cmdStr = "counters"
Jon Hall80daded2015-05-27 16:07:00 -07003714 if jsonFormat:
3715 cmdStr += " -j"
Jon Hall390696c2015-05-05 17:13:41 -07003716 output = self.sendline( cmdStr )
3717 assert "Error executing command" not in output
3718 main.log.info( self.name + ": " + output )
Jon Hall80daded2015-05-27 16:07:00 -07003719 return output
Jon Hall390696c2015-05-05 17:13:41 -07003720 except AssertionError:
3721 main.log.error( "Error in processing 'counters' command: " +
3722 str( output ) )
Jon Hall80daded2015-05-27 16:07:00 -07003723 return None
Jon Hall390696c2015-05-05 17:13:41 -07003724 except TypeError:
3725 main.log.exception( self.name + ": Object not as expected" )
Jon Hall80daded2015-05-27 16:07:00 -07003726 return None
Jon Hall390696c2015-05-05 17:13:41 -07003727 except pexpect.EOF:
3728 main.log.error( self.name + ": EOF exception found" )
3729 main.log.error( self.name + ": " + self.handle.before )
3730 main.cleanup()
3731 main.exit()
3732 except Exception:
3733 main.log.exception( self.name + ": Uncaught exception!" )
3734 main.cleanup()
3735 main.exit()
3736
Jon Halle1a3b752015-07-22 13:02:46 -07003737 def counterTestAddAndGet( self, counter, delta=1, inMemory=False ):
Jon Hall390696c2015-05-05 17:13:41 -07003738 """
Jon Halle1a3b752015-07-22 13:02:46 -07003739 CLI command to add a delta to then get a distributed counter.
Jon Hall390696c2015-05-05 17:13:41 -07003740 Required arguments:
3741 counter - The name of the counter to increment.
3742 Optional arguments:
Jon Halle1a3b752015-07-22 13:02:46 -07003743 delta - The long to add to the counter
Jon Hall390696c2015-05-05 17:13:41 -07003744 inMemory - use in memory map for the counter
3745 returns:
3746 integer value of the counter or
3747 None on Error
3748 """
3749 try:
3750 counter = str( counter )
Jon Halle1a3b752015-07-22 13:02:46 -07003751 delta = int( delta )
Jon Hall390696c2015-05-05 17:13:41 -07003752 cmdStr = "counter-test-increment "
3753 if inMemory:
3754 cmdStr += "-i "
3755 cmdStr += counter
Jon Halle1a3b752015-07-22 13:02:46 -07003756 if delta != 1:
3757 cmdStr += " " + str( delta )
Jon Hall390696c2015-05-05 17:13:41 -07003758 output = self.sendline( cmdStr )
Jon Hallfeff3082015-05-19 10:23:26 -07003759 try:
3760 # TODO: Maybe make this less hardcoded
3761 # ConsistentMap Exceptions
3762 assert "org.onosproject.store.service" not in output
3763 # Node not leader
3764 assert "java.lang.IllegalStateException" not in output
3765 except AssertionError:
Jon Halle1a3b752015-07-22 13:02:46 -07003766 main.log.error( "Error in processing '" + cmdStr + "' " +
Jon Hallfeff3082015-05-19 10:23:26 -07003767 "command: " + str( output ) )
3768 retryTime = 30 # Conservative time, given by Madan
3769 main.log.info( "Waiting " + str( retryTime ) +
3770 "seconds before retrying." )
3771 time.sleep( retryTime ) # Due to change in mastership
3772 output = self.sendline( cmdStr )
Jon Hall390696c2015-05-05 17:13:41 -07003773 assert "Error executing command" not in output
3774 main.log.info( self.name + ": " + output )
Jon Halle1a3b752015-07-22 13:02:46 -07003775 pattern = counter + " was updated to (-?\d+)"
Jon Hall390696c2015-05-05 17:13:41 -07003776 match = re.search( pattern, output )
3777 if match:
3778 return int( match.group( 1 ) )
3779 else:
Jon Halle1a3b752015-07-22 13:02:46 -07003780 main.log.error( self.name + ": counterTestAddAndGet did not" +
Jon Hall390696c2015-05-05 17:13:41 -07003781 " match expected output." )
3782 main.log.debug( self.name + " expected: " + pattern )
3783 main.log.debug( self.name + " actual: " + repr( output ) )
3784 return None
3785 except AssertionError:
Jon Halle1a3b752015-07-22 13:02:46 -07003786 main.log.error( "Error in processing '" + cmdStr + "'" +
Jon Hall390696c2015-05-05 17:13:41 -07003787 " command: " + str( output ) )
3788 return None
3789 except TypeError:
3790 main.log.exception( self.name + ": Object not as expected" )
3791 return None
3792 except pexpect.EOF:
3793 main.log.error( self.name + ": EOF exception found" )
3794 main.log.error( self.name + ": " + self.handle.before )
3795 main.cleanup()
3796 main.exit()
3797 except Exception:
3798 main.log.exception( self.name + ": Uncaught exception!" )
3799 main.cleanup()
3800 main.exit()
3801
Jon Halle1a3b752015-07-22 13:02:46 -07003802 def counterTestGetAndAdd( self, counter, delta=1, inMemory=False ):
3803 """
3804 CLI command to get a distributed counter then add a delta to it.
3805 Required arguments:
3806 counter - The name of the counter to increment.
3807 Optional arguments:
3808 delta - The long to add to the counter
3809 inMemory - use in memory map for the counter
3810 returns:
3811 integer value of the counter or
3812 None on Error
3813 """
3814 try:
3815 counter = str( counter )
3816 delta = int( delta )
3817 cmdStr = "counter-test-increment -g "
3818 if inMemory:
3819 cmdStr += "-i "
3820 cmdStr += counter
3821 if delta != 1:
3822 cmdStr += " " + str( delta )
3823 output = self.sendline( cmdStr )
3824 try:
3825 # TODO: Maybe make this less hardcoded
3826 # ConsistentMap Exceptions
3827 assert "org.onosproject.store.service" not in output
3828 # Node not leader
3829 assert "java.lang.IllegalStateException" not in output
3830 except AssertionError:
3831 main.log.error( "Error in processing '" + cmdStr + "' " +
3832 "command: " + str( output ) )
3833 retryTime = 30 # Conservative time, given by Madan
3834 main.log.info( "Waiting " + str( retryTime ) +
3835 "seconds before retrying." )
3836 time.sleep( retryTime ) # Due to change in mastership
3837 output = self.sendline( cmdStr )
3838 assert "Error executing command" not in output
3839 main.log.info( self.name + ": " + output )
3840 pattern = counter + " was updated to (-?\d+)"
3841 match = re.search( pattern, output )
3842 if match:
3843 return int( match.group( 1 ) )
3844 else:
3845 main.log.error( self.name + ": counterTestGetAndAdd did not" +
3846 " match expected output." )
3847 main.log.debug( self.name + " expected: " + pattern )
3848 main.log.debug( self.name + " actual: " + repr( output ) )
3849 return None
3850 except AssertionError:
3851 main.log.error( "Error in processing '" + cmdStr + "'" +
3852 " command: " + str( output ) )
3853 return None
3854 except TypeError:
3855 main.log.exception( self.name + ": Object not as expected" )
3856 return None
3857 except pexpect.EOF:
3858 main.log.error( self.name + ": EOF exception found" )
3859 main.log.error( self.name + ": " + self.handle.before )
3860 main.cleanup()
3861 main.exit()
3862 except Exception:
3863 main.log.exception( self.name + ": Uncaught exception!" )
3864 main.cleanup()
3865 main.exit()
3866
kelvin-onlaba297c4d2015-06-01 13:53:55 -07003867 def summary( self, jsonFormat=True ):
3868 """
3869 Description: Execute summary command in onos
3870 Returns: json object ( summary -j ), returns main.FALSE if there is
3871 no output
3872
3873 """
3874 try:
3875 cmdStr = "summary"
3876 if jsonFormat:
3877 cmdStr += " -j"
3878 handle = self.sendline( cmdStr )
3879
3880 if re.search( "Error:", handle ):
3881 main.log.error( self.name + ": summary() response: " +
3882 str( handle ) )
3883 if not handle:
3884 main.log.error( self.name + ": There is no output in " +
3885 "summary command" )
3886 return main.FALSE
3887 return handle
3888 except TypeError:
3889 main.log.exception( self.name + ": Object not as expected" )
3890 return None
3891 except pexpect.EOF:
3892 main.log.error( self.name + ": EOF exception found" )
3893 main.log.error( self.name + ": " + self.handle.before )
3894 main.cleanup()
3895 main.exit()
3896 except Exception:
3897 main.log.exception( self.name + ": Uncaught exception!" )
3898 main.cleanup()
3899 main.exit()
Jon Hall2a5002c2015-08-21 16:49:11 -07003900
3901 def transactionalMapGet( self, keyName, inMemory=False ):
3902 """
3903 CLI command to get the value of a key in a consistent map using
3904 transactions. This a test function and can only get keys from the
3905 test map hard coded into the cli command
3906 Required arguments:
3907 keyName - The name of the key to get
3908 Optional arguments:
3909 inMemory - use in memory map for the counter
3910 returns:
3911 The string value of the key or
3912 None on Error
3913 """
3914 try:
3915 keyName = str( keyName )
3916 cmdStr = "transactional-map-test-get "
3917 if inMemory:
3918 cmdStr += "-i "
3919 cmdStr += keyName
3920 output = self.sendline( cmdStr )
3921 try:
3922 # TODO: Maybe make this less hardcoded
3923 # ConsistentMap Exceptions
3924 assert "org.onosproject.store.service" not in output
3925 # Node not leader
3926 assert "java.lang.IllegalStateException" not in output
3927 except AssertionError:
3928 main.log.error( "Error in processing '" + cmdStr + "' " +
3929 "command: " + str( output ) )
3930 return None
3931 pattern = "Key-value pair \(" + keyName + ", (?P<value>.+)\) found."
3932 if "Key " + keyName + " not found." in output:
3933 return None
3934 else:
3935 match = re.search( pattern, output )
3936 if match:
3937 return match.groupdict()[ 'value' ]
3938 else:
3939 main.log.error( self.name + ": transactionlMapGet did not" +
3940 " match expected output." )
3941 main.log.debug( self.name + " expected: " + pattern )
3942 main.log.debug( self.name + " actual: " + repr( output ) )
3943 return None
3944 except TypeError:
3945 main.log.exception( self.name + ": Object not as expected" )
3946 return None
3947 except pexpect.EOF:
3948 main.log.error( self.name + ": EOF exception found" )
3949 main.log.error( self.name + ": " + self.handle.before )
3950 main.cleanup()
3951 main.exit()
3952 except Exception:
3953 main.log.exception( self.name + ": Uncaught exception!" )
3954 main.cleanup()
3955 main.exit()
3956
3957 def transactionalMapPut( self, numKeys, value, inMemory=False ):
3958 """
3959 CLI command to put a value into 'numKeys' number of keys in a
3960 consistent map using transactions. This a test function and can only
3961 put into keys named 'Key#' of the test map hard coded into the cli command
3962 Required arguments:
3963 numKeys - Number of keys to add the value to
3964 value - The string value to put into the keys
3965 Optional arguments:
3966 inMemory - use in memory map for the counter
3967 returns:
3968 A dictionary whose keys are the name of the keys put into the map
3969 and the values of the keys are dictionaries whose key-values are
3970 'value': value put into map and optionaly
3971 'oldValue': Previous value in the key or
3972 None on Error
3973
3974 Example output
3975 { 'Key1': {'oldValue': 'oldTestValue', 'value': 'Testing'},
3976 'Key2': {'value': 'Testing'} }
3977 """
3978 try:
3979 numKeys = str( numKeys )
3980 value = str( value )
3981 cmdStr = "transactional-map-test-put "
3982 if inMemory:
3983 cmdStr += "-i "
3984 cmdStr += numKeys + " " + value
3985 output = self.sendline( cmdStr )
3986 try:
3987 # TODO: Maybe make this less hardcoded
3988 # ConsistentMap Exceptions
3989 assert "org.onosproject.store.service" not in output
3990 # Node not leader
3991 assert "java.lang.IllegalStateException" not in output
3992 except AssertionError:
3993 main.log.error( "Error in processing '" + cmdStr + "' " +
3994 "command: " + str( output ) )
3995 return None
3996 newPattern = 'Created Key (?P<key>(\w)+) with value (?P<value>(.)+)\.'
3997 updatedPattern = "Put (?P<value>(.)+) into key (?P<key>(\w)+)\. The old value was (?P<oldValue>(.)+)\."
3998 results = {}
3999 for line in output.splitlines():
4000 new = re.search( newPattern, line )
4001 updated = re.search( updatedPattern, line )
4002 if new:
4003 results[ new.groupdict()[ 'key' ] ] = { 'value': new.groupdict()[ 'value' ] }
4004 elif updated:
4005 results[ updated.groupdict()[ 'key' ] ] = { 'value': updated.groupdict()[ 'value' ],
4006 'oldValue': updated.groupdict()[ 'oldValue' ] }
4007 else:
4008 main.log.error( self.name + ": transactionlMapGet did not" +
4009 " match expected output." )
4010 main.log.debug( self.name + " expected: " + pattern )
4011 main.log.debug( self.name + " actual: " + repr( output ) )
4012 return results
4013 except TypeError:
4014 main.log.exception( self.name + ": Object not as expected" )
4015 return None
4016 except pexpect.EOF:
4017 main.log.error( self.name + ": EOF exception found" )
4018 main.log.error( self.name + ": " + self.handle.before )
4019 main.cleanup()
4020 main.exit()
4021 except Exception:
4022 main.log.exception( self.name + ": Uncaught exception!" )
4023 main.cleanup()
4024 main.exit()
acsmarsdaea66c2015-09-03 11:44:06 -07004025 def maps( self, jsonFormat=True ):
4026 """
4027 Description: Returns result of onos:maps
4028 Optional:
4029 * jsonFormat: enable json formatting of output
4030 """
4031 try:
4032 cmdStr = "maps"
4033 if jsonFormat:
4034 cmdStr += " -j"
4035 handle = self.sendline( cmdStr )
4036 return handle
4037 except TypeError:
4038 main.log.exception( self.name + ": Object not as expected" )
4039 return None
4040 except pexpect.EOF:
4041 main.log.error( self.name + ": EOF exception found" )
4042 main.log.error( self.name + ": " + self.handle.before )
4043 main.cleanup()
4044 main.exit()
4045 except Exception:
4046 main.log.exception( self.name + ": Uncaught exception!" )
4047 main.cleanup()
4048 main.exit()
GlennRC050596c2015-11-18 17:06:41 -08004049
4050 def getSwController( self, uri, jsonFormat=True ):
4051 """
4052 Descrition: Gets the controller information from the device
4053 """
4054 try:
4055 cmd = "device-controllers "
4056 if jsonFormat:
4057 cmd += "-j "
4058 response = self.sendline( cmd + uri )
4059 return response
4060 except TypeError:
4061 main.log.exception( self.name + ": Object not as expected" )
4062 return None
4063 except pexpect.EOF:
4064 main.log.error( self.name + ": EOF exception found" )
4065 main.log.error( self.name + ": " + self.handle.before )
4066 main.cleanup()
4067 main.exit()
4068 except Exception:
4069 main.log.exception( self.name + ": Uncaught exception!" )
4070 main.cleanup()
4071 main.exit()
4072
4073 def setSwController( self, uri, ip, proto="tcp", port="6653", jsonFormat=True ):
4074 """
4075 Descrition: sets the controller(s) for the specified device
4076
4077 Parameters:
4078 Required: uri - String: The uri of the device(switch).
4079 ip - String or List: The ip address of the controller.
4080 This parameter can be formed in a couple of different ways.
4081 VALID:
4082 10.0.0.1 - just the ip address
4083 tcp:10.0.0.1 - the protocol and the ip address
4084 tcp:10.0.0.1:6653 - the protocol and port can be specified,
4085 so that you can add controllers with different
4086 protocols and ports
4087 INVALID:
4088 10.0.0.1:6653 - this is not supported by ONOS
4089
4090 Optional: proto - The type of connection e.g. tcp, ssl. If a list of ips are given
4091 port - The port number.
4092 jsonFormat - If set ONOS will output in json NOTE: This is currently not supported
4093
4094 Returns: main.TRUE if ONOS returns without any errors, otherwise returns main.FALSE
4095 """
4096 try:
4097 cmd = "device-setcontrollers"
4098
4099 if jsonFormat:
4100 cmd += " -j"
4101 cmd += " " + uri
4102 if isinstance( ip, str ):
4103 ip = [ip]
4104 for item in ip:
4105 if ":" in item:
4106 sitem = item.split( ":" )
4107 if len(sitem) == 3:
4108 cmd += " " + item
4109 elif "." in sitem[1]:
4110 cmd += " {}:{}".format(item, port)
4111 else:
4112 main.log.error( "Malformed entry: " + item )
4113 raise TypeError
4114 else:
4115 cmd += " {}:{}:{}".format( proto, item, port )
4116
4117 response = self.sendline( cmd )
4118
4119 if "Error" in response:
4120 main.log.error( response )
4121 return main.FALSE
4122
GlennRC050596c2015-11-18 17:06:41 -08004123 return main.TRUE
4124
4125 except TypeError:
4126 main.log.exception( self.name + ": Object not as expected" )
4127 return main.FALSE
4128 except pexpect.EOF:
4129 main.log.error( self.name + ": EOF exception found" )
4130 main.log.error( self.name + ": " + self.handle.before )
4131 main.cleanup()
4132 main.exit()
4133 except Exception:
4134 main.log.exception( self.name + ": Uncaught exception!" )
4135 main.cleanup()
4136 main.exit()
GlennRC20fc6522015-12-23 23:26:57 -08004137
4138 def removeDevice( self, device ):
4139 '''
4140 Description:
4141 Remove a device from ONOS by passing the uri of the device(s).
4142 Parameters:
4143 device - (str or list) the id or uri of the device ex. "of:0000000000000001"
4144 Returns:
4145 Returns main.FALSE if an exception is thrown or an error is present
4146 in the response. Otherwise, returns main.TRUE.
4147 NOTE:
4148 If a host cannot be removed, then this function will return main.FALSE
4149 '''
4150 try:
4151 if type( device ) is str:
4152 device = list( device )
4153
4154 for d in device:
4155 time.sleep( 1 )
4156 response = self.sendline( "device-remove {}".format( d ) )
4157 if "Error" in response:
4158 main.log.warn( "Error for device: {}\nResponse: {}".format( d, response ) )
4159 return main.FALSE
4160
4161 return main.TRUE
4162
4163 except TypeError:
4164 main.log.exception( self.name + ": Object not as expected" )
4165 return main.FALSE
4166 except pexpect.EOF:
4167 main.log.error( self.name + ": EOF exception found" )
4168 main.log.error( self.name + ": " + self.handle.before )
4169 main.cleanup()
4170 main.exit()
4171 except Exception:
4172 main.log.exception( self.name + ": Uncaught exception!" )
4173 main.cleanup()
4174 main.exit()
4175
4176 def removeHost( self, host ):
4177 '''
4178 Description:
4179 Remove a host from ONOS by passing the id of the host(s)
4180 Parameters:
4181 hostId - (str or list) the id or mac of the host ex. "00:00:00:00:00:01"
4182 Returns:
4183 Returns main.FALSE if an exception is thrown or an error is present
4184 in the response. Otherwise, returns main.TRUE.
4185 NOTE:
4186 If a host cannot be removed, then this function will return main.FALSE
4187 '''
4188 try:
4189 if type( host ) is str:
4190 host = list( host )
4191
4192 for h in host:
4193 time.sleep( 1 )
4194 response = self.sendline( "host-remove {}".format( h ) )
4195 if "Error" in response:
4196 main.log.warn( "Error for host: {}\nResponse: {}".format( h, response ) )
4197 return main.FALSE
4198
4199 return main.TRUE
4200
4201 except TypeError:
4202 main.log.exception( self.name + ": Object not as expected" )
4203 return main.FALSE
4204 except pexpect.EOF:
4205 main.log.error( self.name + ": EOF exception found" )
4206 main.log.error( self.name + ": " + self.handle.before )
4207 main.cleanup()
4208 main.exit()
4209 except Exception:
4210 main.log.exception( self.name + ": Uncaught exception!" )
4211 main.cleanup()
4212 main.exit()