blob: c317fb05a2c64bf02249008e5ec6d476fa0a9368 [file] [log] [blame]
andrewonlab95ce8322014-10-13 14:12:04 -04001#!/usr/bin/env python
2
kelvin8ec71442015-01-15 16:57:00 -08003"""
Jeremy Ronquillob27ce4c2017-07-17 12:41:28 -07004OCT 13 2014
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00005Copyright 2014 Open Networking Foundation (ONF)
Jeremy Ronquillob27ce4c2017-07-17 12:41:28 -07006
7Please refer questions to either the onos test mailing list at <onos-test@onosproject.org>,
8the System Testing Plans and Results wiki page at <https://wiki.onosproject.org/x/voMg>,
9or the System Testing Guide page at <https://wiki.onosproject.org/x/WYQg>
10
11 TestON is free software: you can redistribute it and/or modify
12 it under the terms of the GNU General Public License as published by
13 the Free Software Foundation, either version 2 of the License, or
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +000014 (at your option) any later version.
Jeremy Ronquillob27ce4c2017-07-17 12:41:28 -070015
16 TestON is distributed in the hope that it will be useful,
17 but WITHOUT ANY WARRANTY; without even the implied warranty of
18 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 GNU General Public License for more details.
20
21 You should have received a copy of the GNU General Public License
22 along with TestON. If not, see <http://www.gnu.org/licenses/>.
23"""
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +000024
Jeremy Ronquillob27ce4c2017-07-17 12:41:28 -070025"""
andrewonlab95ce8322014-10-13 14:12:04 -040026This driver enters the onos> prompt to issue commands.
27
kelvin8ec71442015-01-15 16:57:00 -080028Please follow the coding style demonstrated by existing
andrewonlab95ce8322014-10-13 14:12:04 -040029functions and document properly.
30
31If you are a contributor to the driver, please
32list your email here for future contact:
33
34jhall@onlab.us
35andrew@onlab.us
Jon Halle8217482014-10-17 13:49:14 -040036shreya@onlab.us
Jeremy Ronquillo818bc7c2017-08-09 17:14:53 +000037jeremyr@opennetworking.org
kelvin8ec71442015-01-15 16:57:00 -080038"""
andrewonlab95ce8322014-10-13 14:12:04 -040039import pexpect
40import re
Jon Hall30b82fa2015-03-04 17:15:43 -080041import json
42import types
Jon Hallbd16b922015-03-26 17:53:15 -070043import time
kelvin-onlaba4074292015-07-09 15:19:49 -070044import os
andrewonlab95ce8322014-10-13 14:12:04 -040045from drivers.common.clidriver import CLI
You Wangdb8cd0a2016-05-26 15:19:45 -070046from core.graph import Graph
Shreya Chowdhary6fbb96c2017-05-02 16:20:19 -070047from cStringIO import StringIO
48from itertools import izip
andrewonlab95ce8322014-10-13 14:12:04 -040049
kelvin8ec71442015-01-15 16:57:00 -080050class OnosCliDriver( CLI ):
andrewonlab95ce8322014-10-13 14:12:04 -040051
kelvin8ec71442015-01-15 16:57:00 -080052 def __init__( self ):
53 """
54 Initialize client
55 """
Jon Hallefbd9792015-03-05 16:11:36 -080056 self.name = None
57 self.home = None
58 self.handle = None
Devin Limdc78e202017-06-09 18:30:07 -070059 self.karafUser = None
60 self.karafPass = None
You Wangdb8cd0a2016-05-26 15:19:45 -070061 self.graph = Graph()
Devin Limdc78e202017-06-09 18:30:07 -070062 super( OnosCliDriver, self ).__init__()
kelvin8ec71442015-01-15 16:57:00 -080063
Jeremy Ronquillo82705492017-10-18 14:19:55 -070064 def checkOptions( self, var, defaultVar ):
Devin Limdc78e202017-06-09 18:30:07 -070065 if var is None or var == "":
66 return defaultVar
67 return var
Jeremy Ronquillo82705492017-10-18 14:19:55 -070068
kelvin8ec71442015-01-15 16:57:00 -080069 def connect( self, **connectargs ):
70 """
andrewonlab95ce8322014-10-13 14:12:04 -040071 Creates ssh handle for ONOS cli.
kelvin8ec71442015-01-15 16:57:00 -080072 """
andrewonlab95ce8322014-10-13 14:12:04 -040073 try:
74 for key in connectargs:
kelvin8ec71442015-01-15 16:57:00 -080075 vars( self )[ key ] = connectargs[ key ]
Author Namee1c79982019-06-04 23:38:42 +010076 self.karafPrompt = self.user_name + "@root >"
andrew@onlab.us658ec012015-03-11 15:13:09 -070077 self.home = "~/onos"
andrewonlab95ce8322014-10-13 14:12:04 -040078 for key in self.options:
79 if key == "home":
Devin Limdc78e202017-06-09 18:30:07 -070080 self.home = self.options[ key ]
81 elif key == "karaf_username":
82 self.karafUser = self.options[ key ]
83 elif key == "karaf_password":
84 self.karafPass = self.options[ key ]
Jeremy Ronquillo82705492017-10-18 14:19:55 -070085 self.home = self.checkOptions( self.home, "~/onos" )
86 self.karafUser = self.checkOptions( self.karafUser, self.user_name )
87 self.karafPass = self.checkOptions( self.karafPass, self.pwd )
andrewonlab95ce8322014-10-13 14:12:04 -040088
kelvin-onlaba4074292015-07-09 15:19:49 -070089 for key in self.options:
90 if key == 'onosIp':
91 self.onosIp = self.options[ 'onosIp' ]
92 break
93
kelvin8ec71442015-01-15 16:57:00 -080094 self.name = self.options[ 'name' ]
kelvin-onlaba4074292015-07-09 15:19:49 -070095
96 try:
Jon Hallc6793552016-01-19 14:18:37 -080097 if os.getenv( str( self.ip_address ) ) is not None:
kelvin-onlaba4074292015-07-09 15:19:49 -070098 self.ip_address = os.getenv( str( self.ip_address ) )
99 else:
100 main.log.info( self.name +
101 ": Trying to connect to " +
102 self.ip_address )
103
104 except KeyError:
105 main.log.info( "Invalid host name," +
106 " connecting to local host instead" )
107 self.ip_address = 'localhost'
108 except Exception as inst:
109 main.log.error( "Uncaught exception: " + str( inst ) )
110
kelvin8ec71442015-01-15 16:57:00 -0800111 self.handle = super( OnosCliDriver, self ).connect(
kelvin-onlab08679eb2015-01-21 16:11:48 -0800112 user_name=self.user_name,
113 ip_address=self.ip_address,
kelvin-onlab898a6c62015-01-16 14:13:53 -0800114 port=self.port,
115 pwd=self.pwd,
116 home=self.home )
andrewonlab95ce8322014-10-13 14:12:04 -0400117
kelvin8ec71442015-01-15 16:57:00 -0800118 self.handle.sendline( "cd " + self.home )
Devin Limdc78e202017-06-09 18:30:07 -0700119 self.handle.expect( self.prompt )
andrewonlab95ce8322014-10-13 14:12:04 -0400120 if self.handle:
121 return self.handle
kelvin8ec71442015-01-15 16:57:00 -0800122 else:
123 main.log.info( "NO ONOS HANDLE" )
andrewonlab95ce8322014-10-13 14:12:04 -0400124 return main.FALSE
Jon Halld4d4b372015-01-28 16:02:41 -0800125 except TypeError:
126 main.log.exception( self.name + ": Object not as expected" )
127 return None
andrewonlab95ce8322014-10-13 14:12:04 -0400128 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -0800129 main.log.error( self.name + ": EOF exception found" )
130 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -0700131 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -0800132 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -0800133 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -0700134 main.cleanAndExit()
andrewonlab95ce8322014-10-13 14:12:04 -0400135
kelvin8ec71442015-01-15 16:57:00 -0800136 def disconnect( self ):
137 """
andrewonlab95ce8322014-10-13 14:12:04 -0400138 Called when Test is complete to disconnect the ONOS handle.
kelvin8ec71442015-01-15 16:57:00 -0800139 """
Jon Halld61331b2015-02-17 16:35:47 -0800140 response = main.TRUE
andrewonlab95ce8322014-10-13 14:12:04 -0400141 try:
Jon Hall61282e32015-03-19 11:34:11 -0700142 if self.handle:
143 i = self.logout()
144 if i == main.TRUE:
145 self.handle.sendline( "" )
Devin Limdc78e202017-06-09 18:30:07 -0700146 self.handle.expect( self.prompt )
Jon Hall61282e32015-03-19 11:34:11 -0700147 self.handle.sendline( "exit" )
148 self.handle.expect( "closed" )
Jon Halld4d4b372015-01-28 16:02:41 -0800149 except TypeError:
150 main.log.exception( self.name + ": Object not as expected" )
Jon Halld61331b2015-02-17 16:35:47 -0800151 response = main.FALSE
andrewonlab95ce8322014-10-13 14:12:04 -0400152 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -0800153 main.log.error( self.name + ": EOF exception found" )
154 main.log.error( self.name + ": " + self.handle.before )
Jon Hall61282e32015-03-19 11:34:11 -0700155 except ValueError:
Jon Hall1a77a1e2015-04-06 10:41:13 -0700156 main.log.exception( "Exception in disconnect of " + self.name )
Jon Hall61282e32015-03-19 11:34:11 -0700157 response = main.TRUE
Jon Hallfebb1c72015-03-05 13:30:09 -0800158 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -0800159 main.log.exception( self.name + ": Connection failed to the host" )
andrewonlab95ce8322014-10-13 14:12:04 -0400160 response = main.FALSE
161 return response
162
kelvin8ec71442015-01-15 16:57:00 -0800163 def logout( self ):
164 """
andrewonlab38d2b4a2014-11-13 16:28:47 -0500165 Sends 'logout' command to ONOS cli
Jon Hall61282e32015-03-19 11:34:11 -0700166 Returns main.TRUE if exited CLI and
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000167 main.FALSE on timeout (not guranteed you are disconnected)
Jon Hall61282e32015-03-19 11:34:11 -0700168 None on TypeError
169 Exits test on unknown error or pexpect exits unexpectedly
kelvin8ec71442015-01-15 16:57:00 -0800170 """
andrewonlab38d2b4a2014-11-13 16:28:47 -0500171 try:
Jon Hall61282e32015-03-19 11:34:11 -0700172 if self.handle:
173 self.handle.sendline( "" )
Jon Hall6c9e2da2018-11-06 12:01:23 -0800174 i = self.handle.expect( [ self.karafPrompt, self.prompt, pexpect.TIMEOUT ],
Jon Hall61282e32015-03-19 11:34:11 -0700175 timeout=10 )
176 if i == 0: # In ONOS CLI
177 self.handle.sendline( "logout" )
Devin Limdc78e202017-06-09 18:30:07 -0700178 j = self.handle.expect( [ self.prompt,
Jon Hallbfe00002016-04-05 10:23:54 -0700179 "Command not found:",
180 pexpect.TIMEOUT ] )
181 if j == 0: # Successfully logged out
182 return main.TRUE
183 elif j == 1 or j == 2:
184 # ONOS didn't fully load, and logout command isn't working
185 # or the command timed out
186 self.handle.send( "\x04" ) # send ctrl-d
Jon Hall64ab3bd2016-05-13 11:29:44 -0700187 try:
Devin Limdc78e202017-06-09 18:30:07 -0700188 self.handle.expect( self.prompt )
Jon Hall64ab3bd2016-05-13 11:29:44 -0700189 except pexpect.TIMEOUT:
190 main.log.error( "ONOS did not respond to 'logout' or CTRL-d" )
Jon Hallbfe00002016-04-05 10:23:54 -0700191 return main.TRUE
Jon Halle0f0b342017-04-18 11:43:47 -0700192 else: # some other output
Jon Hallbfe00002016-04-05 10:23:54 -0700193 main.log.warn( "Unknown repsonse to logout command: '{}'",
194 repr( self.handle.before ) )
195 return main.FALSE
Jon Hall61282e32015-03-19 11:34:11 -0700196 elif i == 1: # not in CLI
197 return main.TRUE
steven30801e42f1fb2019-01-17 11:31:45 +0800198 elif i == 2: # Timeout
Jon Hall61282e32015-03-19 11:34:11 -0700199 return main.FALSE
200 else:
andrewonlab9627f432014-11-14 12:45:10 -0500201 return main.TRUE
Jon Halld4d4b372015-01-28 16:02:41 -0800202 except TypeError:
203 main.log.exception( self.name + ": Object not as expected" )
204 return None
andrewonlab38d2b4a2014-11-13 16:28:47 -0500205 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -0800206 main.log.error( self.name + ": eof exception found" )
Jon Hall61282e32015-03-19 11:34:11 -0700207 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -0700208 main.cleanAndExit()
Jon Hall61282e32015-03-19 11:34:11 -0700209 except ValueError:
Jon Hall5aa168b2015-03-23 14:23:09 -0700210 main.log.error( self.name +
211 "ValueError exception in logout method" )
Jon Hallfebb1c72015-03-05 13:30:09 -0800212 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -0800213 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -0700214 main.cleanAndExit()
andrewonlab38d2b4a2014-11-13 16:28:47 -0500215
kelvin-onlabd3b64892015-01-20 13:26:24 -0800216 def setCell( self, cellname ):
kelvin8ec71442015-01-15 16:57:00 -0800217 """
andrewonlab95ce8322014-10-13 14:12:04 -0400218 Calls 'cell <name>' to set the environment variables on ONOSbench
kelvin8ec71442015-01-15 16:57:00 -0800219
andrewonlab95ce8322014-10-13 14:12:04 -0400220 Before issuing any cli commands, set the environment variable first.
kelvin8ec71442015-01-15 16:57:00 -0800221 """
andrewonlab95ce8322014-10-13 14:12:04 -0400222 try:
223 if not cellname:
kelvin8ec71442015-01-15 16:57:00 -0800224 main.log.error( "Must define cellname" )
Devin Lim44075962017-08-11 10:56:37 -0700225 main.cleanAndExit()
andrewonlab95ce8322014-10-13 14:12:04 -0400226 else:
kelvin8ec71442015-01-15 16:57:00 -0800227 self.handle.sendline( "cell " + str( cellname ) )
kelvin-onlabd3b64892015-01-20 13:26:24 -0800228 # Expect the cellname in the ONOSCELL variable.
kelvin8ec71442015-01-15 16:57:00 -0800229 # Note that this variable name is subject to change
andrewonlab95ce8322014-10-13 14:12:04 -0400230 # and that this driver will have to change accordingly
Jeremy Ronquillo82705492017-10-18 14:19:55 -0700231 self.handle.expect( str( cellname ) )
andrew@onlab.usc400b112015-01-21 15:33:19 -0800232 handleBefore = self.handle.before
233 handleAfter = self.handle.after
kelvin8ec71442015-01-15 16:57:00 -0800234 # Get the rest of the handle
Jeremy Ronquillo82705492017-10-18 14:19:55 -0700235 self.handle.sendline( "" )
236 self.handle.expect( self.prompt )
andrew@onlab.usc400b112015-01-21 15:33:19 -0800237 handleMore = self.handle.before
andrewonlab95ce8322014-10-13 14:12:04 -0400238
kelvin-onlabd3b64892015-01-20 13:26:24 -0800239 main.log.info( "Cell call returned: " + handleBefore +
240 handleAfter + handleMore )
andrewonlab95ce8322014-10-13 14:12:04 -0400241
242 return main.TRUE
243
Jon Halld4d4b372015-01-28 16:02:41 -0800244 except TypeError:
245 main.log.exception( self.name + ": Object not as expected" )
246 return None
andrewonlab95ce8322014-10-13 14:12:04 -0400247 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -0800248 main.log.error( self.name + ": eof exception found" )
249 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -0700250 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -0800251 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -0800252 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -0700253 main.cleanAndExit()
kelvin8ec71442015-01-15 16:57:00 -0800254
pingping-lin57a56ce2015-05-20 16:43:48 -0700255 def startOnosCli( self, ONOSIp, karafTimeout="",
Chiyu Chengef109502016-11-21 15:51:38 -0800256 commandlineTimeout=10, onosStartTimeout=60, waitForStart=False ):
kelvin8ec71442015-01-15 16:57:00 -0800257 """
Jon Hallefbd9792015-03-05 16:11:36 -0800258 karafTimeout is an optional argument. karafTimeout value passed
kelvin-onlabd3b64892015-01-20 13:26:24 -0800259 by user would be used to set the current karaf shell idle timeout.
260 Note that when ever this property is modified the shell will exit and
Hari Krishnad7b9c202015-01-05 10:38:14 -0800261 the subsequent login would reflect new idle timeout.
kelvin-onlabd3b64892015-01-20 13:26:24 -0800262 Below is an example to start a session with 60 seconds idle timeout
263 ( input value is in milliseconds ):
kelvin8ec71442015-01-15 16:57:00 -0800264
Hari Krishna25d42f72015-01-05 15:08:28 -0800265 tValue = "60000"
kelvin-onlabd3b64892015-01-20 13:26:24 -0800266 main.ONOScli1.startOnosCli( ONOSIp, karafTimeout=tValue )
kelvin8ec71442015-01-15 16:57:00 -0800267
kelvin-onlabd3b64892015-01-20 13:26:24 -0800268 Note: karafTimeout is left as str so that this could be read
269 and passed to startOnosCli from PARAMS file as str.
kelvin8ec71442015-01-15 16:57:00 -0800270 """
You Wangf69ab392016-01-26 16:34:38 -0800271 self.onosIp = ONOSIp
andrewonlab95ce8322014-10-13 14:12:04 -0400272 try:
Jon Hall67253832016-12-05 09:47:13 -0800273 # Check if we are already in the cli
kelvin8ec71442015-01-15 16:57:00 -0800274 self.handle.sendline( "" )
275 x = self.handle.expect( [
Jon Hall6c9e2da2018-11-06 12:01:23 -0800276 self.prompt, self.karafPrompt ], commandlineTimeout )
andrewonlab48829f62014-11-17 13:49:01 -0500277 if x == 1:
kelvin8ec71442015-01-15 16:57:00 -0800278 main.log.info( "ONOS cli is already running" )
andrewonlab48829f62014-11-17 13:49:01 -0500279 return main.TRUE
andrewonlab95ce8322014-10-13 14:12:04 -0400280
Jon Hall67253832016-12-05 09:47:13 -0800281 # Not in CLI so login
Chiyu Chengef109502016-11-21 15:51:38 -0800282 if waitForStart:
Jeremy Ronquilloec916a42018-02-02 13:05:57 -0800283 # Wait for onos start ( onos-wait-for-start ) and enter onos cli
284 startCliCommand = "onos-wait-for-start "
Chiyu Chengef109502016-11-21 15:51:38 -0800285 else:
286 startCliCommand = "onos "
287 self.handle.sendline( startCliCommand + str( ONOSIp ) )
kelvin8ec71442015-01-15 16:57:00 -0800288 i = self.handle.expect( [
Jon Hall6c9e2da2018-11-06 12:01:23 -0800289 self.karafPrompt,
pingping-lin57a56ce2015-05-20 16:43:48 -0700290 pexpect.TIMEOUT ], onosStartTimeout )
andrewonlab2a7ea9b2014-10-24 12:21:05 -0400291
292 if i == 0:
kelvin-onlabd3b64892015-01-20 13:26:24 -0800293 main.log.info( str( ONOSIp ) + " CLI Started successfully" )
Jon Hall6c9e2da2018-11-06 12:01:23 -0800294 if karafTimeout: # FIXME: This doesn't look right
kelvin8ec71442015-01-15 16:57:00 -0800295 self.handle.sendline(
Hari Krishnaac4e1782015-01-26 12:09:12 -0800296 "config:property-set -p org.apache.karaf.shell\
297 sshIdleTimeout " +
kelvin8ec71442015-01-15 16:57:00 -0800298 karafTimeout )
Devin Limdc78e202017-06-09 18:30:07 -0700299 self.handle.expect( self.prompt )
Chiyu Chengef109502016-11-21 15:51:38 -0800300 self.handle.sendline( startCliCommand + str( ONOSIp ) )
Jon Hall6c9e2da2018-11-06 12:01:23 -0800301 self.handle.expect( self.karafPrompt )
302 main.log.debug( self.handle.before )
andrewonlab2a7ea9b2014-10-24 12:21:05 -0400303 return main.TRUE
304 else:
kelvin8ec71442015-01-15 16:57:00 -0800305 # If failed, send ctrl+c to process and try again
306 main.log.info( "Starting CLI failed. Retrying..." )
307 self.handle.send( "\x03" )
Chiyu Chengef109502016-11-21 15:51:38 -0800308 self.handle.sendline( startCliCommand + str( ONOSIp ) )
Jon Hall6c9e2da2018-11-06 12:01:23 -0800309 i = self.handle.expect( [ self.karafPrompt, pexpect.TIMEOUT ],
kelvin8ec71442015-01-15 16:57:00 -0800310 timeout=30 )
andrewonlab3a7c3c72014-10-24 17:21:03 -0400311 if i == 0:
kelvin-onlabd3b64892015-01-20 13:26:24 -0800312 main.log.info( str( ONOSIp ) + " CLI Started " +
kelvin8ec71442015-01-15 16:57:00 -0800313 "successfully after retry attempt" )
Hari Krishnae36ef212015-01-04 14:09:13 -0800314 if karafTimeout:
kelvin8ec71442015-01-15 16:57:00 -0800315 self.handle.sendline(
kelvin-onlabd3b64892015-01-20 13:26:24 -0800316 "config:property-set -p org.apache.karaf.shell\
317 sshIdleTimeout " +
kelvin8ec71442015-01-15 16:57:00 -0800318 karafTimeout )
Devin Limdc78e202017-06-09 18:30:07 -0700319 self.handle.expect( self.prompt )
Chiyu Chengef109502016-11-21 15:51:38 -0800320 self.handle.sendline( startCliCommand + str( ONOSIp ) )
Jon Hall6c9e2da2018-11-06 12:01:23 -0800321 self.handle.expect( self.karafPrompt )
andrewonlab3a7c3c72014-10-24 17:21:03 -0400322 return main.TRUE
323 else:
kelvin8ec71442015-01-15 16:57:00 -0800324 main.log.error( "Connection to CLI " +
kelvin-onlabd3b64892015-01-20 13:26:24 -0800325 str( ONOSIp ) + " timeout" )
andrewonlab3a7c3c72014-10-24 17:21:03 -0400326 return main.FALSE
andrewonlab95ce8322014-10-13 14:12:04 -0400327
Jon Halld4d4b372015-01-28 16:02:41 -0800328 except TypeError:
329 main.log.exception( self.name + ": Object not as expected" )
330 return None
andrewonlab95ce8322014-10-13 14:12:04 -0400331 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -0800332 main.log.error( self.name + ": EOF exception found" )
333 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -0700334 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -0800335 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -0800336 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -0700337 main.cleanAndExit()
andrewonlab95ce8322014-10-13 14:12:04 -0400338
suibin zhang116647a2016-05-06 16:30:09 -0700339 def startCellCli( self, karafTimeout="",
340 commandlineTimeout=10, onosStartTimeout=60 ):
341 """
342 Start CLI on onos ecll handle.
343
344 karafTimeout is an optional argument. karafTimeout value passed
345 by user would be used to set the current karaf shell idle timeout.
346 Note that when ever this property is modified the shell will exit and
347 the subsequent login would reflect new idle timeout.
348 Below is an example to start a session with 60 seconds idle timeout
349 ( input value is in milliseconds ):
350
351 tValue = "60000"
352
353 Note: karafTimeout is left as str so that this could be read
354 and passed to startOnosCli from PARAMS file as str.
355 """
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000356
suibin zhang116647a2016-05-06 16:30:09 -0700357 try:
358 self.handle.sendline( "" )
359 x = self.handle.expect( [
Jon Hall6c9e2da2018-11-06 12:01:23 -0800360 self.prompt, self.karafPrompt ], commandlineTimeout )
suibin zhang116647a2016-05-06 16:30:09 -0700361
362 if x == 1:
363 main.log.info( "ONOS cli is already running" )
364 return main.TRUE
365
Jeremy Ronquilloec916a42018-02-02 13:05:57 -0800366 # Wait for onos start ( onos-wait-for-start ) and enter onos cli
suibin zhang116647a2016-05-06 16:30:09 -0700367 self.handle.sendline( "/opt/onos/bin/onos" )
368 i = self.handle.expect( [
Jon Hall6c9e2da2018-11-06 12:01:23 -0800369 self.karafPrompt,
suibin zhang116647a2016-05-06 16:30:09 -0700370 pexpect.TIMEOUT ], onosStartTimeout )
371
372 if i == 0:
373 main.log.info( self.name + " CLI Started successfully" )
Jon Hall6c9e2da2018-11-06 12:01:23 -0800374 if karafTimeout: # FIXME: This doesn't look right
suibin zhang116647a2016-05-06 16:30:09 -0700375 self.handle.sendline(
376 "config:property-set -p org.apache.karaf.shell\
377 sshIdleTimeout " +
378 karafTimeout )
Devin Limdc78e202017-06-09 18:30:07 -0700379 self.handle.expect( self.prompt )
suibin zhang116647a2016-05-06 16:30:09 -0700380 self.handle.sendline( "/opt/onos/bin/onos" )
Jon Hall6c9e2da2018-11-06 12:01:23 -0800381 self.handle.expect( self.karafPrompt )
382 main.log.debug( self.handle.before )
suibin zhang116647a2016-05-06 16:30:09 -0700383 return main.TRUE
384 else:
385 # If failed, send ctrl+c to process and try again
386 main.log.info( "Starting CLI failed. Retrying..." )
387 self.handle.send( "\x03" )
388 self.handle.sendline( "/opt/onos/bin/onos" )
Jon Hall6c9e2da2018-11-06 12:01:23 -0800389 i = self.handle.expect( [ self.karafPrompt, pexpect.TIMEOUT ],
suibin zhang116647a2016-05-06 16:30:09 -0700390 timeout=30 )
391 if i == 0:
392 main.log.info( self.name + " CLI Started " +
393 "successfully after retry attempt" )
394 if karafTimeout:
395 self.handle.sendline(
396 "config:property-set -p org.apache.karaf.shell\
397 sshIdleTimeout " +
398 karafTimeout )
Devin Limdc78e202017-06-09 18:30:07 -0700399 self.handle.expect( self.prompt )
suibin zhang116647a2016-05-06 16:30:09 -0700400 self.handle.sendline( "/opt/onos/bin/onos" )
Jon Hall6c9e2da2018-11-06 12:01:23 -0800401 self.handle.expect( self.karafPrompt )
suibin zhang116647a2016-05-06 16:30:09 -0700402 return main.TRUE
403 else:
404 main.log.error( "Connection to CLI " +
405 self.name + " timeout" )
406 return main.FALSE
407
408 except TypeError:
409 main.log.exception( self.name + ": Object not as expected" )
410 return None
411 except pexpect.EOF:
412 main.log.error( self.name + ": EOF exception found" )
413 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -0700414 main.cleanAndExit()
suibin zhang116647a2016-05-06 16:30:09 -0700415 except Exception:
416 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -0700417 main.cleanAndExit()
suibin zhang116647a2016-05-06 16:30:09 -0700418
Pratik Parab3b2ab5a2017-02-14 13:15:14 -0800419 def log( self, cmdStr, level="", noExit=False ):
kelvin-onlab9f541032015-02-04 16:19:53 -0800420 """
421 log the commands in the onos CLI.
kelvin-onlab338f5512015-02-06 10:53:16 -0800422 returns main.TRUE on success
Jon Hallefbd9792015-03-05 16:11:36 -0800423 returns main.FALSE if Error occurred
YPZhangebf9eb52016-05-12 15:20:24 -0700424 if noExit is True, TestON will not exit, but clean up
kelvin-onlab338f5512015-02-06 10:53:16 -0800425 Available level: DEBUG, TRACE, INFO, WARN, ERROR
426 Level defaults to INFO
Pratik Parab3b2ab5a2017-02-14 13:15:14 -0800427 if cmdStr has spaces then put quotes in the passed string
kelvin-onlab9f541032015-02-04 16:19:53 -0800428 """
429 try:
kelvin-onlab338f5512015-02-06 10:53:16 -0800430 lvlStr = ""
431 if level:
432 lvlStr = "--level=" + level
433
kelvin-onlab338f5512015-02-06 10:53:16 -0800434 self.handle.sendline( "log:log " + lvlStr + " " + cmdStr )
Jon Hall390696c2015-05-05 17:13:41 -0700435 self.handle.expect( "log:log" )
Jon Hall6c9e2da2018-11-06 12:01:23 -0800436 self.handle.expect( self.karafPrompt )
kelvin-onlabfb521662015-02-27 09:52:40 -0800437
kelvin-onlab9f541032015-02-04 16:19:53 -0800438 response = self.handle.before
439 if re.search( "Error", response ):
Jon Halldac3eae2020-06-05 12:04:06 -0700440 main.log.debug( response )
kelvin-onlab9f541032015-02-04 16:19:53 -0800441 return main.FALSE
442 return main.TRUE
Jon Hall80daded2015-05-27 16:07:00 -0700443 except pexpect.TIMEOUT:
444 main.log.exception( self.name + ": TIMEOUT exception found" )
Jon Hall43060f62020-06-23 13:13:33 -0700445 main.log.error( self.name + ": " + self.handle.before )
YPZhangebf9eb52016-05-12 15:20:24 -0700446 if noExit:
447 main.cleanup()
448 return None
449 else:
Devin Lim44075962017-08-11 10:56:37 -0700450 main.cleanAndExit()
kelvin-onlab9f541032015-02-04 16:19:53 -0800451 except pexpect.EOF:
452 main.log.error( self.name + ": EOF exception found" )
453 main.log.error( self.name + ": " + self.handle.before )
YPZhangebf9eb52016-05-12 15:20:24 -0700454 if noExit:
455 main.cleanup()
456 return None
457 else:
Devin Lim44075962017-08-11 10:56:37 -0700458 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -0800459 except Exception:
kelvin-onlabfb521662015-02-27 09:52:40 -0800460 main.log.exception( self.name + ": Uncaught exception!" )
YPZhangebf9eb52016-05-12 15:20:24 -0700461 if noExit:
462 main.cleanup()
463 return None
464 else:
Devin Lim44075962017-08-11 10:56:37 -0700465 main.cleanAndExit()
andrewonlab95ce8322014-10-13 14:12:04 -0400466
Jon Hall0e240372018-05-02 11:21:57 -0700467 def clearBuffer( self, debug=False, timeout=10, noExit=False ):
kelvin8ec71442015-01-15 16:57:00 -0800468 """
Jon Hall0e240372018-05-02 11:21:57 -0700469 Test cli connection and clear any left over output in the buffer
470 Optional Arguments:
471 debug - Defaults to False. If True, will enable debug logging.
472 timeout - Defaults to 10. Amount of time in seconds for a command to return
473 before a timeout.
474 noExit - Defaults to False. If True, will not exit TestON in the event of a
kelvin8ec71442015-01-15 16:57:00 -0800475 """
andrewonlaba18f6bf2014-10-13 19:31:54 -0400476 try:
Jon Halla495f562016-05-16 18:03:26 -0700477 # Try to reconnect if disconnected from cli
478 self.handle.sendline( "" )
Jon Hall6c9e2da2018-11-06 12:01:23 -0800479 i = self.handle.expect( [ self.karafPrompt, self.prompt, pexpect.TIMEOUT ] )
Jon Hall0e240372018-05-02 11:21:57 -0700480 response = self.handle.before
Jon Halla495f562016-05-16 18:03:26 -0700481 if i == 1:
Jeremy Ronquillo82705492017-10-18 14:19:55 -0700482 main.log.error( self.name + ": onos cli session closed. " )
Jon Halla495f562016-05-16 18:03:26 -0700483 if self.onosIp:
484 main.log.warn( "Trying to reconnect " + self.onosIp )
485 reconnectResult = self.startOnosCli( self.onosIp )
486 if reconnectResult:
487 main.log.info( self.name + ": onos cli session reconnected." )
488 else:
489 main.log.error( self.name + ": reconnection failed." )
YPZhang14a4aa92016-07-15 13:37:15 -0700490 if noExit:
491 return None
492 else:
Devin Lim44075962017-08-11 10:56:37 -0700493 main.cleanAndExit()
Jon Halla495f562016-05-16 18:03:26 -0700494 else:
Devin Lim44075962017-08-11 10:56:37 -0700495 main.cleanAndExit()
Jon Halla495f562016-05-16 18:03:26 -0700496 if i == 2:
Jon Hall7a6ebfd2017-03-13 10:58:58 -0700497 main.log.warn( "Timeout when testing cli responsiveness" )
498 main.log.debug( self.handle.before )
499 self.handle.send( "\x03" ) # Send ctrl-c to clear previous output
Jon Hall6c9e2da2018-11-06 12:01:23 -0800500 self.handle.expect( self.karafPrompt )
Jon Halla495f562016-05-16 18:03:26 -0700501
Jon Hall0e240372018-05-02 11:21:57 -0700502 response += self.handle.before
Jon Hall14a03b52016-05-11 12:07:30 -0700503 if debug:
Jon Hall0e240372018-05-02 11:21:57 -0700504 main.log.debug( self.name + ": Raw output from sending ''" )
505 main.log.debug( self.name + ": " + repr( response ) )
506 except pexpect.TIMEOUT:
507 main.log.error( self.name + ": ONOS timeout" )
508 main.log.debug( self.handle.before )
You Wang141b43b2018-06-26 16:50:18 -0700509 self.handle.send( "\x03" )
Jon Hall6c9e2da2018-11-06 12:01:23 -0800510 self.handle.expect( self.karafPrompt )
Jon Hall0e240372018-05-02 11:21:57 -0700511 return None
512 except pexpect.EOF:
513 main.log.error( self.name + ": EOF exception found" )
514 main.log.error( self.name + ": " + self.handle.before )
515 if noExit:
516 return None
517 else:
518 main.cleanAndExit()
519 except Exception:
520 main.log.exception( self.name + ": Uncaught exception!" )
521 if noExit:
522 return None
523 else:
524 main.cleanAndExit()
525
Jon Hall22e94ce2019-01-15 14:52:17 -0800526 def sendline( self, cmdStr, showResponse=False, debug=False, timeout=10, noExit=False, relaxedRegex=True, expectJson=False ):
Jon Hall0e240372018-05-02 11:21:57 -0700527 """
528 A wrapper around pexpect's sendline/expect. Will return all the output from a given command
529
530 Required Arguments:
531 cmdStr - String to send to the pexpect session
532
533 Optional Arguments:
534 showResponse - Defaults to False. If True will log the response.
535 debug - Defaults to False. If True, will enable debug logging.
536 timeout - Defaults to 10. Amount of time in seconds for a command to return
537 before a timeout.
538 noExit - Defaults to False. If True, will not exit TestON in the event of a
539 closed channel, but instead return None
Jon Hall6c9e2da2018-11-06 12:01:23 -0800540 relaxedRegex - Defaults to True. If there is a pipe in the command send, will only try to match the last part of the piped command.
Jon Hall0e240372018-05-02 11:21:57 -0700541
542 Warning: There are no sanity checking to commands sent using this method.
543
544 """
545 try:
546 # Try to reconnect if disconnected from cli
547 self.clearBuffer( debug=debug, timeout=timeout, noExit=noExit )
548 if debug:
549 # NOTE: This adds an average of .4 seconds per call
Jon Hall14a03b52016-05-11 12:07:30 -0700550 logStr = "\"Sending CLI command: '" + cmdStr + "'\""
Jon Halle0f0b342017-04-18 11:43:47 -0700551 self.log( logStr, noExit=noExit )
kelvin-onlabd3b64892015-01-20 13:26:24 -0800552 self.handle.sendline( cmdStr )
Jon Hall6c9e2da2018-11-06 12:01:23 -0800553 self.handle.expect( self.karafPrompt, timeout )
Jon Hall63604932015-02-26 17:09:50 -0800554 response = self.handle.before
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000555 main.log.info( "Command '" + str( cmdStr ) + "' sent to "
Jon Hallc6793552016-01-19 14:18:37 -0800556 + self.name + "." )
Jon Hallc6358dd2015-04-10 12:44:28 -0700557 if debug:
Jon Hall390696c2015-05-05 17:13:41 -0700558 main.log.debug( self.name + ": Raw output" )
559 main.log.debug( self.name + ": " + repr( response ) )
Jon Hallc6358dd2015-04-10 12:44:28 -0700560
Jon Hall6c9e2da2018-11-06 12:01:23 -0800561 # Remove control codes from karaf 4.2.1
Jon Hallcf31d0f2018-12-13 11:18:48 -0800562 karafEscape = re.compile( r"('(0|1)~\'|\r\r\r\n\x1b\[A\x1b\[79C(x|\s)?|\x1b(>|=)|\x1b\[90m~)" )
Jon Hall6c9e2da2018-11-06 12:01:23 -0800563 response = karafEscape.sub( '', response )
564 if debug:
565 main.log.debug( self.name + ": karafEscape output" )
566 main.log.debug( self.name + ": " + repr( response ) )
Jon Hallc6358dd2015-04-10 12:44:28 -0700567 # Remove ANSI color control strings from output
Jon Hall43060f62020-06-23 13:13:33 -0700568 response = self.cleanOutput( response, debug )
Jon Hallc6358dd2015-04-10 12:44:28 -0700569
Jon Hall6c9e2da2018-11-06 12:01:23 -0800570 # Remove ANSI color control strings from output
Jon Hallcf31d0f2018-12-13 11:18:48 -0800571 # NOTE: karaf is sometimes adding a single character then two
572 # backspaces and sometimes adding 2 characters with 2 backspaces??
Jon Hall6c9e2da2018-11-06 12:01:23 -0800573 backspaceEscape = re.compile( r'((..\x08\x08)|(.|\s)\x08)' )
574 response = backspaceEscape.sub( '', response )
575 if debug:
576 main.log.debug( self.name + ": backspaceEscape output" )
577 main.log.debug( self.name + ": " + repr( response ) )
578
kelvin-onlabfb521662015-02-27 09:52:40 -0800579 # Remove extra return chars that get added
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000580 response = re.sub( r"\s\r", "", response )
Jon Hallc6358dd2015-04-10 12:44:28 -0700581 if debug:
Jon Hall390696c2015-05-05 17:13:41 -0700582 main.log.debug( self.name + ": Removed extra returns " +
583 "from output" )
584 main.log.debug( self.name + ": " + repr( response ) )
Jon Hallc6358dd2015-04-10 12:44:28 -0700585
586 # Strip excess whitespace
Jon Hall63604932015-02-26 17:09:50 -0800587 response = response.strip()
Jon Hallc6358dd2015-04-10 12:44:28 -0700588 if debug:
Jon Hall390696c2015-05-05 17:13:41 -0700589 main.log.debug( self.name + ": parsed and stripped output" )
590 main.log.debug( self.name + ": " + repr( response ) )
Jon Hallc6358dd2015-04-10 12:44:28 -0700591
Jon Hall63604932015-02-26 17:09:50 -0800592 # parse for just the output, remove the cmd from response
Jon Hallce0d70b2018-12-11 11:01:32 -0800593 cmdPattern = cmdStr.strip()
594 main.log.debug( "REGEX PATTERN SET TO: " + repr( cmdPattern ) +
595 "\nSENT COMMAND STRING WAS: " + repr( cmdStr ) )
Jon Hall6c9e2da2018-11-06 12:01:23 -0800596 if relaxedRegex:
Jon Hallce0d70b2018-12-11 11:01:32 -0800597 cmdPattern = cmdPattern.split( '|' )[ -1 ].strip()
598 main.log.debug( "REGEX PATTERN SET TO: " + repr( cmdPattern ) +
599 "\nSENT COMMAND STRING WAS: " + repr( cmdStr ) )
Jon Hall6c9e2da2018-11-06 12:01:23 -0800600 # This was added because karaf 4.2 is stripping some characters from the command echo
Jon Hallce0d70b2018-12-11 11:01:32 -0800601 output = response.split( cmdPattern, 1 )
Jon Hall22e94ce2019-01-15 14:52:17 -0800602 if expectJson:
603 main.log.warn( "Relaxed Regex: Searching for a json string amongst the output" )
604 jsonPattern = r'\{.*\}'
605 match = re.search( jsonPattern, output[ 0 ] )
606 if match:
607 output = [ '' , match.group( 0 ) ] # We expect a list with the second element to be the output
Jon Hall39e3ffe2018-12-05 11:40:29 -0800608 if len( output ) < 2:
609 main.log.warn( "Relaxing regex match to last 5 characters of the sent command" )
Jon Hallce0d70b2018-12-11 11:01:32 -0800610 cmdPattern = cmdPattern[ -5: ]
611 main.log.debug( "REGEX PATTERN SET TO: " + repr( cmdPattern ) +
612 "\nSENT COMMAND STRING WAS: " + repr( cmdStr ) )
613 output = response.split( cmdPattern, 1 )
Jon Hall6c9e2da2018-11-06 12:01:23 -0800614 else:
Jon Hallce0d70b2018-12-11 11:01:32 -0800615 output = response.split( cmdPattern, 1 )
616 if len( output ) < 2: # TODO: Should we do this without the relaxedRegex flag?
Jon Hall8c9dd1c2018-11-14 15:40:39 -0800617 main.log.warn( "Relaxing regex match to last 5 characters of the sent command" )
Jon Hallce0d70b2018-12-11 11:01:32 -0800618 output = response.split( cmdPattern[ -5: ], 1 )
Jon Hall0e240372018-05-02 11:21:57 -0700619 if output:
620 if debug:
621 main.log.debug( self.name + ": split output" )
622 for r in output:
623 main.log.debug( self.name + ": " + repr( r ) )
Jon Hallce0d70b2018-12-11 11:01:32 -0800624 if len( output ) == 1:
625 main.log.error( "Could not remove sent command echo from output" )
626 return output
Jon Hall0e240372018-05-02 11:21:57 -0700627 output = output[ 1 ].strip()
GlennRC85870432015-11-23 11:45:51 -0800628 if showResponse:
GlennRCed771242016-01-13 17:02:47 -0800629 main.log.info( "Response from ONOS: {}".format( output ) )
Jon Hall0e240372018-05-02 11:21:57 -0700630 self.clearBuffer( debug=debug, timeout=timeout, noExit=noExit )
GlennRC85870432015-11-23 11:45:51 -0800631 return output
GlennRCed771242016-01-13 17:02:47 -0800632 except pexpect.TIMEOUT:
Jon Hall0e240372018-05-02 11:21:57 -0700633 main.log.error( self.name + ": ONOS timeout" )
GlennRCed771242016-01-13 17:02:47 -0800634 if debug:
635 main.log.debug( self.handle.before )
You Wang6b5e5ba2019-01-31 15:32:40 -0800636 self.exitFromCmd( self.karafPrompt, 100 )
GlennRCed771242016-01-13 17:02:47 -0800637 return None
Jon Hallc6358dd2015-04-10 12:44:28 -0700638 except IndexError:
639 main.log.exception( self.name + ": Object not as expected" )
Jon Halla495f562016-05-16 18:03:26 -0700640 main.log.debug( "response: {}".format( repr( response ) ) )
Jon Hallc6358dd2015-04-10 12:44:28 -0700641 return None
Jon Halld4d4b372015-01-28 16:02:41 -0800642 except TypeError:
643 main.log.exception( self.name + ": Object not as expected" )
644 return None
andrewonlaba18f6bf2014-10-13 19:31:54 -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 )
YPZhangebf9eb52016-05-12 15:20:24 -0700648 if noExit:
YPZhangebf9eb52016-05-12 15:20:24 -0700649 return None
650 else:
Devin Lim44075962017-08-11 10:56:37 -0700651 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -0800652 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -0800653 main.log.exception( self.name + ": Uncaught exception!" )
YPZhangebf9eb52016-05-12 15:20:24 -0700654 if noExit:
YPZhangebf9eb52016-05-12 15:20:24 -0700655 return None
656 else:
Devin Lim44075962017-08-11 10:56:37 -0700657 main.cleanAndExit()
andrewonlaba18f6bf2014-10-13 19:31:54 -0400658
Jon Halld5a94fb2018-11-13 14:32:23 -0800659 def lineCount( self, cmdStr, showResponse=False, debug=False, timeout=10, noExit=False, relaxedRegex=True ):
660 """
661 A wrapper around sendline(). Will return the number of lines returned or None on error
662
663 Required Arguments:
664 cmdStr - String to send to the pexpect session
665
666 Optional Arguments:
667 showResponse - Defaults to False. If True will log the response.
668 debug - Defaults to False. If True, will enable debug logging.
669 timeout - Defaults to 10. Amount of time in seconds for a command to return
670 before a timeout.
671 noExit - Defaults to False. If True, will not exit TestON in the event of a
672 closed channel, but instead return None
673 relaxedRegex - Defaults to True. If there is a pipe in the command send, will only try to match the last part of the piped command.
674
675 Warning: There are no sanity checking to commands sent using this method.
676
677 """
678 try:
679 numLines = self.sendline( cmdStr, showResponse, debug, timeout, noExit, relaxedRegex )
You Wang0ce8e0c2019-02-22 12:22:26 -0800680 parsed = re.search( "(\d+)", numLines )
Jon Hall8c9dd1c2018-11-14 15:40:39 -0800681 if not parsed:
682 main.log.error( "Warning, output of karaf's wc may have changed" )
683 return None
684 return parsed.group( 1 )
Jon Halld5a94fb2018-11-13 14:32:23 -0800685 except IndexError:
686 main.log.exception( self.name + ": Object not as expected" )
Jon Hallce0d70b2018-12-11 11:01:32 -0800687 main.log.debug( "response: {}".format( repr( numLines ) ) )
Jon Halld5a94fb2018-11-13 14:32:23 -0800688 return None
689 except TypeError:
690 main.log.exception( self.name + ": Object not as expected" )
691 return None
692 except Exception:
693 main.log.exception( self.name + ": Uncaught exception!" )
694 if noExit:
695 return None
696 else:
697 main.cleanAndExit()
698
kelvin8ec71442015-01-15 16:57:00 -0800699 # IMPORTANT NOTE:
700 # For all cli commands, naming convention should match
kelvin-onlabd3b64892015-01-20 13:26:24 -0800701 # the cli command changing 'a:b' with 'aB'.
702 # Ex ) onos:topology > onosTopology
703 # onos:links > onosLinks
704 # feature:list > featureList
Jon Halle3f39ff2015-01-13 11:50:53 -0800705
kelvin-onlabd3b64892015-01-20 13:26:24 -0800706 def addNode( self, nodeId, ONOSIp, tcpPort="" ):
kelvin8ec71442015-01-15 16:57:00 -0800707 """
andrewonlabc2d05aa2014-10-13 16:51:10 -0400708 Adds a new cluster node by ID and address information.
709 Required:
kelvin-onlabd3b64892015-01-20 13:26:24 -0800710 * nodeId
711 * ONOSIp
andrewonlabc2d05aa2014-10-13 16:51:10 -0400712 Optional:
kelvin-onlabd3b64892015-01-20 13:26:24 -0800713 * tcpPort
kelvin8ec71442015-01-15 16:57:00 -0800714 """
andrewonlabc2d05aa2014-10-13 16:51:10 -0400715 try:
kelvin-onlabd3b64892015-01-20 13:26:24 -0800716 cmdStr = "add-node " + str( nodeId ) + " " +\
717 str( ONOSIp ) + " " + str( tcpPort )
718 handle = self.sendline( cmdStr )
Jon Halla495f562016-05-16 18:03:26 -0700719 assert handle is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -0800720 assert "Command not found:" not in handle, handle
kelvin-onlab898a6c62015-01-16 14:13:53 -0800721 if re.search( "Error", handle ):
Jon Hall0e240372018-05-02 11:21:57 -0700722 main.log.error( self.name + ": Error in adding node" )
kelvin8ec71442015-01-15 16:57:00 -0800723 main.log.error( handle )
Jon Halle3f39ff2015-01-13 11:50:53 -0800724 return main.FALSE
andrewonlabc2d05aa2014-10-13 16:51:10 -0400725 else:
kelvin-onlabd3b64892015-01-20 13:26:24 -0800726 main.log.info( "Node " + str( ONOSIp ) + " added" )
andrewonlabc2d05aa2014-10-13 16:51:10 -0400727 return main.TRUE
Jon Hallc6793552016-01-19 14:18:37 -0800728 except AssertionError:
729 main.log.exception( "" )
730 return None
Jon Halld4d4b372015-01-28 16:02:41 -0800731 except TypeError:
732 main.log.exception( self.name + ": Object not as expected" )
733 return None
andrewonlabc2d05aa2014-10-13 16:51:10 -0400734 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -0800735 main.log.error( self.name + ": EOF exception found" )
736 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -0700737 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -0800738 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -0800739 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -0700740 main.cleanAndExit()
andrewonlabc2d05aa2014-10-13 16:51:10 -0400741
kelvin-onlabd3b64892015-01-20 13:26:24 -0800742 def removeNode( self, nodeId ):
kelvin8ec71442015-01-15 16:57:00 -0800743 """
andrewonlab86dc3082014-10-13 18:18:38 -0400744 Removes a cluster by ID
745 Issues command: 'remove-node [<node-id>]'
746 Required:
kelvin-onlabd3b64892015-01-20 13:26:24 -0800747 * nodeId
kelvin8ec71442015-01-15 16:57:00 -0800748 """
andrewonlab86dc3082014-10-13 18:18:38 -0400749 try:
andrewonlab86dc3082014-10-13 18:18:38 -0400750
kelvin-onlabd3b64892015-01-20 13:26:24 -0800751 cmdStr = "remove-node " + str( nodeId )
Jon Hall08f61bc2015-04-13 16:00:30 -0700752 handle = self.sendline( cmdStr )
Jon Halla495f562016-05-16 18:03:26 -0700753 assert handle is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -0800754 assert "Command not found:" not in handle, handle
Jon Hallc6358dd2015-04-10 12:44:28 -0700755 if re.search( "Error", handle ):
Jon Hall0e240372018-05-02 11:21:57 -0700756 main.log.error( self.name + ": Error in removing node" )
Jon Hallc6358dd2015-04-10 12:44:28 -0700757 main.log.error( handle )
758 return main.FALSE
759 else:
760 return main.TRUE
Jon Hallc6793552016-01-19 14:18:37 -0800761 except AssertionError:
762 main.log.exception( "" )
763 return None
Jon Halld4d4b372015-01-28 16:02:41 -0800764 except TypeError:
765 main.log.exception( self.name + ": Object not as expected" )
766 return None
andrewonlab86dc3082014-10-13 18:18:38 -0400767 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -0800768 main.log.error( self.name + ": EOF exception found" )
769 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -0700770 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -0800771 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -0800772 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -0700773 main.cleanAndExit()
andrewonlabc2d05aa2014-10-13 16:51:10 -0400774
Jeremy Ronquillo82705492017-10-18 14:19:55 -0700775 def nodes( self, jsonFormat=True ):
kelvin8ec71442015-01-15 16:57:00 -0800776 """
andrewonlab7c211572014-10-15 16:45:20 -0400777 List the nodes currently visible
778 Issues command: 'nodes'
Jon Hall61282e32015-03-19 11:34:11 -0700779 Optional argument:
780 * jsonFormat - boolean indicating if you want output in json
kelvin8ec71442015-01-15 16:57:00 -0800781 """
andrewonlab7c211572014-10-15 16:45:20 -0400782 try:
Jon Hallc6358dd2015-04-10 12:44:28 -0700783 cmdStr = "nodes"
Jon Hall61282e32015-03-19 11:34:11 -0700784 if jsonFormat:
Jon Hallc6358dd2015-04-10 12:44:28 -0700785 cmdStr += " -j"
786 output = self.sendline( cmdStr )
Jon Halla495f562016-05-16 18:03:26 -0700787 assert output is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -0800788 assert "Command not found:" not in output, output
Jon Hallc6358dd2015-04-10 12:44:28 -0700789 return output
Jon Hallc6793552016-01-19 14:18:37 -0800790 except AssertionError:
791 main.log.exception( "" )
792 return None
Jon Halld4d4b372015-01-28 16:02:41 -0800793 except TypeError:
794 main.log.exception( self.name + ": Object not as expected" )
795 return None
andrewonlab7c211572014-10-15 16:45:20 -0400796 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -0800797 main.log.error( self.name + ": EOF exception found" )
798 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -0700799 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -0800800 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -0800801 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -0700802 main.cleanAndExit()
andrewonlab7c211572014-10-15 16:45:20 -0400803
kelvin8ec71442015-01-15 16:57:00 -0800804 def topology( self ):
805 """
Hari Krishnaef1bd4e2015-03-12 16:55:30 -0700806 Definition:
Jon Hall390696c2015-05-05 17:13:41 -0700807 Returns the output of topology command.
Hari Krishnaef1bd4e2015-03-12 16:55:30 -0700808 Return:
809 topology = current ONOS topology
kelvin8ec71442015-01-15 16:57:00 -0800810 """
andrewonlab95ce8322014-10-13 14:12:04 -0400811 try:
Hari Krishnaef1bd4e2015-03-12 16:55:30 -0700812 cmdStr = "topology -j"
kelvin-onlabd3b64892015-01-20 13:26:24 -0800813 handle = self.sendline( cmdStr )
You Wangb5a55f72017-03-03 12:51:05 -0800814 assert handle is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -0800815 assert "Command not found:" not in handle, handle
Jon Hallc6358dd2015-04-10 12:44:28 -0700816 main.log.info( cmdStr + " returned: " + str( handle ) )
andrewonlab95ce8322014-10-13 14:12:04 -0400817 return handle
Jon Hallc6793552016-01-19 14:18:37 -0800818 except AssertionError:
819 main.log.exception( "" )
Jon Halld4d4b372015-01-28 16:02:41 -0800820 return None
Jon Halld4d4b372015-01-28 16:02:41 -0800821 except TypeError:
822 main.log.exception( self.name + ": Object not as expected" )
823 return None
andrewonlabc2d05aa2014-10-13 16:51:10 -0400824 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -0800825 main.log.error( self.name + ": EOF exception found" )
826 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -0700827 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -0800828 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -0800829 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -0700830 main.cleanAndExit()
Jon Hallffb386d2014-11-21 13:43:38 -0800831
jenkins7ead5a82015-03-13 10:28:21 -0700832 def deviceRemove( self, deviceId ):
833 """
834 Removes particular device from storage
835
836 TODO: refactor this function
837 """
838 try:
Jon Hallc6358dd2015-04-10 12:44:28 -0700839 cmdStr = "device-remove " + str( deviceId )
840 handle = self.sendline( cmdStr )
You Wangb5a55f72017-03-03 12:51:05 -0800841 assert handle is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -0800842 assert "Command not found:" not in handle, handle
Jon Hallc6358dd2015-04-10 12:44:28 -0700843 if re.search( "Error", handle ):
Jon Hall0e240372018-05-02 11:21:57 -0700844 main.log.error( self.name + ": Error in removing device" )
Jon Hallc6358dd2015-04-10 12:44:28 -0700845 main.log.error( handle )
846 return main.FALSE
847 else:
848 return main.TRUE
Jon Hallc6793552016-01-19 14:18:37 -0800849 except AssertionError:
850 main.log.exception( "" )
851 return None
jenkins7ead5a82015-03-13 10:28:21 -0700852 except TypeError:
853 main.log.exception( self.name + ": Object not as expected" )
854 return None
855 except pexpect.EOF:
856 main.log.error( self.name + ": EOF exception found" )
857 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -0700858 main.cleanAndExit()
jenkins7ead5a82015-03-13 10:28:21 -0700859 except Exception:
860 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -0700861 main.cleanAndExit()
jenkins7ead5a82015-03-13 10:28:21 -0700862
You Wang3b9689a2018-08-30 12:24:00 -0700863 def devices( self, jsonFormat=True, timeout=30 ):
kelvin8ec71442015-01-15 16:57:00 -0800864 """
Jon Hall7b02d952014-10-17 20:14:54 -0400865 Lists all infrastructure devices or switches
andrewonlab86dc3082014-10-13 18:18:38 -0400866 Optional argument:
kelvin-onlabd3b64892015-01-20 13:26:24 -0800867 * jsonFormat - boolean indicating if you want output in json
kelvin8ec71442015-01-15 16:57:00 -0800868 """
andrewonlab86dc3082014-10-13 18:18:38 -0400869 try:
Jon Hallc6358dd2015-04-10 12:44:28 -0700870 cmdStr = "devices"
kelvin-onlabd3b64892015-01-20 13:26:24 -0800871 if jsonFormat:
Jon Hallc6358dd2015-04-10 12:44:28 -0700872 cmdStr += " -j"
You Wang3b9689a2018-08-30 12:24:00 -0700873 handle = self.sendline( cmdStr, timeout=timeout )
You Wangb5a55f72017-03-03 12:51:05 -0800874 assert handle is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -0800875 assert "Command not found:" not in handle, handle
Jon Hallc6358dd2015-04-10 12:44:28 -0700876 return handle
Jon Hallc6793552016-01-19 14:18:37 -0800877 except AssertionError:
878 main.log.exception( "" )
879 return None
Jon Halld4d4b372015-01-28 16:02:41 -0800880 except TypeError:
881 main.log.exception( self.name + ": Object not as expected" )
882 return None
andrewonlab7c211572014-10-15 16:45:20 -0400883 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -0800884 main.log.error( self.name + ": EOF exception found" )
885 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -0700886 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -0800887 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -0800888 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -0700889 main.cleanAndExit()
andrewonlab7c211572014-10-15 16:45:20 -0400890
kelvin-onlabd3b64892015-01-20 13:26:24 -0800891 def balanceMasters( self ):
kelvin8ec71442015-01-15 16:57:00 -0800892 """
Hari Krishnaa43d4e92014-12-19 13:22:40 -0800893 This balances the devices across all controllers
894 by issuing command: 'onos> onos:balance-masters'
895 If required this could be extended to return devices balanced output.
kelvin8ec71442015-01-15 16:57:00 -0800896 """
Hari Krishnaa43d4e92014-12-19 13:22:40 -0800897 try:
kelvin-onlabd3b64892015-01-20 13:26:24 -0800898 cmdStr = "onos:balance-masters"
Jon Hallc6358dd2015-04-10 12:44:28 -0700899 handle = self.sendline( cmdStr )
You Wangb5a55f72017-03-03 12:51:05 -0800900 assert handle is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -0800901 assert "Command not found:" not in handle, handle
Jon Hallc6358dd2015-04-10 12:44:28 -0700902 if re.search( "Error", handle ):
Jon Hall0e240372018-05-02 11:21:57 -0700903 main.log.error( self.name + ": Error in balancing masters" )
Jon Hallc6358dd2015-04-10 12:44:28 -0700904 main.log.error( handle )
905 return main.FALSE
906 else:
907 return main.TRUE
Jon Hallc6793552016-01-19 14:18:37 -0800908 except AssertionError:
909 main.log.exception( "" )
910 return None
Jon Halld4d4b372015-01-28 16:02:41 -0800911 except TypeError:
912 main.log.exception( self.name + ": Object not as expected" )
913 return None
Hari Krishnaa43d4e92014-12-19 13:22:40 -0800914 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -0800915 main.log.error( self.name + ": EOF exception found" )
916 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -0700917 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -0800918 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -0800919 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -0700920 main.cleanAndExit()
Hari Krishnaa43d4e92014-12-19 13:22:40 -0800921
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000922 def checkMasters( self, jsonFormat=True ):
acsmars24950022015-07-30 18:00:43 -0700923 """
924 Returns the output of the masters command.
925 Optional argument:
926 * jsonFormat - boolean indicating if you want output in json
927 """
928 try:
929 cmdStr = "onos:masters"
930 if jsonFormat:
931 cmdStr += " -j"
932 output = self.sendline( cmdStr )
Jon Halla495f562016-05-16 18:03:26 -0700933 assert output is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -0800934 assert "Command not found:" not in output, output
acsmars24950022015-07-30 18:00:43 -0700935 return output
Jon Hallc6793552016-01-19 14:18:37 -0800936 except AssertionError:
937 main.log.exception( "" )
938 return None
acsmars24950022015-07-30 18:00:43 -0700939 except TypeError:
940 main.log.exception( self.name + ": Object not as expected" )
941 return None
942 except pexpect.EOF:
943 main.log.error( self.name + ": EOF exception found" )
944 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -0700945 main.cleanAndExit()
acsmars24950022015-07-30 18:00:43 -0700946 except Exception:
947 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -0700948 main.cleanAndExit()
acsmars24950022015-07-30 18:00:43 -0700949
Jon Hallc6793552016-01-19 14:18:37 -0800950 def checkBalanceMasters( self, jsonFormat=True ):
acsmars24950022015-07-30 18:00:43 -0700951 """
952 Uses the master command to check that the devices' leadership
953 is evenly divided
954
955 Dependencies: checkMasters() and summary()
956
Jon Hall6509dbf2016-06-21 17:01:17 -0700957 Returns main.TRUE if the devices are balanced
958 Returns main.FALSE if the devices are unbalanced
acsmars24950022015-07-30 18:00:43 -0700959 Exits on Exception
960 Returns None on TypeError
961 """
962 try:
Jon Hallc6793552016-01-19 14:18:37 -0800963 summaryOutput = self.summary()
964 totalDevices = json.loads( summaryOutput )[ "devices" ]
965 except ( TypeError, ValueError ):
966 main.log.exception( "{}: Object not as expected: {!r}".format( self.name, summaryOutput ) )
967 return None
968 try:
acsmars24950022015-07-30 18:00:43 -0700969 totalOwnedDevices = 0
Jon Hallc6793552016-01-19 14:18:37 -0800970 mastersOutput = self.checkMasters()
971 masters = json.loads( mastersOutput )
acsmars24950022015-07-30 18:00:43 -0700972 first = masters[ 0 ][ "size" ]
973 for master in masters:
974 totalOwnedDevices += master[ "size" ]
975 if master[ "size" ] > first + 1 or master[ "size" ] < first - 1:
976 main.log.error( "Mastership not balanced" )
977 main.log.info( "\n" + self.checkMasters( False ) )
978 return main.FALSE
Jon Halle0f0b342017-04-18 11:43:47 -0700979 main.log.info( "Mastership balanced between " +
Jeremy Ronquillo82705492017-10-18 14:19:55 -0700980 str( len( masters ) ) + " masters" )
acsmars24950022015-07-30 18:00:43 -0700981 return main.TRUE
Jon Hallc6793552016-01-19 14:18:37 -0800982 except ( TypeError, ValueError ):
983 main.log.exception( "{}: Object not as expected: {!r}".format( self.name, mastersOutput ) )
acsmars24950022015-07-30 18:00:43 -0700984 return None
985 except pexpect.EOF:
986 main.log.error( self.name + ": EOF exception found" )
987 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -0700988 main.cleanAndExit()
acsmars24950022015-07-30 18:00:43 -0700989 except Exception:
990 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -0700991 main.cleanAndExit()
acsmars24950022015-07-30 18:00:43 -0700992
YPZhangfebf7302016-05-24 16:45:56 -0700993 def links( self, jsonFormat=True, timeout=30 ):
kelvin8ec71442015-01-15 16:57:00 -0800994 """
Jon Halle8217482014-10-17 13:49:14 -0400995 Lists all core links
996 Optional argument:
kelvin-onlabd3b64892015-01-20 13:26:24 -0800997 * jsonFormat - boolean indicating if you want output in json
kelvin8ec71442015-01-15 16:57:00 -0800998 """
Jon Halle8217482014-10-17 13:49:14 -0400999 try:
Jon Hallc6358dd2015-04-10 12:44:28 -07001000 cmdStr = "links"
kelvin-onlabd3b64892015-01-20 13:26:24 -08001001 if jsonFormat:
Jon Hallc6358dd2015-04-10 12:44:28 -07001002 cmdStr += " -j"
YPZhangfebf7302016-05-24 16:45:56 -07001003 handle = self.sendline( cmdStr, timeout=timeout )
You Wangb5a55f72017-03-03 12:51:05 -08001004 assert handle is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08001005 assert "Command not found:" not in handle, handle
Jon Hallc6358dd2015-04-10 12:44:28 -07001006 return handle
Jon Hallc6793552016-01-19 14:18:37 -08001007 except AssertionError:
1008 main.log.exception( "" )
1009 return None
Jon Halld4d4b372015-01-28 16:02:41 -08001010 except TypeError:
1011 main.log.exception( self.name + ": Object not as expected" )
1012 return None
Jon Halle8217482014-10-17 13:49:14 -04001013 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08001014 main.log.error( self.name + ": EOF exception found" )
1015 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001016 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -08001017 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -08001018 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001019 main.cleanAndExit()
Jon Halle8217482014-10-17 13:49:14 -04001020
You Wang3b9689a2018-08-30 12:24:00 -07001021 def ports( self, jsonFormat=True, timeout=30 ):
kelvin8ec71442015-01-15 16:57:00 -08001022 """
Jon Halle8217482014-10-17 13:49:14 -04001023 Lists all ports
1024 Optional argument:
kelvin-onlabd3b64892015-01-20 13:26:24 -08001025 * jsonFormat - boolean indicating if you want output in json
kelvin8ec71442015-01-15 16:57:00 -08001026 """
Jon Halle8217482014-10-17 13:49:14 -04001027 try:
Jon Hallc6358dd2015-04-10 12:44:28 -07001028 cmdStr = "ports"
kelvin-onlabd3b64892015-01-20 13:26:24 -08001029 if jsonFormat:
Jon Hallc6358dd2015-04-10 12:44:28 -07001030 cmdStr += " -j"
You Wang3b9689a2018-08-30 12:24:00 -07001031 handle = self.sendline( cmdStr, timeout=timeout )
You Wangb5a55f72017-03-03 12:51:05 -08001032 assert handle is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08001033 assert "Command not found:" not in handle, handle
Jon Hallc6358dd2015-04-10 12:44:28 -07001034 return handle
Jon Hallc6793552016-01-19 14:18:37 -08001035 except AssertionError:
1036 main.log.exception( "" )
1037 return None
Jon Halld4d4b372015-01-28 16:02:41 -08001038 except TypeError:
1039 main.log.exception( self.name + ": Object not as expected" )
1040 return None
Jon Halle8217482014-10-17 13:49:14 -04001041 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08001042 main.log.error( self.name + ": EOF exception found" )
1043 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001044 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -08001045 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -08001046 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001047 main.cleanAndExit()
Jon Halle8217482014-10-17 13:49:14 -04001048
kelvin-onlabd3b64892015-01-20 13:26:24 -08001049 def roles( self, jsonFormat=True ):
kelvin8ec71442015-01-15 16:57:00 -08001050 """
Jon Hall983a1702014-10-28 18:44:22 -04001051 Lists all devices and the controllers with roles assigned to them
1052 Optional argument:
kelvin-onlabd3b64892015-01-20 13:26:24 -08001053 * jsonFormat - boolean indicating if you want output in json
kelvin8ec71442015-01-15 16:57:00 -08001054 """
andrewonlab7c211572014-10-15 16:45:20 -04001055 try:
Jon Hallc6358dd2015-04-10 12:44:28 -07001056 cmdStr = "roles"
kelvin-onlabd3b64892015-01-20 13:26:24 -08001057 if jsonFormat:
Jon Hallc6358dd2015-04-10 12:44:28 -07001058 cmdStr += " -j"
1059 handle = self.sendline( cmdStr )
You Wangb5a55f72017-03-03 12:51:05 -08001060 assert handle is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08001061 assert "Command not found:" not in handle, handle
Jon Hallc6358dd2015-04-10 12:44:28 -07001062 return handle
Jon Hallc6793552016-01-19 14:18:37 -08001063 except AssertionError:
1064 main.log.exception( "" )
1065 return None
Jon Halld4d4b372015-01-28 16:02:41 -08001066 except TypeError:
1067 main.log.exception( self.name + ": Object not as expected" )
1068 return None
Jon Hall983a1702014-10-28 18:44:22 -04001069 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08001070 main.log.error( self.name + ": EOF exception found" )
1071 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001072 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -08001073 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -08001074 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001075 main.cleanAndExit()
Jon Hall983a1702014-10-28 18:44:22 -04001076
kelvin-onlabd3b64892015-01-20 13:26:24 -08001077 def getRole( self, deviceId ):
kelvin-onlab898a6c62015-01-16 14:13:53 -08001078 """
Jon Halle3f39ff2015-01-13 11:50:53 -08001079 Given the a string containing the json representation of the "roles"
1080 cli command and a partial or whole device id, returns a json object
1081 containing the roles output for the first device whose id contains
1082 "device_id"
Jon Hall983a1702014-10-28 18:44:22 -04001083
1084 Returns:
Jon Halle3f39ff2015-01-13 11:50:53 -08001085 A dict of the role assignments for the given device or
1086 None if no match
kelvin8ec71442015-01-15 16:57:00 -08001087 """
Jon Hall983a1702014-10-28 18:44:22 -04001088 try:
kelvin-onlabd3b64892015-01-20 13:26:24 -08001089 if deviceId is None:
Jon Hall983a1702014-10-28 18:44:22 -04001090 return None
1091 else:
kelvin-onlabd3b64892015-01-20 13:26:24 -08001092 rawRoles = self.roles()
1093 rolesJson = json.loads( rawRoles )
kelvin8ec71442015-01-15 16:57:00 -08001094 # search json for the device with id then return the device
kelvin-onlabd3b64892015-01-20 13:26:24 -08001095 for device in rolesJson:
kelvin8ec71442015-01-15 16:57:00 -08001096 # print device
kelvin-onlabd3b64892015-01-20 13:26:24 -08001097 if str( deviceId ) in device[ 'id' ]:
Jon Hall983a1702014-10-28 18:44:22 -04001098 return device
1099 return None
Jon Hallc6793552016-01-19 14:18:37 -08001100 except ( TypeError, ValueError ):
1101 main.log.exception( "{}: Object not as expected: {!r}".format( self.name, rawRoles ) )
Jon Halld4d4b372015-01-28 16:02:41 -08001102 return None
andrewonlab86dc3082014-10-13 18:18:38 -04001103 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08001104 main.log.error( self.name + ": EOF exception found" )
1105 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001106 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -08001107 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -08001108 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001109 main.cleanAndExit()
Jon Hall94fd0472014-12-08 11:52:42 -08001110
kelvin-onlabd3b64892015-01-20 13:26:24 -08001111 def rolesNotNull( self ):
kelvin8ec71442015-01-15 16:57:00 -08001112 """
Jon Hall94fd0472014-12-08 11:52:42 -08001113 Iterates through each device and checks if there is a master assigned
1114 Returns: main.TRUE if each device has a master
1115 main.FALSE any device has no master
kelvin8ec71442015-01-15 16:57:00 -08001116 """
Jon Hall94fd0472014-12-08 11:52:42 -08001117 try:
kelvin-onlabd3b64892015-01-20 13:26:24 -08001118 rawRoles = self.roles()
1119 rolesJson = json.loads( rawRoles )
kelvin8ec71442015-01-15 16:57:00 -08001120 # search json for the device with id then return the device
kelvin-onlabd3b64892015-01-20 13:26:24 -08001121 for device in rolesJson:
kelvin8ec71442015-01-15 16:57:00 -08001122 # print device
1123 if device[ 'master' ] == "none":
1124 main.log.warn( "Device has no master: " + str( device ) )
Jon Hall94fd0472014-12-08 11:52:42 -08001125 return main.FALSE
1126 return main.TRUE
Jon Hallc6793552016-01-19 14:18:37 -08001127 except ( TypeError, ValueError ):
1128 main.log.exception( "{}: Object not as expected: {!r}".format( self.name, rawRoles ) )
Jon Halld4d4b372015-01-28 16:02:41 -08001129 return None
Jon Hall94fd0472014-12-08 11:52:42 -08001130 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08001131 main.log.error( self.name + ": EOF exception found" )
1132 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001133 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -08001134 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -08001135 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001136 main.cleanAndExit()
Jon Hall94fd0472014-12-08 11:52:42 -08001137
kelvin-onlabd3b64892015-01-20 13:26:24 -08001138 def paths( self, srcId, dstId ):
kelvin8ec71442015-01-15 16:57:00 -08001139 """
andrewonlab3e15ead2014-10-15 14:21:34 -04001140 Returns string of paths, and the cost.
1141 Issues command: onos:paths <src> <dst>
kelvin8ec71442015-01-15 16:57:00 -08001142 """
andrewonlab3e15ead2014-10-15 14:21:34 -04001143 try:
kelvin-onlabd3b64892015-01-20 13:26:24 -08001144 cmdStr = "onos:paths " + str( srcId ) + " " + str( dstId )
1145 handle = self.sendline( cmdStr )
You Wangb5a55f72017-03-03 12:51:05 -08001146 assert handle is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08001147 assert "Command not found:" not in handle, handle
Jon Halle3f39ff2015-01-13 11:50:53 -08001148 if re.search( "Error", handle ):
Jon Hall0e240372018-05-02 11:21:57 -07001149 main.log.error( self.name + ": Error in getting paths" )
kelvin8ec71442015-01-15 16:57:00 -08001150 return ( handle, "Error" )
andrewonlab3e15ead2014-10-15 14:21:34 -04001151 else:
kelvin8ec71442015-01-15 16:57:00 -08001152 path = handle.split( ";" )[ 0 ]
1153 cost = handle.split( ";" )[ 1 ]
1154 return ( path, cost )
Jon Hallc6793552016-01-19 14:18:37 -08001155 except AssertionError:
1156 main.log.exception( "" )
1157 return ( handle, "Error" )
Jon Halld4d4b372015-01-28 16:02:41 -08001158 except TypeError:
1159 main.log.exception( self.name + ": Object not as expected" )
1160 return ( handle, "Error" )
andrewonlab3e15ead2014-10-15 14:21:34 -04001161 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08001162 main.log.error( self.name + ": EOF exception found" )
1163 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001164 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -08001165 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -08001166 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001167 main.cleanAndExit()
Jon Hallffb386d2014-11-21 13:43:38 -08001168
kelvin-onlabd3b64892015-01-20 13:26:24 -08001169 def hosts( self, jsonFormat=True ):
kelvin8ec71442015-01-15 16:57:00 -08001170 """
Jon Hallffb386d2014-11-21 13:43:38 -08001171 Lists all discovered hosts
Jon Hall42db6dc2014-10-24 19:03:48 -04001172 Optional argument:
kelvin-onlabd3b64892015-01-20 13:26:24 -08001173 * jsonFormat - boolean indicating if you want output in json
kelvin8ec71442015-01-15 16:57:00 -08001174 """
Jon Hall42db6dc2014-10-24 19:03:48 -04001175 try:
Jon Hallc6358dd2015-04-10 12:44:28 -07001176 cmdStr = "hosts"
kelvin-onlabd3b64892015-01-20 13:26:24 -08001177 if jsonFormat:
Jon Hallc6358dd2015-04-10 12:44:28 -07001178 cmdStr += " -j"
1179 handle = self.sendline( cmdStr )
Jeremyd9e4eb12016-04-13 12:09:06 -07001180 if handle:
1181 assert "Command not found:" not in handle, handle
Jon Hallbaf53162015-12-17 17:04:34 -08001182 # TODO: Maybe make this less hardcoded
1183 # ConsistentMap Exceptions
1184 assert "org.onosproject.store.service" not in handle
1185 # Node not leader
1186 assert "java.lang.IllegalStateException" not in handle
Jon Hallc6358dd2015-04-10 12:44:28 -07001187 return handle
Jon Hallc6793552016-01-19 14:18:37 -08001188 except AssertionError:
Jon Hall0e240372018-05-02 11:21:57 -07001189 main.log.exception( self.name + ": Error in processing '" + cmdStr + "' " +
Jeremy Songster6949cea2016-04-19 18:13:18 -07001190 "command: " + str( handle ) )
Jon Hallc6793552016-01-19 14:18:37 -08001191 return None
Jon Halld4d4b372015-01-28 16:02:41 -08001192 except TypeError:
1193 main.log.exception( self.name + ": Object not as expected" )
1194 return None
Jon Hall42db6dc2014-10-24 19:03:48 -04001195 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08001196 main.log.error( self.name + ": EOF exception found" )
1197 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001198 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -08001199 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -08001200 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001201 main.cleanAndExit()
Jon Hall42db6dc2014-10-24 19:03:48 -04001202
kelvin-onlabd3b64892015-01-20 13:26:24 -08001203 def getHost( self, mac ):
kelvin8ec71442015-01-15 16:57:00 -08001204 """
Jon Hall42db6dc2014-10-24 19:03:48 -04001205 Return the first host from the hosts api whose 'id' contains 'mac'
Jon Halle3f39ff2015-01-13 11:50:53 -08001206
Jon Hallefbd9792015-03-05 16:11:36 -08001207 Note: mac must be a colon separated mac address, but could be a
Jon Halle3f39ff2015-01-13 11:50:53 -08001208 partial mac address
1209
Jon Hall42db6dc2014-10-24 19:03:48 -04001210 Return None if there is no match
kelvin8ec71442015-01-15 16:57:00 -08001211 """
Jon Hall42db6dc2014-10-24 19:03:48 -04001212 try:
kelvin8ec71442015-01-15 16:57:00 -08001213 if mac is None:
Jon Hall42db6dc2014-10-24 19:03:48 -04001214 return None
1215 else:
1216 mac = mac
kelvin-onlabd3b64892015-01-20 13:26:24 -08001217 rawHosts = self.hosts()
1218 hostsJson = json.loads( rawHosts )
kelvin8ec71442015-01-15 16:57:00 -08001219 # search json for the host with mac then return the device
kelvin-onlabd3b64892015-01-20 13:26:24 -08001220 for host in hostsJson:
kelvin8ec71442015-01-15 16:57:00 -08001221 # print "%s in %s?" % ( mac, host[ 'id' ] )
Jon Halld4d4b372015-01-28 16:02:41 -08001222 if not host:
1223 pass
1224 elif mac in host[ 'id' ]:
Jon Hall42db6dc2014-10-24 19:03:48 -04001225 return host
1226 return None
Jon Hallc6793552016-01-19 14:18:37 -08001227 except ( TypeError, ValueError ):
1228 main.log.exception( "{}: Object not as expected: {!r}".format( self.name, rawHosts ) )
Jon Halld4d4b372015-01-28 16:02:41 -08001229 return None
Jon Hall42db6dc2014-10-24 19:03:48 -04001230 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08001231 main.log.error( self.name + ": EOF exception found" )
1232 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001233 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -08001234 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -08001235 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001236 main.cleanAndExit()
Jon Hall42db6dc2014-10-24 19:03:48 -04001237
kelvin-onlabd3b64892015-01-20 13:26:24 -08001238 def getHostsId( self, hostList ):
kelvin8ec71442015-01-15 16:57:00 -08001239 """
1240 Obtain list of hosts
andrewonlab3f0a4af2014-10-17 12:25:14 -04001241 Issues command: 'onos> hosts'
kelvin8ec71442015-01-15 16:57:00 -08001242
andrewonlab3f0a4af2014-10-17 12:25:14 -04001243 Required:
kelvin-onlabd3b64892015-01-20 13:26:24 -08001244 * hostList: List of hosts obtained by Mininet
andrewonlab3f0a4af2014-10-17 12:25:14 -04001245 IMPORTANT:
1246 This function assumes that you started your
kelvin8ec71442015-01-15 16:57:00 -08001247 topology with the option '--mac'.
andrewonlab3f0a4af2014-10-17 12:25:14 -04001248 Furthermore, it assumes that value of VLAN is '-1'
1249 Description:
kelvin8ec71442015-01-15 16:57:00 -08001250 Converts mininet hosts ( h1, h2, h3... ) into
1251 ONOS format ( 00:00:00:00:00:01/-1 , ... )
1252 """
andrewonlab3f0a4af2014-10-17 12:25:14 -04001253 try:
kelvin-onlabd3b64892015-01-20 13:26:24 -08001254 onosHostList = []
andrewonlab3f0a4af2014-10-17 12:25:14 -04001255
kelvin-onlabd3b64892015-01-20 13:26:24 -08001256 for host in hostList:
kelvin8ec71442015-01-15 16:57:00 -08001257 host = host.replace( "h", "" )
kelvin-onlabd3b64892015-01-20 13:26:24 -08001258 hostHex = hex( int( host ) ).zfill( 12 )
1259 hostHex = str( hostHex ).replace( 'x', '0' )
1260 i = iter( str( hostHex ) )
1261 hostHex = ":".join( a + b for a, b in zip( i, i ) )
1262 hostHex = hostHex + "/-1"
1263 onosHostList.append( hostHex )
andrewonlab3f0a4af2014-10-17 12:25:14 -04001264
kelvin-onlabd3b64892015-01-20 13:26:24 -08001265 return onosHostList
andrewonlab3f0a4af2014-10-17 12:25:14 -04001266
Jon Halld4d4b372015-01-28 16:02:41 -08001267 except TypeError:
1268 main.log.exception( self.name + ": Object not as expected" )
1269 return None
andrewonlab3f0a4af2014-10-17 12:25:14 -04001270 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08001271 main.log.error( self.name + ": EOF exception found" )
1272 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001273 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -08001274 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -08001275 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001276 main.cleanAndExit()
andrewonlab3e15ead2014-10-15 14:21:34 -04001277
You Wangbc898b82018-05-03 16:22:34 -07001278 def verifyHostLocation( self, hostIp, location ):
1279 """
1280 Description:
1281 Verify the host given is discovered in all locations expected
1282 Required:
1283 hostIp: IP address of the host
1284 location: expected location(s) of the given host. ex. "of:0000000000000005/8"
1285 Could be a string or list
1286 Returns:
1287 main.TRUE if host is discovered on all locations provided
1288 main.FALSE otherwise
1289 """
You Wangbc898b82018-05-03 16:22:34 -07001290 locations = [ location ] if isinstance( location, str ) else location
1291 assert isinstance( locations, list ), "Wrong type of location: {}".format( type( location ) )
1292 try:
1293 hosts = self.hosts()
1294 hosts = json.loads( hosts )
1295 targetHost = None
1296 for host in hosts:
1297 if hostIp in host[ "ipAddresses" ]:
1298 targetHost = host
You Wangfd80ab42018-05-10 17:21:53 -07001299 assert targetHost, "Not able to find host with IP {}".format( hostIp )
You Wangbc898b82018-05-03 16:22:34 -07001300 result = main.TRUE
1301 locationsDiscovered = [ loc[ "elementId" ] + "/" + loc[ "port" ] for loc in targetHost[ "locations" ] ]
1302 for loc in locations:
1303 discovered = False
1304 for locDiscovered in locationsDiscovered:
You Wang547893e2018-05-08 13:34:59 -07001305 locToMatch = locDiscovered if "/" in loc else locDiscovered.split( "/" )[0]
1306 if loc == locToMatch:
You Wangbc898b82018-05-03 16:22:34 -07001307 main.log.debug( "Host {} discovered with location {}".format( hostIp, loc ) )
You Wang547893e2018-05-08 13:34:59 -07001308 discovered = True
You Wangbc898b82018-05-03 16:22:34 -07001309 break
1310 if discovered:
1311 locationsDiscovered.remove( locDiscovered )
1312 else:
1313 main.log.warn( "Host {} not discovered with location {}".format( hostIp, loc ) )
1314 result = main.FALSE
1315 if locationsDiscovered:
1316 main.log.warn( "Host {} is also discovered with location {}".format( hostIp, locationsDiscovered ) )
1317 result = main.FALSE
1318 return result
1319 except KeyError:
1320 main.log.exception( self.name + ": host data not as expected: " + hosts )
1321 return None
1322 except pexpect.EOF:
1323 main.log.error( self.name + ": EOF exception found" )
1324 main.log.error( self.name + ": " + self.handle.before )
1325 main.cleanAndExit()
1326 except Exception:
1327 main.log.exception( self.name + ": Uncaught exception" )
1328 return None
1329
You Wang53dba1e2018-02-02 17:45:44 -08001330 def verifyHostIp( self, hostList=[], prefix="" ):
1331 """
1332 Description:
1333 Verify that all hosts have IP address assigned to them
1334 Optional:
1335 hostList: If specified, verifications only happen to the hosts
1336 in hostList
1337 prefix: at least one of the ip address assigned to the host
1338 needs to have the specified prefix
1339 Returns:
1340 main.TRUE if all hosts have specific IP address assigned;
1341 main.FALSE otherwise
1342 """
You Wang53dba1e2018-02-02 17:45:44 -08001343 try:
1344 hosts = self.hosts()
1345 hosts = json.loads( hosts )
1346 if not hostList:
1347 hostList = [ host[ "id" ] for host in hosts ]
1348 for host in hosts:
1349 hostId = host[ "id" ]
1350 if hostId not in hostList:
1351 continue
1352 ipList = host[ "ipAddresses" ]
1353 main.log.debug( self.name + ": IP list on host " + str( hostId ) + ": " + str( ipList ) )
1354 if not ipList:
1355 main.log.warn( self.name + ": Failed to discover any IP addresses on host " + str( hostId ) )
1356 else:
1357 if not any( ip.startswith( str( prefix ) ) for ip in ipList ):
1358 main.log.warn( self.name + ": None of the IPs on host " + str( hostId ) + " has prefix " + str( prefix ) )
1359 else:
1360 main.log.debug( self.name + ": Found matching IP on host " + str( hostId ) )
1361 hostList.remove( hostId )
1362 if hostList:
1363 main.log.warn( self.name + ": failed to verify IP on following hosts: " + str( hostList) )
Jon Hall43060f62020-06-23 13:13:33 -07001364 # Print info for debugging
1365 main.log.debug( self.name + ": hosts output: " + str( hosts ) )
You Wang53dba1e2018-02-02 17:45:44 -08001366 return main.FALSE
1367 else:
1368 return main.TRUE
1369 except KeyError:
1370 main.log.exception( self.name + ": host data not as expected: " + hosts )
1371 return None
1372 except pexpect.EOF:
1373 main.log.error( self.name + ": EOF exception found" )
1374 main.log.error( self.name + ": " + self.handle.before )
1375 main.cleanAndExit()
1376 except Exception:
1377 main.log.exception( self.name + ": Uncaught exception" )
1378 return None
1379
Shreya Chowdhary6fbb96c2017-05-02 16:20:19 -07001380 def addHostIntent( self, hostIdOne, hostIdTwo, vlanId="", setVlan="", encap="", bandwidth="" ):
kelvin8ec71442015-01-15 16:57:00 -08001381 """
andrewonlabe6745342014-10-17 14:29:13 -04001382 Required:
kelvin-onlabd3b64892015-01-20 13:26:24 -08001383 * hostIdOne: ONOS host id for host1
1384 * hostIdTwo: ONOS host id for host2
Jeremy Songster832f9e92016-05-05 14:30:49 -07001385 Optional:
1386 * vlanId: specify a VLAN id for the intent
Jeremy Songsterff553672016-05-12 17:06:23 -07001387 * setVlan: specify a VLAN id treatment
Jeremy Songsterc032f162016-08-04 17:14:49 -07001388 * encap: specify an encapsulation type
andrewonlabe6745342014-10-17 14:29:13 -04001389 Description:
Jon Hallefbd9792015-03-05 16:11:36 -08001390 Adds a host-to-host intent ( bidirectional ) by
Jon Hallb1290e82014-11-18 16:17:48 -05001391 specifying the two hosts.
kelvin-onlabfb521662015-02-27 09:52:40 -08001392 Returns:
1393 A string of the intent id or None on Error
kelvin8ec71442015-01-15 16:57:00 -08001394 """
andrewonlabe6745342014-10-17 14:29:13 -04001395 try:
Jeremy Songster832f9e92016-05-05 14:30:49 -07001396 cmdStr = "add-host-intent "
1397 if vlanId:
1398 cmdStr += "-v " + str( vlanId ) + " "
Jeremy Songsterff553672016-05-12 17:06:23 -07001399 if setVlan:
1400 cmdStr += "--setVlan " + str( vlanId ) + " "
Jeremy Songsterc032f162016-08-04 17:14:49 -07001401 if encap:
1402 cmdStr += "--encapsulation " + str( encap ) + " "
Shreya Chowdhary6fbb96c2017-05-02 16:20:19 -07001403 if bandwidth:
1404 cmdStr += "-b " + str( bandwidth ) + " "
Jeremy Songster832f9e92016-05-05 14:30:49 -07001405 cmdStr += str( hostIdOne ) + " " + str( hostIdTwo )
kelvin-onlabd3b64892015-01-20 13:26:24 -08001406 handle = self.sendline( cmdStr )
You Wangb5a55f72017-03-03 12:51:05 -08001407 assert handle is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08001408 assert "Command not found:" not in handle, handle
Hari Krishnaac4e1782015-01-26 12:09:12 -08001409 if re.search( "Error", handle ):
Jon Hall0e240372018-05-02 11:21:57 -07001410 main.log.error( self.name + ": Error in adding Host intent" )
Jon Hall61282e32015-03-19 11:34:11 -07001411 main.log.debug( "Response from ONOS was: " + repr( handle ) )
kelvin-onlabfb521662015-02-27 09:52:40 -08001412 return None
Hari Krishnaac4e1782015-01-26 12:09:12 -08001413 else:
1414 main.log.info( "Host intent installed between " +
kelvin-onlabfb521662015-02-27 09:52:40 -08001415 str( hostIdOne ) + " and " + str( hostIdTwo ) )
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001416 match = re.search( 'id=0x([\da-f]+),', handle )
kelvin-onlabfb521662015-02-27 09:52:40 -08001417 if match:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001418 return match.group()[ 3:-1 ]
kelvin-onlabfb521662015-02-27 09:52:40 -08001419 else:
1420 main.log.error( "Error, intent ID not found" )
Jon Hall61282e32015-03-19 11:34:11 -07001421 main.log.debug( "Response from ONOS was: " +
1422 repr( handle ) )
kelvin-onlabfb521662015-02-27 09:52:40 -08001423 return None
Jon Hallc6793552016-01-19 14:18:37 -08001424 except AssertionError:
1425 main.log.exception( "" )
1426 return None
Jon Halld4d4b372015-01-28 16:02:41 -08001427 except TypeError:
1428 main.log.exception( self.name + ": Object not as expected" )
1429 return None
andrewonlabe6745342014-10-17 14:29:13 -04001430 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08001431 main.log.error( self.name + ": EOF exception found" )
1432 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001433 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -08001434 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -08001435 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001436 main.cleanAndExit()
andrewonlabe6745342014-10-17 14:29:13 -04001437
kelvin-onlabd3b64892015-01-20 13:26:24 -08001438 def addOpticalIntent( self, ingressDevice, egressDevice ):
kelvin8ec71442015-01-15 16:57:00 -08001439 """
andrewonlab7b31d232014-10-24 13:31:47 -04001440 Required:
kelvin-onlabd3b64892015-01-20 13:26:24 -08001441 * ingressDevice: device id of ingress device
1442 * egressDevice: device id of egress device
andrewonlab7b31d232014-10-24 13:31:47 -04001443 Optional:
1444 TODO: Still needs to be implemented via dev side
kelvin-onlabfb521662015-02-27 09:52:40 -08001445 Description:
1446 Adds an optical intent by specifying an ingress and egress device
1447 Returns:
1448 A string of the intent id or None on error
kelvin-onlab898a6c62015-01-16 14:13:53 -08001449 """
andrewonlab7b31d232014-10-24 13:31:47 -04001450 try:
kelvin-onlabd3b64892015-01-20 13:26:24 -08001451 cmdStr = "add-optical-intent " + str( ingressDevice ) +\
1452 " " + str( egressDevice )
1453 handle = self.sendline( cmdStr )
You Wangb5a55f72017-03-03 12:51:05 -08001454 assert handle is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08001455 assert "Command not found:" not in handle, handle
kelvin-onlab898a6c62015-01-16 14:13:53 -08001456 # If error, return error message
Jon Halle3f39ff2015-01-13 11:50:53 -08001457 if re.search( "Error", handle ):
Jon Hall0e240372018-05-02 11:21:57 -07001458 main.log.error( self.name + ": Error in adding Optical intent" )
kelvin-onlabfb521662015-02-27 09:52:40 -08001459 return None
andrewonlab7b31d232014-10-24 13:31:47 -04001460 else:
kelvin-onlabfb521662015-02-27 09:52:40 -08001461 main.log.info( "Optical intent installed between " +
1462 str( ingressDevice ) + " and " +
1463 str( egressDevice ) )
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001464 match = re.search( 'id=0x([\da-f]+),', handle )
kelvin-onlabfb521662015-02-27 09:52:40 -08001465 if match:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001466 return match.group()[ 3:-1 ]
kelvin-onlabfb521662015-02-27 09:52:40 -08001467 else:
1468 main.log.error( "Error, intent ID not found" )
1469 return None
Jon Hallc6793552016-01-19 14:18:37 -08001470 except AssertionError:
1471 main.log.exception( "" )
1472 return None
Jon Halld4d4b372015-01-28 16:02:41 -08001473 except TypeError:
1474 main.log.exception( self.name + ": Object not as expected" )
1475 return None
andrewonlab7b31d232014-10-24 13:31:47 -04001476 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08001477 main.log.error( self.name + ": EOF exception found" )
1478 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001479 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -08001480 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -08001481 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001482 main.cleanAndExit()
andrewonlab7b31d232014-10-24 13:31:47 -04001483
kelvin-onlabd3b64892015-01-20 13:26:24 -08001484 def addPointIntent(
kelvin-onlab898a6c62015-01-16 14:13:53 -08001485 self,
kelvin-onlabd3b64892015-01-20 13:26:24 -08001486 ingressDevice,
1487 egressDevice,
1488 portIngress="",
1489 portEgress="",
kelvin-onlab898a6c62015-01-16 14:13:53 -08001490 ethType="",
1491 ethSrc="",
1492 ethDst="",
1493 bandwidth="",
kelvin-onlabd3b64892015-01-20 13:26:24 -08001494 lambdaAlloc=False,
alisonda157272016-12-22 01:13:21 -08001495 protected=False,
kelvin-onlab898a6c62015-01-16 14:13:53 -08001496 ipProto="",
1497 ipSrc="",
1498 ipDst="",
1499 tcpSrc="",
Jeremy Songster832f9e92016-05-05 14:30:49 -07001500 tcpDst="",
Jeremy Songsterff553672016-05-12 17:06:23 -07001501 vlanId="",
Jeremy Songsterc032f162016-08-04 17:14:49 -07001502 setVlan="",
1503 encap="" ):
kelvin8ec71442015-01-15 16:57:00 -08001504 """
andrewonlab4dbb4d82014-10-17 18:22:31 -04001505 Required:
kelvin-onlabd3b64892015-01-20 13:26:24 -08001506 * ingressDevice: device id of ingress device
1507 * egressDevice: device id of egress device
andrewonlab289e4b72014-10-21 21:24:18 -04001508 Optional:
1509 * ethType: specify ethType
kelvin8ec71442015-01-15 16:57:00 -08001510 * ethSrc: specify ethSrc ( i.e. src mac addr )
1511 * ethDst: specify ethDst ( i.e. dst mac addr )
andrewonlab0dbb6ec2014-11-06 13:46:55 -05001512 * bandwidth: specify bandwidth capacity of link
kelvin-onlabd3b64892015-01-20 13:26:24 -08001513 * lambdaAlloc: if True, intent will allocate lambda
andrewonlab40ccd8b2014-11-06 16:23:34 -05001514 for the specified intent
Jon Halle3f39ff2015-01-13 11:50:53 -08001515 * ipProto: specify ip protocol
andrewonlabf77e0cb2014-11-11 17:17:59 -05001516 * ipSrc: specify ip source address
1517 * ipDst: specify ip destination address
1518 * tcpSrc: specify tcp source port
1519 * tcpDst: specify tcp destination port
Jeremy Songster832f9e92016-05-05 14:30:49 -07001520 * vlanId: specify vlan ID
Jeremy Songsterff553672016-05-12 17:06:23 -07001521 * setVlan: specify a VLAN id treatment
Jeremy Songsterc032f162016-08-04 17:14:49 -07001522 * encap: specify an Encapsulation type to use
andrewonlab4dbb4d82014-10-17 18:22:31 -04001523 Description:
kelvin8ec71442015-01-15 16:57:00 -08001524 Adds a point-to-point intent ( uni-directional ) by
andrewonlab289e4b72014-10-21 21:24:18 -04001525 specifying device id's and optional fields
kelvin-onlabfb521662015-02-27 09:52:40 -08001526 Returns:
1527 A string of the intent id or None on error
andrewonlab289e4b72014-10-21 21:24:18 -04001528
Jon Halle3f39ff2015-01-13 11:50:53 -08001529 NOTE: This function may change depending on the
andrewonlab4dbb4d82014-10-17 18:22:31 -04001530 options developers provide for point-to-point
1531 intent via cli
kelvin8ec71442015-01-15 16:57:00 -08001532 """
andrewonlab4dbb4d82014-10-17 18:22:31 -04001533 try:
Jeremy Songsterff553672016-05-12 17:06:23 -07001534 cmd = "add-point-intent"
andrewonlab36af3822014-11-18 17:48:18 -05001535
Jeremy Songsterff553672016-05-12 17:06:23 -07001536 if ethType:
1537 cmd += " --ethType " + str( ethType )
1538 if ethSrc:
1539 cmd += " --ethSrc " + str( ethSrc )
1540 if ethDst:
1541 cmd += " --ethDst " + str( ethDst )
1542 if bandwidth:
1543 cmd += " --bandwidth " + str( bandwidth )
1544 if lambdaAlloc:
1545 cmd += " --lambda "
1546 if ipProto:
1547 cmd += " --ipProto " + str( ipProto )
1548 if ipSrc:
1549 cmd += " --ipSrc " + str( ipSrc )
1550 if ipDst:
1551 cmd += " --ipDst " + str( ipDst )
1552 if tcpSrc:
1553 cmd += " --tcpSrc " + str( tcpSrc )
1554 if tcpDst:
1555 cmd += " --tcpDst " + str( tcpDst )
1556 if vlanId:
1557 cmd += " -v " + str( vlanId )
1558 if setVlan:
1559 cmd += " --setVlan " + str( setVlan )
Jeremy Songsterc032f162016-08-04 17:14:49 -07001560 if encap:
1561 cmd += " --encapsulation " + str( encap )
alisonda157272016-12-22 01:13:21 -08001562 if protected:
1563 cmd += " --protect "
andrewonlab289e4b72014-10-21 21:24:18 -04001564
kelvin8ec71442015-01-15 16:57:00 -08001565 # Check whether the user appended the port
1566 # or provided it as an input
kelvin-onlabd3b64892015-01-20 13:26:24 -08001567 if "/" in ingressDevice:
1568 cmd += " " + str( ingressDevice )
andrewonlab36af3822014-11-18 17:48:18 -05001569 else:
kelvin-onlabd3b64892015-01-20 13:26:24 -08001570 if not portIngress:
kelvin-onlabfb521662015-02-27 09:52:40 -08001571 main.log.error( "You must specify the ingress port" )
kelvin8ec71442015-01-15 16:57:00 -08001572 # TODO: perhaps more meaningful return
kelvin-onlabfb521662015-02-27 09:52:40 -08001573 # Would it make sense to throw an exception and exit
1574 # the test?
1575 return None
andrewonlab36af3822014-11-18 17:48:18 -05001576
kelvin8ec71442015-01-15 16:57:00 -08001577 cmd += " " + \
kelvin-onlabd3b64892015-01-20 13:26:24 -08001578 str( ingressDevice ) + "/" +\
1579 str( portIngress ) + " "
andrewonlab36af3822014-11-18 17:48:18 -05001580
kelvin-onlabd3b64892015-01-20 13:26:24 -08001581 if "/" in egressDevice:
1582 cmd += " " + str( egressDevice )
andrewonlab36af3822014-11-18 17:48:18 -05001583 else:
kelvin-onlabd3b64892015-01-20 13:26:24 -08001584 if not portEgress:
kelvin-onlabfb521662015-02-27 09:52:40 -08001585 main.log.error( "You must specify the egress port" )
1586 return None
Jon Halle3f39ff2015-01-13 11:50:53 -08001587
kelvin8ec71442015-01-15 16:57:00 -08001588 cmd += " " +\
kelvin-onlabd3b64892015-01-20 13:26:24 -08001589 str( egressDevice ) + "/" +\
1590 str( portEgress )
kelvin8ec71442015-01-15 16:57:00 -08001591
kelvin-onlab898a6c62015-01-16 14:13:53 -08001592 handle = self.sendline( cmd )
You Wangb5a55f72017-03-03 12:51:05 -08001593 assert handle is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08001594 assert "Command not found:" not in handle, handle
kelvin-onlabfb521662015-02-27 09:52:40 -08001595 # If error, return error message
kelvin-onlab898a6c62015-01-16 14:13:53 -08001596 if re.search( "Error", handle ):
Jon Hall0e240372018-05-02 11:21:57 -07001597 main.log.error( self.name + ": Error in adding point-to-point intent" )
kelvin-onlabfb521662015-02-27 09:52:40 -08001598 return None
andrewonlab4dbb4d82014-10-17 18:22:31 -04001599 else:
kelvin-onlabfb521662015-02-27 09:52:40 -08001600 # TODO: print out all the options in this message?
1601 main.log.info( "Point-to-point intent installed between " +
1602 str( ingressDevice ) + " and " +
1603 str( egressDevice ) )
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001604 match = re.search( 'id=0x([\da-f]+),', handle )
kelvin-onlabfb521662015-02-27 09:52:40 -08001605 if match:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001606 return match.group()[ 3:-1 ]
kelvin-onlabfb521662015-02-27 09:52:40 -08001607 else:
1608 main.log.error( "Error, intent ID not found" )
1609 return None
Jon Hallc6793552016-01-19 14:18:37 -08001610 except AssertionError:
1611 main.log.exception( "" )
1612 return None
Jon Halld4d4b372015-01-28 16:02:41 -08001613 except TypeError:
1614 main.log.exception( self.name + ": Object not as expected" )
1615 return None
andrewonlab4dbb4d82014-10-17 18:22:31 -04001616 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08001617 main.log.error( self.name + ": EOF exception found" )
1618 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001619 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -08001620 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -08001621 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001622 main.cleanAndExit()
andrewonlab4dbb4d82014-10-17 18:22:31 -04001623
kelvin-onlabd3b64892015-01-20 13:26:24 -08001624 def addMultipointToSinglepointIntent(
kelvin-onlab898a6c62015-01-16 14:13:53 -08001625 self,
shahshreyac2f97072015-03-19 17:04:29 -07001626 ingressDeviceList,
kelvin-onlabd3b64892015-01-20 13:26:24 -08001627 egressDevice,
shahshreyac2f97072015-03-19 17:04:29 -07001628 portIngressList=None,
kelvin-onlabd3b64892015-01-20 13:26:24 -08001629 portEgress="",
kelvin-onlab898a6c62015-01-16 14:13:53 -08001630 ethType="",
1631 ethSrc="",
1632 ethDst="",
1633 bandwidth="",
kelvin-onlabd3b64892015-01-20 13:26:24 -08001634 lambdaAlloc=False,
kelvin-onlab898a6c62015-01-16 14:13:53 -08001635 ipProto="",
1636 ipSrc="",
1637 ipDst="",
1638 tcpSrc="",
1639 tcpDst="",
1640 setEthSrc="",
Jeremy Songster832f9e92016-05-05 14:30:49 -07001641 setEthDst="",
Jeremy Songsterff553672016-05-12 17:06:23 -07001642 vlanId="",
Jeremy Songster9385d412016-06-02 17:57:36 -07001643 setVlan="",
Jeremy Songsterc032f162016-08-04 17:14:49 -07001644 partial=False,
1645 encap="" ):
kelvin8ec71442015-01-15 16:57:00 -08001646 """
shahshreyad0c80432014-12-04 16:56:05 -08001647 Note:
shahshreya70622b12015-03-19 17:19:00 -07001648 This function assumes the format of all ingress devices
Jon Hallbe379602015-03-24 13:39:32 -07001649 is same. That is, all ingress devices include port numbers
1650 with a "/" or all ingress devices could specify device
1651 ids and port numbers seperately.
shahshreyad0c80432014-12-04 16:56:05 -08001652 Required:
Jon Hallbe379602015-03-24 13:39:32 -07001653 * ingressDeviceList: List of device ids of ingress device
shahshreyac2f97072015-03-19 17:04:29 -07001654 ( Atleast 2 ingress devices required in the list )
kelvin-onlabd3b64892015-01-20 13:26:24 -08001655 * egressDevice: device id of egress device
shahshreyad0c80432014-12-04 16:56:05 -08001656 Optional:
1657 * ethType: specify ethType
kelvin8ec71442015-01-15 16:57:00 -08001658 * ethSrc: specify ethSrc ( i.e. src mac addr )
1659 * ethDst: specify ethDst ( i.e. dst mac addr )
shahshreyad0c80432014-12-04 16:56:05 -08001660 * bandwidth: specify bandwidth capacity of link
kelvin-onlabd3b64892015-01-20 13:26:24 -08001661 * lambdaAlloc: if True, intent will allocate lambda
shahshreyad0c80432014-12-04 16:56:05 -08001662 for the specified intent
Jon Halle3f39ff2015-01-13 11:50:53 -08001663 * ipProto: specify ip protocol
shahshreyad0c80432014-12-04 16:56:05 -08001664 * ipSrc: specify ip source address
1665 * ipDst: specify ip destination address
1666 * tcpSrc: specify tcp source port
1667 * tcpDst: specify tcp destination port
1668 * setEthSrc: action to Rewrite Source MAC Address
1669 * setEthDst: action to Rewrite Destination MAC Address
Jeremy Songster832f9e92016-05-05 14:30:49 -07001670 * vlanId: specify vlan Id
Jeremy Songsterff553672016-05-12 17:06:23 -07001671 * setVlan: specify VLAN Id treatment
Jeremy Songsterc032f162016-08-04 17:14:49 -07001672 * encap: specify a type of encapsulation
shahshreyad0c80432014-12-04 16:56:05 -08001673 Description:
kelvin8ec71442015-01-15 16:57:00 -08001674 Adds a multipoint-to-singlepoint intent ( uni-directional ) by
shahshreyad0c80432014-12-04 16:56:05 -08001675 specifying device id's and optional fields
kelvin-onlabfb521662015-02-27 09:52:40 -08001676 Returns:
1677 A string of the intent id or None on error
shahshreyad0c80432014-12-04 16:56:05 -08001678
Jon Halle3f39ff2015-01-13 11:50:53 -08001679 NOTE: This function may change depending on the
Jon Hallefbd9792015-03-05 16:11:36 -08001680 options developers provide for multipoint-to-singlepoint
shahshreyad0c80432014-12-04 16:56:05 -08001681 intent via cli
kelvin8ec71442015-01-15 16:57:00 -08001682 """
shahshreyad0c80432014-12-04 16:56:05 -08001683 try:
Jeremy Songsterff553672016-05-12 17:06:23 -07001684 cmd = "add-multi-to-single-intent"
shahshreyad0c80432014-12-04 16:56:05 -08001685
Jeremy Songsterff553672016-05-12 17:06:23 -07001686 if ethType:
1687 cmd += " --ethType " + str( ethType )
1688 if ethSrc:
1689 cmd += " --ethSrc " + str( ethSrc )
1690 if ethDst:
1691 cmd += " --ethDst " + str( ethDst )
1692 if bandwidth:
1693 cmd += " --bandwidth " + str( bandwidth )
1694 if lambdaAlloc:
1695 cmd += " --lambda "
1696 if ipProto:
1697 cmd += " --ipProto " + str( ipProto )
1698 if ipSrc:
1699 cmd += " --ipSrc " + str( ipSrc )
1700 if ipDst:
1701 cmd += " --ipDst " + str( ipDst )
1702 if tcpSrc:
1703 cmd += " --tcpSrc " + str( tcpSrc )
1704 if tcpDst:
1705 cmd += " --tcpDst " + str( tcpDst )
1706 if setEthSrc:
1707 cmd += " --setEthSrc " + str( setEthSrc )
1708 if setEthDst:
1709 cmd += " --setEthDst " + str( setEthDst )
1710 if vlanId:
1711 cmd += " -v " + str( vlanId )
1712 if setVlan:
1713 cmd += " --setVlan " + str( setVlan )
Jeremy Songster9385d412016-06-02 17:57:36 -07001714 if partial:
1715 cmd += " --partial"
Jeremy Songsterc032f162016-08-04 17:14:49 -07001716 if encap:
1717 cmd += " --encapsulation " + str( encap )
shahshreyad0c80432014-12-04 16:56:05 -08001718
kelvin8ec71442015-01-15 16:57:00 -08001719 # Check whether the user appended the port
1720 # or provided it as an input
shahshreyac2f97072015-03-19 17:04:29 -07001721
1722 if portIngressList is None:
1723 for ingressDevice in ingressDeviceList:
1724 if "/" in ingressDevice:
1725 cmd += " " + str( ingressDevice )
1726 else:
1727 main.log.error( "You must specify " +
Jon Hallbe379602015-03-24 13:39:32 -07001728 "the ingress port" )
shahshreyac2f97072015-03-19 17:04:29 -07001729 # TODO: perhaps more meaningful return
1730 return main.FALSE
shahshreyad0c80432014-12-04 16:56:05 -08001731 else:
Jon Hall71ce4e72015-03-23 14:05:58 -07001732 if len( ingressDeviceList ) == len( portIngressList ):
Jon Hall08f61bc2015-04-13 16:00:30 -07001733 for ingressDevice, portIngress in zip( ingressDeviceList,
1734 portIngressList ):
shahshreya70622b12015-03-19 17:19:00 -07001735 cmd += " " + \
1736 str( ingressDevice ) + "/" +\
1737 str( portIngress ) + " "
kelvin-onlab38143812015-04-01 15:03:01 -07001738 else:
Jon Hall08f61bc2015-04-13 16:00:30 -07001739 main.log.error( "Device list and port list does not " +
1740 "have the same length" )
kelvin-onlab38143812015-04-01 15:03:01 -07001741 return main.FALSE
kelvin-onlabd3b64892015-01-20 13:26:24 -08001742 if "/" in egressDevice:
1743 cmd += " " + str( egressDevice )
shahshreyad0c80432014-12-04 16:56:05 -08001744 else:
kelvin-onlabd3b64892015-01-20 13:26:24 -08001745 if not portEgress:
kelvin8ec71442015-01-15 16:57:00 -08001746 main.log.error( "You must specify " +
1747 "the egress port" )
shahshreyad0c80432014-12-04 16:56:05 -08001748 return main.FALSE
Jon Halle3f39ff2015-01-13 11:50:53 -08001749
kelvin8ec71442015-01-15 16:57:00 -08001750 cmd += " " +\
kelvin-onlabd3b64892015-01-20 13:26:24 -08001751 str( egressDevice ) + "/" +\
1752 str( portEgress )
kelvin-onlab898a6c62015-01-16 14:13:53 -08001753 handle = self.sendline( cmd )
You Wangb5a55f72017-03-03 12:51:05 -08001754 assert handle is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08001755 assert "Command not found:" not in handle, handle
kelvin-onlabfb521662015-02-27 09:52:40 -08001756 # If error, return error message
kelvin-onlab898a6c62015-01-16 14:13:53 -08001757 if re.search( "Error", handle ):
Jon Hall0e240372018-05-02 11:21:57 -07001758 main.log.error( self.name + ": Error in adding multipoint-to-singlepoint " +
kelvin-onlabfb521662015-02-27 09:52:40 -08001759 "intent" )
1760 return None
shahshreyad0c80432014-12-04 16:56:05 -08001761 else:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001762 match = re.search( 'id=0x([\da-f]+),', handle )
kelvin-onlabb9408212015-04-01 13:34:04 -07001763 if match:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001764 return match.group()[ 3:-1 ]
kelvin-onlabb9408212015-04-01 13:34:04 -07001765 else:
1766 main.log.error( "Error, intent ID not found" )
1767 return None
Jon Hallc6793552016-01-19 14:18:37 -08001768 except AssertionError:
1769 main.log.exception( "" )
1770 return None
kelvin-onlabb9408212015-04-01 13:34:04 -07001771 except TypeError:
1772 main.log.exception( self.name + ": Object not as expected" )
1773 return None
1774 except pexpect.EOF:
1775 main.log.error( self.name + ": EOF exception found" )
1776 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001777 main.cleanAndExit()
kelvin-onlabb9408212015-04-01 13:34:04 -07001778 except Exception:
1779 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001780 main.cleanAndExit()
kelvin-onlabb9408212015-04-01 13:34:04 -07001781
1782 def addSinglepointToMultipointIntent(
1783 self,
1784 ingressDevice,
1785 egressDeviceList,
1786 portIngress="",
1787 portEgressList=None,
1788 ethType="",
1789 ethSrc="",
1790 ethDst="",
1791 bandwidth="",
1792 lambdaAlloc=False,
1793 ipProto="",
1794 ipSrc="",
1795 ipDst="",
1796 tcpSrc="",
1797 tcpDst="",
1798 setEthSrc="",
Jeremy Songster832f9e92016-05-05 14:30:49 -07001799 setEthDst="",
Jeremy Songsterff553672016-05-12 17:06:23 -07001800 vlanId="",
Jeremy Songster9385d412016-06-02 17:57:36 -07001801 setVlan="",
Jeremy Songsterc032f162016-08-04 17:14:49 -07001802 partial=False,
1803 encap="" ):
kelvin-onlabb9408212015-04-01 13:34:04 -07001804 """
1805 Note:
1806 This function assumes the format of all egress devices
1807 is same. That is, all egress devices include port numbers
1808 with a "/" or all egress devices could specify device
1809 ids and port numbers seperately.
1810 Required:
1811 * EgressDeviceList: List of device ids of egress device
1812 ( Atleast 2 eress devices required in the list )
1813 * ingressDevice: device id of ingress device
1814 Optional:
1815 * ethType: specify ethType
1816 * ethSrc: specify ethSrc ( i.e. src mac addr )
1817 * ethDst: specify ethDst ( i.e. dst mac addr )
1818 * bandwidth: specify bandwidth capacity of link
1819 * lambdaAlloc: if True, intent will allocate lambda
1820 for the specified intent
1821 * ipProto: specify ip protocol
1822 * ipSrc: specify ip source address
1823 * ipDst: specify ip destination address
1824 * tcpSrc: specify tcp source port
1825 * tcpDst: specify tcp destination port
1826 * setEthSrc: action to Rewrite Source MAC Address
1827 * setEthDst: action to Rewrite Destination MAC Address
Jeremy Songster832f9e92016-05-05 14:30:49 -07001828 * vlanId: specify vlan Id
Jeremy Songsterff553672016-05-12 17:06:23 -07001829 * setVlan: specify VLAN ID treatment
Jeremy Songsterc032f162016-08-04 17:14:49 -07001830 * encap: specify an encapsulation type
kelvin-onlabb9408212015-04-01 13:34:04 -07001831 Description:
1832 Adds a singlepoint-to-multipoint intent ( uni-directional ) by
1833 specifying device id's and optional fields
1834 Returns:
1835 A string of the intent id or None on error
1836
1837 NOTE: This function may change depending on the
1838 options developers provide for singlepoint-to-multipoint
1839 intent via cli
1840 """
1841 try:
Jeremy Songsterff553672016-05-12 17:06:23 -07001842 cmd = "add-single-to-multi-intent"
kelvin-onlabb9408212015-04-01 13:34:04 -07001843
Jeremy Songsterff553672016-05-12 17:06:23 -07001844 if ethType:
1845 cmd += " --ethType " + str( ethType )
1846 if ethSrc:
1847 cmd += " --ethSrc " + str( ethSrc )
1848 if ethDst:
1849 cmd += " --ethDst " + str( ethDst )
1850 if bandwidth:
1851 cmd += " --bandwidth " + str( bandwidth )
1852 if lambdaAlloc:
1853 cmd += " --lambda "
1854 if ipProto:
1855 cmd += " --ipProto " + str( ipProto )
1856 if ipSrc:
1857 cmd += " --ipSrc " + str( ipSrc )
1858 if ipDst:
1859 cmd += " --ipDst " + str( ipDst )
1860 if tcpSrc:
1861 cmd += " --tcpSrc " + str( tcpSrc )
1862 if tcpDst:
1863 cmd += " --tcpDst " + str( tcpDst )
1864 if setEthSrc:
1865 cmd += " --setEthSrc " + str( setEthSrc )
1866 if setEthDst:
1867 cmd += " --setEthDst " + str( setEthDst )
1868 if vlanId:
1869 cmd += " -v " + str( vlanId )
1870 if setVlan:
1871 cmd += " --setVlan " + str( setVlan )
Jeremy Songster9385d412016-06-02 17:57:36 -07001872 if partial:
1873 cmd += " --partial"
Jeremy Songsterc032f162016-08-04 17:14:49 -07001874 if encap:
1875 cmd += " --encapsulation " + str( encap )
kelvin-onlabb9408212015-04-01 13:34:04 -07001876
1877 # Check whether the user appended the port
1878 # or provided it as an input
Jon Hall08f61bc2015-04-13 16:00:30 -07001879
kelvin-onlabb9408212015-04-01 13:34:04 -07001880 if "/" in ingressDevice:
1881 cmd += " " + str( ingressDevice )
1882 else:
1883 if not portIngress:
1884 main.log.error( "You must specify " +
1885 "the Ingress port" )
1886 return main.FALSE
1887
1888 cmd += " " +\
1889 str( ingressDevice ) + "/" +\
1890 str( portIngress )
1891
1892 if portEgressList is None:
1893 for egressDevice in egressDeviceList:
1894 if "/" in egressDevice:
1895 cmd += " " + str( egressDevice )
1896 else:
1897 main.log.error( "You must specify " +
1898 "the egress port" )
1899 # TODO: perhaps more meaningful return
1900 return main.FALSE
1901 else:
1902 if len( egressDeviceList ) == len( portEgressList ):
Jon Hall08f61bc2015-04-13 16:00:30 -07001903 for egressDevice, portEgress in zip( egressDeviceList,
1904 portEgressList ):
kelvin-onlabb9408212015-04-01 13:34:04 -07001905 cmd += " " + \
1906 str( egressDevice ) + "/" +\
1907 str( portEgress )
kelvin-onlab38143812015-04-01 15:03:01 -07001908 else:
Jon Hall08f61bc2015-04-13 16:00:30 -07001909 main.log.error( "Device list and port list does not " +
1910 "have the same length" )
kelvin-onlab38143812015-04-01 15:03:01 -07001911 return main.FALSE
kelvin-onlabb9408212015-04-01 13:34:04 -07001912 handle = self.sendline( cmd )
You Wangb5a55f72017-03-03 12:51:05 -08001913 assert handle is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08001914 assert "Command not found:" not in handle, handle
kelvin-onlabb9408212015-04-01 13:34:04 -07001915 # If error, return error message
1916 if re.search( "Error", handle ):
Jon Hall0e240372018-05-02 11:21:57 -07001917 main.log.error( self.name + ": Error in adding singlepoint-to-multipoint " +
kelvin-onlabb9408212015-04-01 13:34:04 -07001918 "intent" )
shahshreyac2f97072015-03-19 17:04:29 -07001919 return None
kelvin-onlabb9408212015-04-01 13:34:04 -07001920 else:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001921 match = re.search( 'id=0x([\da-f]+),', handle )
kelvin-onlabb9408212015-04-01 13:34:04 -07001922 if match:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001923 return match.group()[ 3:-1 ]
kelvin-onlabb9408212015-04-01 13:34:04 -07001924 else:
1925 main.log.error( "Error, intent ID not found" )
1926 return None
Jon Hallc6793552016-01-19 14:18:37 -08001927 except AssertionError:
1928 main.log.exception( "" )
1929 return None
Jon Halld4d4b372015-01-28 16:02:41 -08001930 except TypeError:
1931 main.log.exception( self.name + ": Object not as expected" )
1932 return None
shahshreyad0c80432014-12-04 16:56:05 -08001933 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08001934 main.log.error( self.name + ": EOF exception found" )
1935 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001936 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -08001937 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -08001938 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001939 main.cleanAndExit()
shahshreyad0c80432014-12-04 16:56:05 -08001940
Hari Krishna9e232602015-04-13 17:29:08 -07001941 def addMplsIntent(
1942 self,
1943 ingressDevice,
1944 egressDevice,
Hari Krishna87a17f12015-04-13 17:42:23 -07001945 ingressPort="",
1946 egressPort="",
Hari Krishna9e232602015-04-13 17:29:08 -07001947 ethType="",
1948 ethSrc="",
1949 ethDst="",
1950 bandwidth="",
1951 lambdaAlloc=False,
1952 ipProto="",
1953 ipSrc="",
1954 ipDst="",
1955 tcpSrc="",
1956 tcpDst="",
Hari Krishna87a17f12015-04-13 17:42:23 -07001957 ingressLabel="",
Hari Krishnadfff6672015-04-13 17:53:27 -07001958 egressLabel="",
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001959 priority="" ):
Hari Krishna9e232602015-04-13 17:29:08 -07001960 """
1961 Required:
1962 * ingressDevice: device id of ingress device
1963 * egressDevice: device id of egress device
1964 Optional:
1965 * ethType: specify ethType
1966 * ethSrc: specify ethSrc ( i.e. src mac addr )
1967 * ethDst: specify ethDst ( i.e. dst mac addr )
1968 * bandwidth: specify bandwidth capacity of link
1969 * lambdaAlloc: if True, intent will allocate lambda
1970 for the specified intent
1971 * ipProto: specify ip protocol
1972 * ipSrc: specify ip source address
1973 * ipDst: specify ip destination address
1974 * tcpSrc: specify tcp source port
1975 * tcpDst: specify tcp destination port
1976 * ingressLabel: Ingress MPLS label
1977 * egressLabel: Egress MPLS label
1978 Description:
1979 Adds MPLS intent by
1980 specifying device id's and optional fields
1981 Returns:
1982 A string of the intent id or None on error
1983
1984 NOTE: This function may change depending on the
1985 options developers provide for MPLS
1986 intent via cli
1987 """
1988 try:
Jeremy Songsterff553672016-05-12 17:06:23 -07001989 cmd = "add-mpls-intent"
Hari Krishna9e232602015-04-13 17:29:08 -07001990
Jeremy Songsterff553672016-05-12 17:06:23 -07001991 if ethType:
1992 cmd += " --ethType " + str( ethType )
1993 if ethSrc:
1994 cmd += " --ethSrc " + str( ethSrc )
1995 if ethDst:
1996 cmd += " --ethDst " + str( ethDst )
1997 if bandwidth:
1998 cmd += " --bandwidth " + str( bandwidth )
1999 if lambdaAlloc:
2000 cmd += " --lambda "
2001 if ipProto:
2002 cmd += " --ipProto " + str( ipProto )
2003 if ipSrc:
2004 cmd += " --ipSrc " + str( ipSrc )
2005 if ipDst:
2006 cmd += " --ipDst " + str( ipDst )
2007 if tcpSrc:
2008 cmd += " --tcpSrc " + str( tcpSrc )
2009 if tcpDst:
2010 cmd += " --tcpDst " + str( tcpDst )
2011 if ingressLabel:
2012 cmd += " --ingressLabel " + str( ingressLabel )
2013 if egressLabel:
2014 cmd += " --egressLabel " + str( egressLabel )
2015 if priority:
2016 cmd += " --priority " + str( priority )
Hari Krishna9e232602015-04-13 17:29:08 -07002017
2018 # Check whether the user appended the port
2019 # or provided it as an input
2020 if "/" in ingressDevice:
2021 cmd += " " + str( ingressDevice )
2022 else:
Hari Krishna87a17f12015-04-13 17:42:23 -07002023 if not ingressPort:
Hari Krishna9e232602015-04-13 17:29:08 -07002024 main.log.error( "You must specify the ingress port" )
2025 return None
2026
2027 cmd += " " + \
2028 str( ingressDevice ) + "/" +\
Hari Krishna87a17f12015-04-13 17:42:23 -07002029 str( ingressPort ) + " "
Hari Krishna9e232602015-04-13 17:29:08 -07002030
2031 if "/" in egressDevice:
2032 cmd += " " + str( egressDevice )
2033 else:
Hari Krishna87a17f12015-04-13 17:42:23 -07002034 if not egressPort:
Hari Krishna9e232602015-04-13 17:29:08 -07002035 main.log.error( "You must specify the egress port" )
2036 return None
2037
2038 cmd += " " +\
2039 str( egressDevice ) + "/" +\
Hari Krishna87a17f12015-04-13 17:42:23 -07002040 str( egressPort )
Hari Krishna9e232602015-04-13 17:29:08 -07002041
2042 handle = self.sendline( cmd )
You Wangb5a55f72017-03-03 12:51:05 -08002043 assert handle is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08002044 assert "Command not found:" not in handle, handle
Hari Krishna9e232602015-04-13 17:29:08 -07002045 # If error, return error message
2046 if re.search( "Error", handle ):
Jon Hall0e240372018-05-02 11:21:57 -07002047 main.log.error( self.name + ": Error in adding mpls intent" )
Hari Krishna9e232602015-04-13 17:29:08 -07002048 return None
2049 else:
2050 # TODO: print out all the options in this message?
2051 main.log.info( "MPLS intent installed between " +
2052 str( ingressDevice ) + " and " +
2053 str( egressDevice ) )
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002054 match = re.search( 'id=0x([\da-f]+),', handle )
Hari Krishna9e232602015-04-13 17:29:08 -07002055 if match:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002056 return match.group()[ 3:-1 ]
Hari Krishna9e232602015-04-13 17:29:08 -07002057 else:
2058 main.log.error( "Error, intent ID not found" )
2059 return None
Jon Hallc6793552016-01-19 14:18:37 -08002060 except AssertionError:
2061 main.log.exception( "" )
2062 return None
Hari Krishna9e232602015-04-13 17:29:08 -07002063 except TypeError:
2064 main.log.exception( self.name + ": Object not as expected" )
2065 return None
2066 except pexpect.EOF:
2067 main.log.error( self.name + ": EOF exception found" )
2068 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002069 main.cleanAndExit()
Hari Krishna9e232602015-04-13 17:29:08 -07002070 except Exception:
2071 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002072 main.cleanAndExit()
Hari Krishna9e232602015-04-13 17:29:08 -07002073
Jon Hallefbd9792015-03-05 16:11:36 -08002074 def removeIntent( self, intentId, app='org.onosproject.cli',
2075 purge=False, sync=False ):
kelvin-onlab898a6c62015-01-16 14:13:53 -08002076 """
shahshreya1c818fc2015-02-26 13:44:08 -08002077 Remove intent for specified application id and intent id
Jon Hall61282e32015-03-19 11:34:11 -07002078 Optional args:-
shahshreya1c818fc2015-02-26 13:44:08 -08002079 -s or --sync: Waits for the removal before returning
Jon Hall61282e32015-03-19 11:34:11 -07002080 -p or --purge: Purge the intent from the store after removal
2081
Jon Halle3f39ff2015-01-13 11:50:53 -08002082 Returns:
Jon Hall6509dbf2016-06-21 17:01:17 -07002083 main.FALSE on error and
Jon Halle3f39ff2015-01-13 11:50:53 -08002084 cli output otherwise
kelvin-onlab898a6c62015-01-16 14:13:53 -08002085 """
andrewonlab9a50dfe2014-10-17 17:22:31 -04002086 try:
Jon Hallc6358dd2015-04-10 12:44:28 -07002087 cmdStr = "remove-intent"
shahshreya1c818fc2015-02-26 13:44:08 -08002088 if purge:
2089 cmdStr += " -p"
2090 if sync:
2091 cmdStr += " -s"
2092
2093 cmdStr += " " + app + " " + str( intentId )
kelvin-onlabd3b64892015-01-20 13:26:24 -08002094 handle = self.sendline( cmdStr )
You Wangb5a55f72017-03-03 12:51:05 -08002095 assert handle is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08002096 assert "Command not found:" not in handle, handle
Jon Halle3f39ff2015-01-13 11:50:53 -08002097 if re.search( "Error", handle ):
Jon Hall0e240372018-05-02 11:21:57 -07002098 main.log.error( self.name + ": Error in removing intent" )
Jon Halle3f39ff2015-01-13 11:50:53 -08002099 return main.FALSE
andrewonlab9a50dfe2014-10-17 17:22:31 -04002100 else:
Jon Halle3f39ff2015-01-13 11:50:53 -08002101 # TODO: Should this be main.TRUE
2102 return handle
Jon Hallc6793552016-01-19 14:18:37 -08002103 except AssertionError:
2104 main.log.exception( "" )
2105 return None
Jon Halld4d4b372015-01-28 16:02:41 -08002106 except TypeError:
2107 main.log.exception( self.name + ": Object not as expected" )
2108 return None
andrewonlab9a50dfe2014-10-17 17:22:31 -04002109 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08002110 main.log.error( self.name + ": EOF exception found" )
2111 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002112 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -08002113 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -08002114 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002115 main.cleanAndExit()
andrewonlab9a50dfe2014-10-17 17:22:31 -04002116
YPZhangfebf7302016-05-24 16:45:56 -07002117 def removeAllIntents( self, purge=False, sync=False, app='org.onosproject.cli', timeout=30 ):
Jeremy42df2e72016-02-23 16:37:46 -08002118 """
2119 Description:
2120 Remove all the intents
2121 Optional args:-
2122 -s or --sync: Waits for the removal before returning
2123 -p or --purge: Purge the intent from the store after removal
2124 Returns:
2125 Returns main.TRUE if all intents are removed, otherwise returns
2126 main.FALSE; Returns None for exception
2127 """
2128 try:
2129 cmdStr = "remove-intent"
2130 if purge:
2131 cmdStr += " -p"
2132 if sync:
2133 cmdStr += " -s"
2134
2135 cmdStr += " " + app
YPZhangfebf7302016-05-24 16:45:56 -07002136 handle = self.sendline( cmdStr, timeout=timeout )
You Wangb5a55f72017-03-03 12:51:05 -08002137 assert handle is not None, "Error in sendline"
Jeremy42df2e72016-02-23 16:37:46 -08002138 assert "Command not found:" not in handle, handle
2139 if re.search( "Error", handle ):
Jon Hall0e240372018-05-02 11:21:57 -07002140 main.log.error( self.name + ": Error in removing intent" )
Jeremy42df2e72016-02-23 16:37:46 -08002141 return main.FALSE
2142 else:
2143 return main.TRUE
2144 except AssertionError:
2145 main.log.exception( "" )
2146 return None
2147 except TypeError:
2148 main.log.exception( self.name + ": Object not as expected" )
2149 return None
2150 except pexpect.EOF:
2151 main.log.error( self.name + ": EOF exception found" )
2152 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002153 main.cleanAndExit()
Jeremy42df2e72016-02-23 16:37:46 -08002154 except Exception:
2155 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002156 main.cleanAndExit()
Jeremy42df2e72016-02-23 16:37:46 -08002157
Hari Krishnaacabd5a2015-07-01 17:10:19 -07002158 def purgeWithdrawnIntents( self ):
Hari Krishna0ce0e152015-06-23 09:55:29 -07002159 """
2160 Purges all WITHDRAWN Intents
2161 """
2162 try:
2163 cmdStr = "purge-intents"
2164 handle = self.sendline( cmdStr )
You Wangb5a55f72017-03-03 12:51:05 -08002165 assert handle is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08002166 assert "Command not found:" not in handle, handle
Hari Krishna0ce0e152015-06-23 09:55:29 -07002167 if re.search( "Error", handle ):
Jon Hall0e240372018-05-02 11:21:57 -07002168 main.log.error( self.name + ": Error in purging intents" )
Hari Krishna0ce0e152015-06-23 09:55:29 -07002169 return main.FALSE
2170 else:
2171 return main.TRUE
Jon Hallc6793552016-01-19 14:18:37 -08002172 except AssertionError:
2173 main.log.exception( "" )
2174 return None
Hari Krishna0ce0e152015-06-23 09:55:29 -07002175 except TypeError:
2176 main.log.exception( self.name + ": Object not as expected" )
2177 return None
2178 except pexpect.EOF:
2179 main.log.error( self.name + ": EOF exception found" )
2180 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002181 main.cleanAndExit()
Hari Krishna0ce0e152015-06-23 09:55:29 -07002182 except Exception:
2183 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002184 main.cleanAndExit()
Hari Krishna0ce0e152015-06-23 09:55:29 -07002185
Devin Lime6fe3c42017-10-18 16:28:40 -07002186 def wipeout( self ):
2187 """
2188 Wipe out the flows,intents,links,devices,hosts, and groups from the ONOS.
2189 """
2190 try:
2191 cmdStr = "wipe-out please"
2192 handle = self.sendline( cmdStr, timeout=60 )
2193 assert handle is not None, "Error in sendline"
2194 assert "Command not found:" not in handle, handle
2195 return main.TRUE
2196 except AssertionError:
2197 main.log.exception( "" )
2198 return None
2199 except TypeError:
2200 main.log.exception( self.name + ": Object not as expected" )
2201 return None
2202 except pexpect.EOF:
2203 main.log.error( self.name + ": EOF exception found" )
2204 main.log.error( self.name + ": " + self.handle.before )
2205 main.cleanAndExit()
2206 except Exception:
2207 main.log.exception( self.name + ": Uncaught exception!" )
2208 main.cleanAndExit()
2209
kelvin-onlabd3b64892015-01-20 13:26:24 -08002210 def routes( self, jsonFormat=False ):
kelvin8ec71442015-01-15 16:57:00 -08002211 """
kelvin-onlab898a6c62015-01-16 14:13:53 -08002212 NOTE: This method should be used after installing application:
2213 onos-app-sdnip
pingping-lin8b306ac2014-11-17 18:13:51 -08002214 Optional:
kelvin-onlabd3b64892015-01-20 13:26:24 -08002215 * jsonFormat: enable output formatting in json
pingping-lin8b306ac2014-11-17 18:13:51 -08002216 Description:
2217 Obtain all routes in the system
kelvin8ec71442015-01-15 16:57:00 -08002218 """
pingping-lin8b306ac2014-11-17 18:13:51 -08002219 try:
Jon Hallc6358dd2015-04-10 12:44:28 -07002220 cmdStr = "routes"
kelvin-onlabd3b64892015-01-20 13:26:24 -08002221 if jsonFormat:
Jon Hallc6358dd2015-04-10 12:44:28 -07002222 cmdStr += " -j"
2223 handle = self.sendline( cmdStr )
You Wangb5a55f72017-03-03 12:51:05 -08002224 assert handle is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08002225 assert "Command not found:" not in handle, handle
pingping-lin8b306ac2014-11-17 18:13:51 -08002226 return handle
Jon Hallc6793552016-01-19 14:18:37 -08002227 except AssertionError:
2228 main.log.exception( "" )
2229 return None
Jon Halld4d4b372015-01-28 16:02:41 -08002230 except TypeError:
2231 main.log.exception( self.name + ": Object not as expected" )
2232 return None
pingping-lin8b306ac2014-11-17 18:13:51 -08002233 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08002234 main.log.error( self.name + ": EOF exception found" )
2235 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002236 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -08002237 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -08002238 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002239 main.cleanAndExit()
pingping-lin8b306ac2014-11-17 18:13:51 -08002240
pingping-lin54b03372015-08-13 14:43:10 -07002241 def ipv4RouteNumber( self ):
2242 """
2243 NOTE: This method should be used after installing application:
2244 onos-app-sdnip
2245 Description:
2246 Obtain the total IPv4 routes number in the system
2247 """
2248 try:
Pratik Parab57963572017-05-09 11:37:54 -07002249 cmdStr = "routes -j"
pingping-lin54b03372015-08-13 14:43:10 -07002250 handle = self.sendline( cmdStr )
You Wangb5a55f72017-03-03 12:51:05 -08002251 assert handle is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08002252 assert "Command not found:" not in handle, handle
pingping-lin54b03372015-08-13 14:43:10 -07002253 jsonResult = json.loads( handle )
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002254 return len( jsonResult[ 'routes4' ] )
Jon Hallc6793552016-01-19 14:18:37 -08002255 except AssertionError:
2256 main.log.exception( "" )
2257 return None
2258 except ( TypeError, ValueError ):
2259 main.log.exception( "{}: Object not as expected: {!r}".format( self.name, handle ) )
pingping-lin54b03372015-08-13 14:43:10 -07002260 return None
2261 except pexpect.EOF:
2262 main.log.error( self.name + ": EOF exception found" )
2263 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002264 main.cleanAndExit()
pingping-lin54b03372015-08-13 14:43:10 -07002265 except Exception:
2266 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002267 main.cleanAndExit()
pingping-lin54b03372015-08-13 14:43:10 -07002268
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002269 # =============Function to check Bandwidth allocation========
Jon Hall0e240372018-05-02 11:21:57 -07002270 def allocations( self, jsonFormat = True ):
Shreya Chowdhary6fbb96c2017-05-02 16:20:19 -07002271 """
2272 Description:
2273 Obtain Bandwidth Allocation Information from ONOS cli.
2274 """
2275 try:
2276 cmdStr = "allocations"
2277 if jsonFormat:
2278 cmdStr += " -j"
Jon Hall0e240372018-05-02 11:21:57 -07002279 handle = self.sendline( cmdStr, timeout=300 )
Shreya Chowdhary6fbb96c2017-05-02 16:20:19 -07002280 assert handle is not None, "Error in sendline"
2281 assert "Command not found:" not in handle, handle
2282 return handle
2283 except AssertionError:
2284 main.log.exception( "" )
2285 return None
2286 except ( TypeError, ValueError ):
2287 main.log.exception( "{}: Object not as expected: {!r}".format( self.name, handle ) )
2288 return None
2289 except pexpect.EOF:
2290 main.log.error( self.name + ": EOF exception found" )
2291 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002292 main.cleanAndExit()
Shreya Chowdhary6fbb96c2017-05-02 16:20:19 -07002293 except Exception:
2294 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002295 main.cleanAndExit()
Shreya Chowdhary6fbb96c2017-05-02 16:20:19 -07002296
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002297 def intents( self, jsonFormat = True, summary = False, **intentargs ):
kelvin8ec71442015-01-15 16:57:00 -08002298 """
andrewonlabe6745342014-10-17 14:29:13 -04002299 Description:
Jon Hallff566d52016-01-15 14:45:36 -08002300 Obtain intents from the ONOS cli.
2301 Optional:
2302 * jsonFormat: Enable output formatting in json, default to True
2303 * summary: Whether only output the intent summary, defaults to False
2304 * type: Only output a certain type of intent. This options is valid
2305 only when jsonFormat is True and summary is True.
kelvin-onlab898a6c62015-01-16 14:13:53 -08002306 """
andrewonlabe6745342014-10-17 14:29:13 -04002307 try:
Jon Hallc6358dd2015-04-10 12:44:28 -07002308 cmdStr = "intents"
pingping-lin8244a3b2015-09-16 13:36:56 -07002309 if summary:
2310 cmdStr += " -s"
kelvin-onlabd3b64892015-01-20 13:26:24 -08002311 if jsonFormat:
Jon Hallc6358dd2015-04-10 12:44:28 -07002312 cmdStr += " -j"
Shreya Chowdhary6fbb96c2017-05-02 16:20:19 -07002313 handle = self.sendline( cmdStr, timeout=300 )
You Wangb5a55f72017-03-03 12:51:05 -08002314 assert handle is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08002315 assert "Command not found:" not in handle, handle
pingping-lin8244a3b2015-09-16 13:36:56 -07002316 args = utilities.parse_args( [ "TYPE" ], **intentargs )
acsmars5b5fbaf2015-09-18 10:38:20 -07002317 if "TYPE" in args.keys():
Jon Hallff566d52016-01-15 14:45:36 -08002318 intentType = args[ "TYPE" ]
acsmars5b5fbaf2015-09-18 10:38:20 -07002319 else:
Jon Hallff566d52016-01-15 14:45:36 -08002320 intentType = ""
2321 # IF we want the summary of a specific intent type
2322 if jsonFormat and summary and ( intentType != "" ):
pingping-lin8244a3b2015-09-16 13:36:56 -07002323 jsonResult = json.loads( handle )
Jon Hallff566d52016-01-15 14:45:36 -08002324 if intentType in jsonResult.keys():
2325 return jsonResult[ intentType ]
pingping-lin8244a3b2015-09-16 13:36:56 -07002326 else:
Jon Hallff566d52016-01-15 14:45:36 -08002327 main.log.error( "unknown TYPE, returning all types of intents" )
pingping-lin8244a3b2015-09-16 13:36:56 -07002328 return handle
2329 else:
2330 return handle
Jon Hallc6793552016-01-19 14:18:37 -08002331 except AssertionError:
2332 main.log.exception( "" )
2333 return None
2334 except ( TypeError, ValueError ):
2335 main.log.exception( "{}: Object not as expected: {!r}".format( self.name, handle ) )
pingping-lin54b03372015-08-13 14:43:10 -07002336 return None
2337 except pexpect.EOF:
2338 main.log.error( self.name + ": EOF exception found" )
2339 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002340 main.cleanAndExit()
pingping-lin54b03372015-08-13 14:43:10 -07002341 except Exception:
2342 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002343 main.cleanAndExit()
pingping-lin54b03372015-08-13 14:43:10 -07002344
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002345 def getIntentState( self, intentsId, intentsJson=None ):
kelvin-onlab54400a92015-02-26 18:05:51 -08002346 """
You Wangfdcbfc42016-05-16 12:16:53 -07002347 Description:
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002348 Gets intent state. Accepts a single intent ID (string type) or a
You Wangfdcbfc42016-05-16 12:16:53 -07002349 list of intent IDs.
2350 Parameters:
2351 intentsId: intent ID, both string type and list type are acceptable
kelvin-onlab54400a92015-02-26 18:05:51 -08002352 intentsJson: parsed json object from the onos:intents api
You Wangfdcbfc42016-05-16 12:16:53 -07002353 Returns:
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002354 Returns the state (string type) of the ID if a single intent ID is
You Wangfdcbfc42016-05-16 12:16:53 -07002355 accepted.
2356 Returns a list of dictionaries if a list of intent IDs is accepted,
2357 and each dictionary maps 'id' to the Intent ID and 'state' to
2358 corresponding intent state.
kelvin-onlab54400a92015-02-26 18:05:51 -08002359 """
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002360
kelvin-onlab54400a92015-02-26 18:05:51 -08002361 try:
2362 state = "State is Undefined"
2363 if not intentsJson:
Jon Hallc6793552016-01-19 14:18:37 -08002364 rawJson = self.intents()
kelvin-onlab54400a92015-02-26 18:05:51 -08002365 else:
Jon Hallc6793552016-01-19 14:18:37 -08002366 rawJson = intentsJson
2367 parsedIntentsJson = json.loads( rawJson )
Jon Hallefbd9792015-03-05 16:11:36 -08002368 if isinstance( intentsId, types.StringType ):
Jon Hallc6793552016-01-19 14:18:37 -08002369 for intent in parsedIntentsJson:
kelvin-onlabc2dcd3f2015-04-09 16:40:02 -07002370 if intentsId == intent[ 'id' ]:
2371 state = intent[ 'state' ]
kelvin-onlab54400a92015-02-26 18:05:51 -08002372 return state
Jon Hallefbd9792015-03-05 16:11:36 -08002373 main.log.info( "Cannot find intent ID" + str( intentsId ) +
Jon Hall53158082017-05-18 11:17:00 -07002374 " in the list" )
kelvin-onlab54400a92015-02-26 18:05:51 -08002375 return state
Jon Hallefbd9792015-03-05 16:11:36 -08002376 elif isinstance( intentsId, types.ListType ):
kelvin-onlab07dbd012015-03-04 16:29:39 -08002377 dictList = []
kelvin-onlabc2dcd3f2015-04-09 16:40:02 -07002378 for i in xrange( len( intentsId ) ):
kelvin-onlab07dbd012015-03-04 16:29:39 -08002379 stateDict = {}
Jon Hall53158082017-05-18 11:17:00 -07002380 for intent in parsedIntentsJson:
2381 if intentsId[ i ] == intent[ 'id' ]:
2382 stateDict[ 'state' ] = intent[ 'state' ]
kelvin-onlabc2dcd3f2015-04-09 16:40:02 -07002383 stateDict[ 'id' ] = intentsId[ i ]
Jon Hallefbd9792015-03-05 16:11:36 -08002384 dictList.append( stateDict )
kelvin-onlab54400a92015-02-26 18:05:51 -08002385 break
Jon Hallefbd9792015-03-05 16:11:36 -08002386 if len( intentsId ) != len( dictList ):
Jon Hall53158082017-05-18 11:17:00 -07002387 main.log.warn( "Could not find all intents in ONOS output" )
2388 main.log.debug( "expected ids: {} \n ONOS intents: {}".format( intentsId, parsedIntentsJson ) )
kelvin-onlab07dbd012015-03-04 16:29:39 -08002389 return dictList
kelvin-onlab54400a92015-02-26 18:05:51 -08002390 else:
Jon Hall53158082017-05-18 11:17:00 -07002391 main.log.info( "Invalid type for intentsId argument" )
kelvin-onlab54400a92015-02-26 18:05:51 -08002392 return None
Jon Hallc6793552016-01-19 14:18:37 -08002393 except ( TypeError, ValueError ):
2394 main.log.exception( "{}: Object not as expected: {!r}".format( self.name, rawJson ) )
kelvin-onlab54400a92015-02-26 18:05:51 -08002395 return None
2396 except pexpect.EOF:
2397 main.log.error( self.name + ": EOF exception found" )
2398 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002399 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -08002400 except Exception:
kelvin-onlab54400a92015-02-26 18:05:51 -08002401 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002402 main.cleanAndExit()
Jon Hall390696c2015-05-05 17:13:41 -07002403
Jon Hallf539eb92017-05-22 17:18:42 -07002404 def checkIntentState( self, intentsId, expectedState='INSTALLED' ):
kelvin-onlabc2dcd3f2015-04-09 16:40:02 -07002405 """
2406 Description:
2407 Check intents state
2408 Required:
2409 intentsId - List of intents ID to be checked
2410 Optional:
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002411 expectedState - Check the expected state(s) of each intents
kelvin-onlabf512e942015-06-08 19:42:59 -07002412 state in the list.
2413 *NOTE: You can pass in a list of expected state,
2414 Eg: expectedState = [ 'INSTALLED' , 'INSTALLING' ]
kelvin-onlabc2dcd3f2015-04-09 16:40:02 -07002415 Return:
Jon Hall53158082017-05-18 11:17:00 -07002416 Returns main.TRUE only if all intent are the same as expected states,
2417 otherwise returns main.FALSE.
kelvin-onlabc2dcd3f2015-04-09 16:40:02 -07002418 """
2419 try:
kelvin-onlabf512e942015-06-08 19:42:59 -07002420 returnValue = main.TRUE
Jon Hallf539eb92017-05-22 17:18:42 -07002421 # Generating a dictionary: intent id as a key and state as value
Devin Lim752dd7b2017-06-27 14:40:03 -07002422
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002423 # intentsDict = self.getIntentState( intentsId )
Devin Lim752dd7b2017-06-27 14:40:03 -07002424 intentsDict = []
2425 for intent in json.loads( self.intents() ):
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002426 if isinstance( intentsId, types.StringType ) \
2427 and intent.get( 'id' ) == intentsId:
2428 intentsDict.append( intent )
2429 elif isinstance( intentsId, types.ListType ) \
Devin Lim752dd7b2017-06-27 14:40:03 -07002430 and any( intent.get( 'id' ) == ids for ids in intentsId ):
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002431 intentsDict.append( intent )
Devin Lim752dd7b2017-06-27 14:40:03 -07002432
2433 if not intentsDict:
Jon Hallae04e622016-01-27 10:38:05 -08002434 main.log.info( self.name + ": There is something wrong " +
kelvin-onlabc2dcd3f2015-04-09 16:40:02 -07002435 "getting intents state" )
2436 return main.FALSE
kelvin-onlabf512e942015-06-08 19:42:59 -07002437
2438 if isinstance( expectedState, types.StringType ):
2439 for intents in intentsDict:
2440 if intents.get( 'state' ) != expectedState:
kelvin-onlaba297c4d2015-06-01 13:53:55 -07002441 main.log.debug( self.name + " : Intent ID - " +
2442 intents.get( 'id' ) +
kelvin-onlabf512e942015-06-08 19:42:59 -07002443 " actual state = " +
2444 intents.get( 'state' )
2445 + " does not equal expected state = "
2446 + expectedState )
kelvin-onlaba297c4d2015-06-01 13:53:55 -07002447 returnValue = main.FALSE
kelvin-onlabf512e942015-06-08 19:42:59 -07002448 elif isinstance( expectedState, types.ListType ):
2449 for intents in intentsDict:
2450 if not any( state == intents.get( 'state' ) for state in
2451 expectedState ):
2452 main.log.debug( self.name + " : Intent ID - " +
2453 intents.get( 'id' ) +
2454 " actual state = " +
2455 intents.get( 'state' ) +
2456 " does not equal expected states = "
2457 + str( expectedState ) )
2458 returnValue = main.FALSE
2459
kelvin-onlabc2dcd3f2015-04-09 16:40:02 -07002460 if returnValue == main.TRUE:
2461 main.log.info( self.name + ": All " +
2462 str( len( intentsDict ) ) +
kelvin-onlabf512e942015-06-08 19:42:59 -07002463 " intents are in " + str( expectedState ) +
2464 " state" )
kelvin-onlabc2dcd3f2015-04-09 16:40:02 -07002465 return returnValue
2466 except TypeError:
2467 main.log.exception( self.name + ": Object not as expected" )
2468 return None
2469 except pexpect.EOF:
2470 main.log.error( self.name + ": EOF exception found" )
2471 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002472 main.cleanAndExit()
kelvin-onlabc2dcd3f2015-04-09 16:40:02 -07002473 except Exception:
2474 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002475 main.cleanAndExit()
andrewonlabe6745342014-10-17 14:29:13 -04002476
Jon Hallf539eb92017-05-22 17:18:42 -07002477 def compareBandwidthAllocations( self, expectedAllocations ):
2478 """
2479 Description:
2480 Compare the allocated bandwidth with the given allocations
2481 Required:
2482 expectedAllocations - The expected ONOS output of the allocations command
2483 Return:
2484 Returns main.TRUE only if all intent are the same as expected states,
2485 otherwise returns main.FALSE.
2486 """
2487 # FIXME: Convert these string comparisons to object comparisons
2488 try:
2489 returnValue = main.TRUE
2490 bandwidthFailed = False
2491 rawAlloc = self.allocations()
2492 expectedFormat = StringIO( expectedAllocations )
2493 ONOSOutput = StringIO( rawAlloc )
2494 main.log.debug( "ONOSOutput: {}\nexpected output: {}".format( str( ONOSOutput ),
2495 str( expectedFormat ) ) )
2496
2497 for actual, expected in izip( ONOSOutput, expectedFormat ):
2498 actual = actual.rstrip()
2499 expected = expected.rstrip()
2500 main.log.debug( "Expect: {}\nactual: {}".format( expected, actual ) )
2501 if actual != expected and 'allocated' in actual and 'allocated' in expected:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002502 marker1 = actual.find( 'allocated' )
2503 m1 = actual[ :marker1 ]
2504 marker2 = expected.find( 'allocated' )
2505 m2 = expected[ :marker2 ]
Jon Hallf539eb92017-05-22 17:18:42 -07002506 if m1 != m2:
2507 bandwidthFailed = True
2508 elif actual != expected and 'allocated' not in actual and 'allocated' not in expected:
2509 bandwidthFailed = True
2510 expectedFormat.close()
2511 ONOSOutput.close()
2512
2513 if bandwidthFailed:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002514 main.log.error( "Bandwidth not allocated correctly using Intents!!" )
Jon Hallf539eb92017-05-22 17:18:42 -07002515 returnValue = main.FALSE
2516 return returnValue
2517 except TypeError:
2518 main.log.exception( self.name + ": Object not as expected" )
2519 return None
2520 except pexpect.EOF:
2521 main.log.error( self.name + ": EOF exception found" )
2522 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002523 main.cleanAndExit()
Jon Hallf539eb92017-05-22 17:18:42 -07002524 except Exception:
2525 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002526 main.cleanAndExit()
Jon Hallf539eb92017-05-22 17:18:42 -07002527
You Wang66518af2016-05-16 15:32:59 -07002528 def compareIntent( self, intentDict ):
2529 """
2530 Description:
2531 Compare the intent ids and states provided in the argument with all intents in ONOS
2532 Return:
2533 Returns main.TRUE if the two sets of intents match exactly, otherwise main.FALSE
2534 Arguments:
2535 intentDict: a dictionary which maps intent ids to intent states
2536 """
2537 try:
2538 intentsRaw = self.intents()
2539 intentsJson = json.loads( intentsRaw )
2540 intentDictONOS = {}
2541 for intent in intentsJson:
2542 intentDictONOS[ intent[ 'id' ] ] = intent[ 'state' ]
You Wang58d04452016-09-21 15:13:05 -07002543 returnValue = main.TRUE
You Wang66518af2016-05-16 15:32:59 -07002544 if len( intentDict ) != len( intentDictONOS ):
You Wang58d04452016-09-21 15:13:05 -07002545 main.log.warn( self.name + ": expected intent count does not match that in ONOS, " +
You Wang66518af2016-05-16 15:32:59 -07002546 str( len( intentDict ) ) + " expected and " +
2547 str( len( intentDictONOS ) ) + " actual" )
You Wang58d04452016-09-21 15:13:05 -07002548 returnValue = main.FALSE
You Wang66518af2016-05-16 15:32:59 -07002549 for intentID in intentDict.keys():
Jon Halle0f0b342017-04-18 11:43:47 -07002550 if intentID not in intentDictONOS.keys():
You Wang66518af2016-05-16 15:32:59 -07002551 main.log.debug( self.name + ": intent ID - " + intentID + " is not in ONOS" )
2552 returnValue = main.FALSE
You Wang58d04452016-09-21 15:13:05 -07002553 else:
2554 if intentDict[ intentID ] != intentDictONOS[ intentID ]:
2555 main.log.debug( self.name + ": intent ID - " + intentID +
2556 " expected state is " + intentDict[ intentID ] +
2557 " but actual state is " + intentDictONOS[ intentID ] )
2558 returnValue = main.FALSE
2559 intentDictONOS.pop( intentID )
2560 if len( intentDictONOS ) > 0:
2561 returnValue = main.FALSE
2562 for intentID in intentDictONOS.keys():
2563 main.log.debug( self.name + ": find extra intent in ONOS: intent ID " + intentID )
You Wang66518af2016-05-16 15:32:59 -07002564 if returnValue == main.TRUE:
2565 main.log.info( self.name + ": all intent IDs and states match that in ONOS" )
2566 return returnValue
You Wang1be9a512016-05-26 16:54:17 -07002567 except KeyError:
2568 main.log.exception( self.name + ": KeyError exception found" )
2569 return main.ERROR
You Wang66518af2016-05-16 15:32:59 -07002570 except ( TypeError, ValueError ):
2571 main.log.exception( "{}: Object not as expected: {!r}".format( self.name, intentsRaw ) )
You Wang85560372016-05-18 10:44:33 -07002572 return main.ERROR
You Wang66518af2016-05-16 15:32:59 -07002573 except pexpect.EOF:
2574 main.log.error( self.name + ": EOF exception found" )
2575 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002576 main.cleanAndExit()
You Wang66518af2016-05-16 15:32:59 -07002577 except Exception:
2578 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002579 main.cleanAndExit()
You Wang66518af2016-05-16 15:32:59 -07002580
YPZhang14a4aa92016-07-15 13:37:15 -07002581 def checkIntentSummary( self, timeout=60, noExit=True ):
GlennRCed771242016-01-13 17:02:47 -08002582 """
2583 Description:
2584 Check the number of installed intents.
2585 Optional:
2586 timeout - the timeout for pexcept
YPZhang14a4aa92016-07-15 13:37:15 -07002587 noExit - If noExit, TestON will not exit if any except.
GlennRCed771242016-01-13 17:02:47 -08002588 Return:
2589 Returns main.TRUE only if the number of all installed intents are the same as total intents number
2590 , otherwise, returns main.FALSE.
2591 """
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002592
GlennRCed771242016-01-13 17:02:47 -08002593 try:
2594 cmd = "intents -s -j"
2595
2596 # Check response if something wrong
YPZhang14a4aa92016-07-15 13:37:15 -07002597 response = self.sendline( cmd, timeout=timeout, noExit=noExit )
Jon Halle0f0b342017-04-18 11:43:47 -07002598 if response is None:
YPZhang0584d432016-06-21 15:20:13 -07002599 return main.FALSE
GlennRCed771242016-01-13 17:02:47 -08002600 response = json.loads( response )
2601
2602 # get total and installed number, see if they are match
2603 allState = response.get( 'all' )
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002604 if allState.get( 'total' ) == allState.get( 'installed' ):
Jon Halla478b852017-12-04 15:00:15 -08002605 main.log.info( 'Total Intents: {} Installed Intents: {}'.format(
2606 allState.get( 'total' ), allState.get( 'installed' ) ) )
GlennRCed771242016-01-13 17:02:47 -08002607 return main.TRUE
Jon Halla478b852017-12-04 15:00:15 -08002608 main.log.info( 'Verified Intents failed Expected intents: {} installed intents: {}'.format(
2609 allState.get( 'total' ), allState.get( 'installed' ) ) )
GlennRCed771242016-01-13 17:02:47 -08002610 return main.FALSE
2611
Jon Hallc6793552016-01-19 14:18:37 -08002612 except ( TypeError, ValueError ):
2613 main.log.exception( "{}: Object not as expected: {!r}".format( self.name, response ) )
GlennRCed771242016-01-13 17:02:47 -08002614 return None
2615 except pexpect.EOF:
2616 main.log.error( self.name + ": EOF exception found" )
2617 main.log.error( self.name + ": " + self.handle.before )
YPZhang14a4aa92016-07-15 13:37:15 -07002618 if noExit:
2619 return main.FALSE
2620 else:
Devin Lim44075962017-08-11 10:56:37 -07002621 main.cleanAndExit()
Jon Halle0f0b342017-04-18 11:43:47 -07002622 except pexpect.TIMEOUT:
2623 main.log.error( self.name + ": ONOS timeout" )
2624 return None
GlennRCed771242016-01-13 17:02:47 -08002625 except Exception:
2626 main.log.exception( self.name + ": Uncaught exception!" )
YPZhang14a4aa92016-07-15 13:37:15 -07002627 if noExit:
2628 return main.FALSE
2629 else:
Devin Lim44075962017-08-11 10:56:37 -07002630 main.cleanAndExit()
GlennRCed771242016-01-13 17:02:47 -08002631
Andreas Pantelopoulosdf5061f2018-05-15 11:46:59 -07002632 def flows( self, state="any", jsonFormat=True, timeout=60, noExit=False, noCore=False, device=""):
kelvin8ec71442015-01-15 16:57:00 -08002633 """
Shreya Shah0f01c812014-10-26 20:15:28 -04002634 Optional:
kelvin-onlabd3b64892015-01-20 13:26:24 -08002635 * jsonFormat: enable output formatting in json
Jeremy Songster306ed7a2016-07-19 10:59:07 -07002636 * noCore: suppress core flows
Shreya Shah0f01c812014-10-26 20:15:28 -04002637 Description:
Jon Halle3f39ff2015-01-13 11:50:53 -08002638 Obtain flows currently installed
kelvin-onlab898a6c62015-01-16 14:13:53 -08002639 """
Shreya Shah0f01c812014-10-26 20:15:28 -04002640 try:
Jon Hallc6358dd2015-04-10 12:44:28 -07002641 cmdStr = "flows"
kelvin-onlabd3b64892015-01-20 13:26:24 -08002642 if jsonFormat:
Andreas Pantelopoulosdf5061f2018-05-15 11:46:59 -07002643 cmdStr += " -j"
Jeremy Songster306ed7a2016-07-19 10:59:07 -07002644 if noCore:
Andreas Pantelopoulosdf5061f2018-05-15 11:46:59 -07002645 cmdStr += " -n"
2646 cmdStr += " " + state
2647 cmdStr += " " + device
YPZhangebf9eb52016-05-12 15:20:24 -07002648 handle = self.sendline( cmdStr, timeout=timeout, noExit=noExit )
You Wangb5a55f72017-03-03 12:51:05 -08002649 assert handle is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08002650 assert "Command not found:" not in handle, handle
2651 if re.search( "Error:", handle ):
2652 main.log.error( self.name + ": flows() response: " +
2653 str( handle ) )
2654 return handle
2655 except AssertionError:
2656 main.log.exception( "" )
GlennRCed771242016-01-13 17:02:47 -08002657 return None
Jon Halld4d4b372015-01-28 16:02:41 -08002658 except TypeError:
2659 main.log.exception( self.name + ": Object not as expected" )
2660 return None
Jon Hallc6793552016-01-19 14:18:37 -08002661 except pexpect.TIMEOUT:
2662 main.log.error( self.name + ": ONOS timeout" )
2663 return None
Shreya Shah0f01c812014-10-26 20:15:28 -04002664 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08002665 main.log.error( self.name + ": EOF exception found" )
2666 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002667 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -08002668 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -08002669 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002670 main.cleanAndExit()
Shreya Shah0f01c812014-10-26 20:15:28 -04002671
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002672 def checkFlowCount( self, min=0, timeout=60 ):
Flavio Castroa1286fe2016-07-25 14:48:51 -07002673 count = self.getTotalFlowsNum( timeout=timeout )
Jon Halle0f0b342017-04-18 11:43:47 -07002674 count = int( count ) if count else 0
steven30801eccfe212019-01-24 13:00:42 +08002675 main.log.debug( "found {} flows".format( count ) )
Jon Halle0f0b342017-04-18 11:43:47 -07002676 return count if ( count > min ) else False
GlennRCed771242016-01-13 17:02:47 -08002677
Jon Halle0f0b342017-04-18 11:43:47 -07002678 def checkFlowsState( self, isPENDING=True, timeout=60, noExit=False ):
kelvin-onlab4df89f22015-04-13 18:10:23 -07002679 """
2680 Description:
GlennRCed771242016-01-13 17:02:47 -08002681 Check the if all the current flows are in ADDED state
Jon Hallc6793552016-01-19 14:18:37 -08002682 We check PENDING_ADD, PENDING_REMOVE, REMOVED, and FAILED flows,
2683 if the count of those states is 0, which means all current flows
2684 are in ADDED state, and return main.TRUE otherwise return main.FALSE
pingping-linbab7f8a2015-09-21 17:33:36 -07002685 Optional:
GlennRCed771242016-01-13 17:02:47 -08002686 * isPENDING: whether the PENDING_ADD is also a correct status
kelvin-onlab4df89f22015-04-13 18:10:23 -07002687 Return:
2688 returnValue - Returns main.TRUE only if all flows are in
Jon Hallc6793552016-01-19 14:18:37 -08002689 ADDED state or PENDING_ADD if the isPENDING
pingping-linbab7f8a2015-09-21 17:33:36 -07002690 parameter is set true, return main.FALSE otherwise.
kelvin-onlab4df89f22015-04-13 18:10:23 -07002691 """
2692 try:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002693 states = [ "PENDING_ADD", "PENDING_REMOVE", "REMOVED", "FAILED" ]
GlennRCed771242016-01-13 17:02:47 -08002694 checkedStates = []
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002695 statesCount = [ 0, 0, 0, 0 ]
GlennRCed771242016-01-13 17:02:47 -08002696 for s in states:
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002697 rawFlows = self.flows( state=s, timeout = timeout )
YPZhang240842b2016-05-17 12:00:50 -07002698 if rawFlows:
2699 # if we didn't get flows or flows function return None, we should return
2700 # main.Flase
2701 checkedStates.append( json.loads( rawFlows ) )
2702 else:
2703 return main.FALSE
Jon Hallc6793552016-01-19 14:18:37 -08002704 for i in range( len( states ) ):
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002705 for c in checkedStates[ i ]:
Jon Hallc6793552016-01-19 14:18:37 -08002706 try:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002707 statesCount[ i ] += int( c.get( "flowCount" ) )
Jon Hallc6793552016-01-19 14:18:37 -08002708 except TypeError:
2709 main.log.exception( "Json object not as expected" )
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002710 main.log.info( states[ i ] + " flows: " + str( statesCount[ i ] ) )
kelvin-onlabf2ec6e02015-05-27 14:15:28 -07002711
GlennRCed771242016-01-13 17:02:47 -08002712 # We want to count PENDING_ADD if isPENDING is true
2713 if isPENDING:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002714 if statesCount[ 1 ] + statesCount[ 2 ] + statesCount[ 3 ] > 0:
GlennRCed771242016-01-13 17:02:47 -08002715 return main.FALSE
pingping-linbab7f8a2015-09-21 17:33:36 -07002716 else:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002717 if statesCount[ 0 ] + statesCount[ 1 ] + statesCount[ 2 ] + statesCount[ 3 ] > 0:
GlennRCed771242016-01-13 17:02:47 -08002718 return main.FALSE
GlennRCed771242016-01-13 17:02:47 -08002719 return main.TRUE
Jon Hallc6793552016-01-19 14:18:37 -08002720 except ( TypeError, ValueError ):
2721 main.log.exception( "{}: Object not as expected: {!r}".format( self.name, rawFlows ) )
kelvin-onlab4df89f22015-04-13 18:10:23 -07002722 return None
Jeremy Songster9385d412016-06-02 17:57:36 -07002723
YPZhang240842b2016-05-17 12:00:50 -07002724 except AssertionError:
2725 main.log.exception( "" )
2726 return None
Jon Halle0f0b342017-04-18 11:43:47 -07002727 except pexpect.TIMEOUT:
2728 main.log.error( self.name + ": ONOS timeout" )
2729 return None
kelvin-onlab4df89f22015-04-13 18:10:23 -07002730 except pexpect.EOF:
2731 main.log.error( self.name + ": EOF exception found" )
2732 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002733 main.cleanAndExit()
kelvin-onlab4df89f22015-04-13 18:10:23 -07002734 except Exception:
2735 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002736 main.cleanAndExit()
kelvin-onlab4df89f22015-04-13 18:10:23 -07002737
GlennRCed771242016-01-13 17:02:47 -08002738 def pushTestIntents( self, ingress, egress, batchSize, offset="",
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002739 options="", timeout=10, background = False, noExit=False, getResponse=False ):
kelvin8ec71442015-01-15 16:57:00 -08002740 """
andrewonlab87852b02014-11-19 18:44:19 -05002741 Description:
Jon Halle3f39ff2015-01-13 11:50:53 -08002742 Push a number of intents in a batch format to
andrewonlab87852b02014-11-19 18:44:19 -05002743 a specific point-to-point intent definition
2744 Required:
GlennRCed771242016-01-13 17:02:47 -08002745 * ingress: specify source dpid
2746 * egress: specify destination dpid
2747 * batchSize: specify number of intents to push
andrewonlab87852b02014-11-19 18:44:19 -05002748 Optional:
GlennRCed771242016-01-13 17:02:47 -08002749 * offset: the keyOffset is where the next batch of intents
2750 will be installed
YPZhangb34b7e12016-06-14 14:28:19 -07002751 * noExit: If set to True, TestON will not exit if any error when issus command
2752 * getResponse: If set to True, function will return ONOS response.
2753
GlennRCed771242016-01-13 17:02:47 -08002754 Returns: If failed to push test intents, it will returen None,
2755 if successful, return true.
2756 Timeout expection will return None,
2757 TypeError will return false
2758 other expections will exit()
kelvin8ec71442015-01-15 16:57:00 -08002759 """
andrewonlab87852b02014-11-19 18:44:19 -05002760 try:
GlennRCed771242016-01-13 17:02:47 -08002761 if background:
2762 back = "&"
andrewonlab87852b02014-11-19 18:44:19 -05002763 else:
GlennRCed771242016-01-13 17:02:47 -08002764 back = ""
2765 cmd = "push-test-intents {} {} {} {} {} {}".format( options,
Jon Hallc6793552016-01-19 14:18:37 -08002766 ingress,
2767 egress,
2768 batchSize,
2769 offset,
2770 back )
YPZhangebf9eb52016-05-12 15:20:24 -07002771 response = self.sendline( cmd, timeout=timeout, noExit=noExit )
You Wangb5a55f72017-03-03 12:51:05 -08002772 assert response is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08002773 assert "Command not found:" not in response, response
GlennRCed771242016-01-13 17:02:47 -08002774 main.log.info( response )
YPZhangb34b7e12016-06-14 14:28:19 -07002775 if getResponse:
2776 return response
2777
GlennRCed771242016-01-13 17:02:47 -08002778 # TODO: We should handle if there is failure in installation
2779 return main.TRUE
2780
Jon Hallc6793552016-01-19 14:18:37 -08002781 except AssertionError:
2782 main.log.exception( "" )
2783 return None
GlennRCed771242016-01-13 17:02:47 -08002784 except pexpect.TIMEOUT:
2785 main.log.error( self.name + ": ONOS timeout" )
Jon Halld4d4b372015-01-28 16:02:41 -08002786 return None
andrewonlab87852b02014-11-19 18:44:19 -05002787 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08002788 main.log.error( self.name + ": EOF exception found" )
2789 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002790 main.cleanAndExit()
GlennRCed771242016-01-13 17:02:47 -08002791 except TypeError:
2792 main.log.exception( self.name + ": Object not as expected" )
Jon Hallc6793552016-01-19 14:18:37 -08002793 return None
Jon Hallfebb1c72015-03-05 13:30:09 -08002794 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -08002795 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002796 main.cleanAndExit()
andrewonlab87852b02014-11-19 18:44:19 -05002797
YPZhangebf9eb52016-05-12 15:20:24 -07002798 def getTotalFlowsNum( self, timeout=60, noExit=False ):
YPZhangb5d3f832016-01-23 22:54:26 -08002799 """
2800 Description:
YPZhangf6f14a02016-01-28 15:17:31 -08002801 Get the number of ADDED flows.
YPZhangb5d3f832016-01-23 22:54:26 -08002802 Return:
YPZhangf6f14a02016-01-28 15:17:31 -08002803 The number of ADDED flows
YPZhang14a4aa92016-07-15 13:37:15 -07002804 Or return None if any exceptions
YPZhangb5d3f832016-01-23 22:54:26 -08002805 """
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002806
YPZhangb5d3f832016-01-23 22:54:26 -08002807 try:
YPZhange3109a72016-02-02 11:25:37 -08002808 # get total added flows number
YPZhang14a4aa92016-07-15 13:37:15 -07002809 cmd = "flows -c added"
2810 rawFlows = self.sendline( cmd, timeout=timeout, noExit=noExit )
2811 if rawFlows:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002812 rawFlows = rawFlows.split( "\n" )
YPZhange3109a72016-02-02 11:25:37 -08002813 totalFlows = 0
YPZhang14a4aa92016-07-15 13:37:15 -07002814 for l in rawFlows:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002815 totalFlows += int( l.split( "Count=" )[ 1 ] )
YPZhang14a4aa92016-07-15 13:37:15 -07002816 else:
You Wang68568b12019-03-04 11:49:57 -08002817 main.log.warn( "Response not as expected!" )
YPZhang14a4aa92016-07-15 13:37:15 -07002818 return None
2819 return totalFlows
YPZhange3109a72016-02-02 11:25:37 -08002820
You Wangd3097f72018-12-12 11:56:03 -08002821 except IndexError:
2822 main.log.exception( "{}: Object not as expected!".format( self.name ) )
2823 main.log.debug( "rawFlows: {}".format( rawFlows ) )
2824 return None
You Wangd3cb2ce2016-05-16 14:01:24 -07002825 except ( TypeError, ValueError ):
YPZhang14a4aa92016-07-15 13:37:15 -07002826 main.log.exception( "{}: Object not as expected!".format( self.name ) )
YPZhangb5d3f832016-01-23 22:54:26 -08002827 return None
2828 except pexpect.EOF:
2829 main.log.error( self.name + ": EOF exception found" )
2830 main.log.error( self.name + ": " + self.handle.before )
YPZhang14a4aa92016-07-15 13:37:15 -07002831 if not noExit:
Devin Lim44075962017-08-11 10:56:37 -07002832 main.cleanAndExit()
YPZhang14a4aa92016-07-15 13:37:15 -07002833 return None
Jon Halle0f0b342017-04-18 11:43:47 -07002834 except pexpect.TIMEOUT:
2835 main.log.error( self.name + ": ONOS timeout" )
2836 return None
YPZhangb5d3f832016-01-23 22:54:26 -08002837 except Exception:
2838 main.log.exception( self.name + ": Uncaught exception!" )
YPZhang14a4aa92016-07-15 13:37:15 -07002839 if not noExit:
Devin Lim44075962017-08-11 10:56:37 -07002840 main.cleanAndExit()
YPZhang14a4aa92016-07-15 13:37:15 -07002841 return None
YPZhangb5d3f832016-01-23 22:54:26 -08002842
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002843 def getTotalIntentsNum( self, timeout=60, noExit = False ):
YPZhangb5d3f832016-01-23 22:54:26 -08002844 """
2845 Description:
2846 Get the total number of intents, include every states.
YPZhang14a4aa92016-07-15 13:37:15 -07002847 Optional:
2848 noExit - If noExit, TestON will not exit if any except.
YPZhangb5d3f832016-01-23 22:54:26 -08002849 Return:
2850 The number of intents
2851 """
2852 try:
2853 cmd = "summary -j"
YPZhang14a4aa92016-07-15 13:37:15 -07002854 response = self.sendline( cmd, timeout=timeout, noExit=noExit )
Jon Halle0f0b342017-04-18 11:43:47 -07002855 if response is None:
2856 return -1
YPZhangb5d3f832016-01-23 22:54:26 -08002857 response = json.loads( response )
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002858 return int( response.get( "intents" ) )
You Wangd3cb2ce2016-05-16 14:01:24 -07002859 except ( TypeError, ValueError ):
2860 main.log.exception( "{}: Object not as expected: {!r}".format( self.name, response ) )
YPZhangb5d3f832016-01-23 22:54:26 -08002861 return None
2862 except pexpect.EOF:
2863 main.log.error( self.name + ": EOF exception found" )
2864 main.log.error( self.name + ": " + self.handle.before )
YPZhang14a4aa92016-07-15 13:37:15 -07002865 if noExit:
2866 return -1
2867 else:
Devin Lim44075962017-08-11 10:56:37 -07002868 main.cleanAndExit()
YPZhangb5d3f832016-01-23 22:54:26 -08002869 except Exception:
2870 main.log.exception( self.name + ": Uncaught exception!" )
YPZhang14a4aa92016-07-15 13:37:15 -07002871 if noExit:
2872 return -1
2873 else:
Devin Lim44075962017-08-11 10:56:37 -07002874 main.cleanAndExit()
YPZhangb5d3f832016-01-23 22:54:26 -08002875
kelvin-onlabd3b64892015-01-20 13:26:24 -08002876 def intentsEventsMetrics( self, jsonFormat=True ):
kelvin8ec71442015-01-15 16:57:00 -08002877 """
Jon Halle3f39ff2015-01-13 11:50:53 -08002878 Description:Returns topology metrics
andrewonlab0dbb6ec2014-11-06 13:46:55 -05002879 Optional:
kelvin-onlabd3b64892015-01-20 13:26:24 -08002880 * jsonFormat: enable json formatting of output
kelvin8ec71442015-01-15 16:57:00 -08002881 """
andrewonlab0dbb6ec2014-11-06 13:46:55 -05002882 try:
Jon Hallc6358dd2015-04-10 12:44:28 -07002883 cmdStr = "intents-events-metrics"
kelvin-onlabd3b64892015-01-20 13:26:24 -08002884 if jsonFormat:
Jon Hallc6358dd2015-04-10 12:44:28 -07002885 cmdStr += " -j"
2886 handle = self.sendline( cmdStr )
You Wangb5a55f72017-03-03 12:51:05 -08002887 assert handle is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08002888 assert "Command not found:" not in handle, handle
andrewonlab0dbb6ec2014-11-06 13:46:55 -05002889 return handle
Jon Hallc6793552016-01-19 14:18:37 -08002890 except AssertionError:
2891 main.log.exception( "" )
2892 return None
Jon Halld4d4b372015-01-28 16:02:41 -08002893 except TypeError:
2894 main.log.exception( self.name + ": Object not as expected" )
2895 return None
andrewonlab0dbb6ec2014-11-06 13:46:55 -05002896 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08002897 main.log.error( self.name + ": EOF exception found" )
2898 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002899 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -08002900 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -08002901 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002902 main.cleanAndExit()
Shreya Shah0f01c812014-10-26 20:15:28 -04002903
kelvin-onlabd3b64892015-01-20 13:26:24 -08002904 def topologyEventsMetrics( self, jsonFormat=True ):
kelvin8ec71442015-01-15 16:57:00 -08002905 """
2906 Description:Returns topology metrics
andrewonlab867212a2014-10-22 20:13:38 -04002907 Optional:
kelvin-onlabd3b64892015-01-20 13:26:24 -08002908 * jsonFormat: enable json formatting of output
kelvin8ec71442015-01-15 16:57:00 -08002909 """
andrewonlab867212a2014-10-22 20:13:38 -04002910 try:
Jon Hallc6358dd2015-04-10 12:44:28 -07002911 cmdStr = "topology-events-metrics"
kelvin-onlabd3b64892015-01-20 13:26:24 -08002912 if jsonFormat:
Jon Hallc6358dd2015-04-10 12:44:28 -07002913 cmdStr += " -j"
2914 handle = self.sendline( cmdStr )
You Wangb5a55f72017-03-03 12:51:05 -08002915 assert handle is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08002916 assert "Command not found:" not in handle, handle
jenkins7ead5a82015-03-13 10:28:21 -07002917 if handle:
2918 return handle
Jon Hallc6358dd2015-04-10 12:44:28 -07002919 elif jsonFormat:
Jon Hallbe379602015-03-24 13:39:32 -07002920 # Return empty json
jenkins7ead5a82015-03-13 10:28:21 -07002921 return '{}'
Jon Hallc6358dd2015-04-10 12:44:28 -07002922 else:
2923 return handle
Jon Hallc6793552016-01-19 14:18:37 -08002924 except AssertionError:
2925 main.log.exception( "" )
2926 return None
Jon Halld4d4b372015-01-28 16:02:41 -08002927 except TypeError:
2928 main.log.exception( self.name + ": Object not as expected" )
2929 return None
andrewonlab867212a2014-10-22 20:13:38 -04002930 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08002931 main.log.error( self.name + ": EOF exception found" )
2932 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002933 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -08002934 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -08002935 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002936 main.cleanAndExit()
andrewonlab867212a2014-10-22 20:13:38 -04002937
kelvin8ec71442015-01-15 16:57:00 -08002938 # Wrapper functions ****************
2939 # Wrapper functions use existing driver
2940 # functions and extends their use case.
2941 # For example, we may use the output of
2942 # a normal driver function, and parse it
2943 # using a wrapper function
andrewonlabc2d05aa2014-10-13 16:51:10 -04002944
kelvin-onlabd3b64892015-01-20 13:26:24 -08002945 def getAllIntentsId( self ):
kelvin8ec71442015-01-15 16:57:00 -08002946 """
andrewonlab9a50dfe2014-10-17 17:22:31 -04002947 Description:
2948 Obtain all intent id's in a list
kelvin8ec71442015-01-15 16:57:00 -08002949 """
andrewonlab9a50dfe2014-10-17 17:22:31 -04002950 try:
kelvin8ec71442015-01-15 16:57:00 -08002951 # Obtain output of intents function
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002952 intentsStr = self.intents( jsonFormat=True )
Jon Hall7a6ebfd2017-03-13 10:58:58 -07002953 if intentsStr is None:
2954 raise TypeError
Jon Hall6021e062017-01-30 11:10:06 -08002955 # Convert to a dictionary
2956 intents = json.loads( intentsStr )
kelvin-onlabd3b64892015-01-20 13:26:24 -08002957 intentIdList = []
Jon Hall6021e062017-01-30 11:10:06 -08002958 for intent in intents:
2959 intentIdList.append( intent[ 'id' ] )
kelvin-onlabd3b64892015-01-20 13:26:24 -08002960 return intentIdList
Jon Halld4d4b372015-01-28 16:02:41 -08002961 except TypeError:
2962 main.log.exception( self.name + ": Object not as expected" )
2963 return None
andrewonlab9a50dfe2014-10-17 17:22:31 -04002964 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08002965 main.log.error( self.name + ": EOF exception found" )
2966 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002967 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -08002968 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -08002969 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002970 main.cleanAndExit()
andrewonlab9a50dfe2014-10-17 17:22:31 -04002971
You Wang3c276252016-09-21 15:21:36 -07002972 def flowAddedCount( self, deviceId, core=False ):
Jon Hall30b82fa2015-03-04 17:15:43 -08002973 """
2974 Determine the number of flow rules for the given device id that are
2975 in the added state
You Wang3c276252016-09-21 15:21:36 -07002976 Params:
2977 core: if True, only return the number of core flows added
Jon Hall30b82fa2015-03-04 17:15:43 -08002978 """
2979 try:
You Wang3c276252016-09-21 15:21:36 -07002980 if core:
2981 cmdStr = "flows any " + str( deviceId ) + " | " +\
2982 "grep 'state=ADDED' | grep org.onosproject.core | wc -l"
2983 else:
2984 cmdStr = "flows any " + str( deviceId ) + " | " +\
2985 "grep 'state=ADDED' | wc -l"
Jon Halld5a94fb2018-11-13 14:32:23 -08002986 handle = self.lineCount( cmdStr )
You Wangb5a55f72017-03-03 12:51:05 -08002987 assert handle is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08002988 assert "Command not found:" not in handle, handle
Jon Hall30b82fa2015-03-04 17:15:43 -08002989 return handle
Jon Hallc6793552016-01-19 14:18:37 -08002990 except AssertionError:
2991 main.log.exception( "" )
2992 return None
Jon Hall30b82fa2015-03-04 17:15:43 -08002993 except pexpect.EOF:
2994 main.log.error( self.name + ": EOF exception found" )
2995 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002996 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -08002997 except Exception:
Jon Hall30b82fa2015-03-04 17:15:43 -08002998 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002999 main.cleanAndExit()
andrewonlab95ce8322014-10-13 14:12:04 -04003000
Andreas Pantelopoulos9173d442018-03-01 17:07:37 -08003001 def groupAddedCount( self, deviceId, core=False ):
3002 """
3003 Determine the number of group rules for the given device id that are
3004 in the added state
3005 Params:
3006 core: if True, only return the number of core groups added
3007 """
3008 try:
3009 if core:
3010 cmdStr = "groups any " + str( deviceId ) + " | " +\
3011 "grep 'state=ADDED' | grep org.onosproject.core | wc -l"
3012 else:
3013 cmdStr = "groups any " + str( deviceId ) + " | " +\
3014 "grep 'state=ADDED' | wc -l"
Jon Halld5a94fb2018-11-13 14:32:23 -08003015 handle = self.lineCount( cmdStr )
Andreas Pantelopoulos9173d442018-03-01 17:07:37 -08003016 assert handle is not None, "Error in sendline"
3017 assert "Command not found:" not in handle, handle
3018 return handle
3019 except AssertionError:
3020 main.log.exception( "" )
3021 return None
3022 except pexpect.EOF:
3023 main.log.error( self.name + ": EOF exception found" )
3024 main.log.error( self.name + ": " + self.handle.before )
3025 main.cleanAndExit()
3026 except Exception:
3027 main.log.exception( self.name + ": Uncaught exception!" )
3028 main.cleanAndExit()
3029
Andreas Pantelopoulos2eae3242018-03-06 13:47:20 -08003030 def addStaticRoute( self, subnet, intf):
3031 """
3032 Adds a static route to onos.
3033 Params:
3034 subnet: The subnet reaching through this route
3035 intf: The interface this route is reachable through
3036 """
3037 try:
3038 cmdStr = "route-add " + subnet + " " + intf
3039 handle = self.sendline( cmdStr )
3040 assert handle is not None, "Error in sendline"
3041 assert "Command not found:" not in handle, handle
3042 return handle
3043 except AssertionError:
3044 main.log.exception( "" )
3045 return None
3046 except pexpect.EOF:
3047 main.log.error( self.name + ": EOF exception found" )
3048 main.log.error( self.name + ": " + self.handle.before )
3049 main.cleanAndExit()
3050 except Exception:
3051 main.log.exception( self.name + ": Uncaught exception!" )
3052 main.cleanAndExit()
3053
Andreas Pantelopoulos9173d442018-03-01 17:07:37 -08003054 def checkGroupAddedCount( self, deviceId, expectedGroupCount=0, core=False, comparison=0):
3055 """
3056 Description:
3057 Check whether the number of groups for the given device id that
3058 are in ADDED state is bigger than minGroupCount.
3059 Required:
3060 * deviceId: device id to check the number of added group rules
3061 Optional:
3062 * minGroupCount: the number of groups to compare
3063 * core: if True, only check the number of core groups added
3064 * comparison: if 0, compare with greater than minFlowCount
3065 * if 1, compare with equal to minFlowCount
3066 Return:
3067 Returns the number of groups if it is bigger than minGroupCount,
3068 returns main.FALSE otherwise.
3069 """
3070 count = self.groupAddedCount( deviceId, core )
3071 count = int( count ) if count else 0
Jon Hall9677ed32018-04-24 11:16:23 -07003072 main.log.debug( "found {} groups".format( count ) )
Andreas Pantelopoulos9173d442018-03-01 17:07:37 -08003073 return count if ((count > expectedGroupCount) if (comparison == 0) else (count == expectedGroupCount)) else main.FALSE
3074
You Wangc02f3be2018-05-18 12:14:23 -07003075 def getGroups( self, deviceId, groupType="any" ):
Andreas Pantelopoulosdf5061f2018-05-15 11:46:59 -07003076 """
3077 Retrieve groups from a specific device.
You Wangc02f3be2018-05-18 12:14:23 -07003078 deviceId: Id of the device from which we retrieve groups
3079 groupType: Type of group
Andreas Pantelopoulosdf5061f2018-05-15 11:46:59 -07003080 """
Andreas Pantelopoulosdf5061f2018-05-15 11:46:59 -07003081 try:
You Wangc02f3be2018-05-18 12:14:23 -07003082 groupCmd = "groups -t {0} any {1}".format( groupType, deviceId )
3083 handle = self.sendline( groupCmd )
Andreas Pantelopoulosdf5061f2018-05-15 11:46:59 -07003084 assert handle is not None, "Error in sendline"
3085 assert "Command not found:" not in handle, handle
3086 return handle
3087 except AssertionError:
3088 main.log.exception( "" )
3089 return None
3090 except TypeError:
3091 main.log.exception( self.name + ": Object not as expected" )
3092 return None
3093 except pexpect.EOF:
3094 main.log.error( self.name + ": EOF exception found" )
3095 main.log.error( self.name + ": " + self.handle.before )
3096 main.cleanAndExit()
3097 except Exception:
3098 main.log.exception( self.name + ": Uncaught exception!" )
3099 main.cleanAndExit()
3100
Andreas Pantelopoulos9173d442018-03-01 17:07:37 -08003101 def checkFlowAddedCount( self, deviceId, expectedFlowCount=0, core=False, comparison=0):
Jonghwan Hyuncf2345c2018-02-26 11:07:54 -08003102 """
3103 Description:
3104 Check whether the number of flow rules for the given device id that
3105 are in ADDED state is bigger than minFlowCount.
3106 Required:
3107 * deviceId: device id to check the number of added flow rules
3108 Optional:
3109 * minFlowCount: the number of flow rules to compare
3110 * core: if True, only check the number of core flows added
Andreas Pantelopoulos9173d442018-03-01 17:07:37 -08003111 * comparison: if 0, compare with greater than minFlowCount
3112 * if 1, compare with equal to minFlowCount
Jonghwan Hyuncf2345c2018-02-26 11:07:54 -08003113 Return:
3114 Returns the number of flow rules if it is bigger than minFlowCount,
3115 returns main.FALSE otherwise.
3116 """
3117 count = self.flowAddedCount( deviceId, core )
3118 count = int( count ) if count else 0
Jon Hall9677ed32018-04-24 11:16:23 -07003119 main.log.debug( "found {} flows".format( count ) )
Andreas Pantelopoulos2eae3242018-03-06 13:47:20 -08003120 return count if ((count > expectedFlowCount) if (comparison == 0) else (count == expectedFlowCount)) else main.FALSE
Jonghwan Hyuncf2345c2018-02-26 11:07:54 -08003121
kelvin-onlabd3b64892015-01-20 13:26:24 -08003122 def getAllDevicesId( self ):
kelvin8ec71442015-01-15 16:57:00 -08003123 """
andrewonlab7e4d2d32014-10-15 13:23:21 -04003124 Use 'devices' function to obtain list of all devices
3125 and parse the result to obtain a list of all device
3126 id's. Returns this list. Returns empty list if no
3127 devices exist
kelvin8ec71442015-01-15 16:57:00 -08003128 List is ordered sequentially
3129
andrewonlab3e15ead2014-10-15 14:21:34 -04003130 This function may be useful if you are not sure of the
kelvin8ec71442015-01-15 16:57:00 -08003131 device id, and wish to execute other commands using
andrewonlab3e15ead2014-10-15 14:21:34 -04003132 the ids. By obtaining the list of device ids on the fly,
3133 you can iterate through the list to get mastership, etc.
kelvin8ec71442015-01-15 16:57:00 -08003134 """
andrewonlab7e4d2d32014-10-15 13:23:21 -04003135 try:
kelvin8ec71442015-01-15 16:57:00 -08003136 # Call devices and store result string
kelvin-onlabd3b64892015-01-20 13:26:24 -08003137 devicesStr = self.devices( jsonFormat=False )
3138 idList = []
kelvin8ec71442015-01-15 16:57:00 -08003139
kelvin-onlabd3b64892015-01-20 13:26:24 -08003140 if not devicesStr:
kelvin8ec71442015-01-15 16:57:00 -08003141 main.log.info( "There are no devices to get id from" )
kelvin-onlabd3b64892015-01-20 13:26:24 -08003142 return idList
kelvin8ec71442015-01-15 16:57:00 -08003143
3144 # Split the string into list by comma
kelvin-onlabd3b64892015-01-20 13:26:24 -08003145 deviceList = devicesStr.split( "," )
kelvin8ec71442015-01-15 16:57:00 -08003146 # Get temporary list of all arguments with string 'id='
kelvin-onlabd3b64892015-01-20 13:26:24 -08003147 tempList = [ dev for dev in deviceList if "id=" in dev ]
kelvin8ec71442015-01-15 16:57:00 -08003148 # Split list further into arguments before and after string
3149 # 'id='. Get the latter portion ( the actual device id ) and
kelvin-onlabd3b64892015-01-20 13:26:24 -08003150 # append to idList
3151 for arg in tempList:
3152 idList.append( arg.split( "id=" )[ 1 ] )
3153 return idList
andrewonlab7e4d2d32014-10-15 13:23:21 -04003154
Jon Halld4d4b372015-01-28 16:02:41 -08003155 except TypeError:
3156 main.log.exception( self.name + ": Object not as expected" )
3157 return None
andrewonlab7e4d2d32014-10-15 13:23:21 -04003158 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08003159 main.log.error( self.name + ": EOF exception found" )
3160 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003161 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -08003162 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -08003163 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003164 main.cleanAndExit()
andrewonlab7e4d2d32014-10-15 13:23:21 -04003165
kelvin-onlabd3b64892015-01-20 13:26:24 -08003166 def getAllNodesId( self ):
kelvin8ec71442015-01-15 16:57:00 -08003167 """
andrewonlab7c211572014-10-15 16:45:20 -04003168 Uses 'nodes' function to obtain list of all nodes
3169 and parse the result of nodes to obtain just the
kelvin8ec71442015-01-15 16:57:00 -08003170 node id's.
andrewonlab7c211572014-10-15 16:45:20 -04003171 Returns:
3172 list of node id's
kelvin8ec71442015-01-15 16:57:00 -08003173 """
andrewonlab7c211572014-10-15 16:45:20 -04003174 try:
Jon Hall5aa168b2015-03-23 14:23:09 -07003175 nodesStr = self.nodes( jsonFormat=True )
kelvin-onlabd3b64892015-01-20 13:26:24 -08003176 idList = []
Jon Hall5aa168b2015-03-23 14:23:09 -07003177 # Sample nodesStr output
Jon Hallbd182782016-03-28 16:42:22 -07003178 # id=local, address=127.0.0.1:9876, state=READY *
kelvin-onlabd3b64892015-01-20 13:26:24 -08003179 if not nodesStr:
kelvin8ec71442015-01-15 16:57:00 -08003180 main.log.info( "There are no nodes to get id from" )
kelvin-onlabd3b64892015-01-20 13:26:24 -08003181 return idList
Jon Hall5aa168b2015-03-23 14:23:09 -07003182 nodesJson = json.loads( nodesStr )
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003183 idList = [ node.get( 'id' ) for node in nodesJson ]
kelvin-onlabd3b64892015-01-20 13:26:24 -08003184 return idList
Jon Hallc6793552016-01-19 14:18:37 -08003185 except ( TypeError, ValueError ):
3186 main.log.exception( "{}: Object not as expected: {!r}".format( self.name, nodesStr ) )
Jon Halld4d4b372015-01-28 16:02:41 -08003187 return None
andrewonlab7c211572014-10-15 16:45:20 -04003188 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08003189 main.log.error( self.name + ": EOF exception found" )
3190 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003191 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -08003192 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -08003193 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003194 main.cleanAndExit()
andrewonlab7e4d2d32014-10-15 13:23:21 -04003195
kelvin-onlabd3b64892015-01-20 13:26:24 -08003196 def getDevice( self, dpid=None ):
kelvin8ec71442015-01-15 16:57:00 -08003197 """
Jon Halla91c4dc2014-10-22 12:57:04 -04003198 Return the first device from the devices api whose 'id' contains 'dpid'
3199 Return None if there is no match
kelvin8ec71442015-01-15 16:57:00 -08003200 """
Jon Halla91c4dc2014-10-22 12:57:04 -04003201 try:
kelvin8ec71442015-01-15 16:57:00 -08003202 if dpid is None:
Jon Halla91c4dc2014-10-22 12:57:04 -04003203 return None
3204 else:
kelvin8ec71442015-01-15 16:57:00 -08003205 dpid = dpid.replace( ':', '' )
kelvin-onlabd3b64892015-01-20 13:26:24 -08003206 rawDevices = self.devices()
3207 devicesJson = json.loads( rawDevices )
kelvin8ec71442015-01-15 16:57:00 -08003208 # search json for the device with dpid then return the device
kelvin-onlabd3b64892015-01-20 13:26:24 -08003209 for device in devicesJson:
kelvin8ec71442015-01-15 16:57:00 -08003210 # print "%s in %s?" % ( dpid, device[ 'id' ] )
3211 if dpid in device[ 'id' ]:
Jon Halla91c4dc2014-10-22 12:57:04 -04003212 return device
3213 return None
Jon Hallc6793552016-01-19 14:18:37 -08003214 except ( TypeError, ValueError ):
3215 main.log.exception( "{}: Object not as expected: {!r}".format( self.name, rawDevices ) )
Jon Halld4d4b372015-01-28 16:02:41 -08003216 return None
Jon Halla91c4dc2014-10-22 12:57:04 -04003217 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08003218 main.log.error( self.name + ": EOF exception found" )
3219 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003220 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -08003221 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -08003222 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003223 main.cleanAndExit()
Jon Halla91c4dc2014-10-22 12:57:04 -04003224
You Wang24139872016-05-03 11:48:47 -07003225 def getTopology( self, topologyOutput ):
3226 """
3227 Definition:
3228 Loads a json topology output
3229 Return:
3230 topology = current ONOS topology
3231 """
You Wang24139872016-05-03 11:48:47 -07003232 try:
3233 # either onos:topology or 'topology' will work in CLI
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003234 topology = json.loads( topologyOutput )
Jeremy Songsterbc2d8ac2016-05-04 11:25:42 -07003235 main.log.debug( topology )
You Wang24139872016-05-03 11:48:47 -07003236 return topology
You Wangd3cb2ce2016-05-16 14:01:24 -07003237 except ( TypeError, ValueError ):
3238 main.log.exception( "{}: Object not as expected: {!r}".format( self.name, topologyOutput ) )
3239 return None
You Wang24139872016-05-03 11:48:47 -07003240 except pexpect.EOF:
3241 main.log.error( self.name + ": EOF exception found" )
3242 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003243 main.cleanAndExit()
You Wang24139872016-05-03 11:48:47 -07003244 except Exception:
3245 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003246 main.cleanAndExit()
You Wang24139872016-05-03 11:48:47 -07003247
Pier6a0c4de2018-03-18 16:01:30 -07003248 def checkStatus( self, numoswitch, numolink = -1, numoctrl = -1, logLevel="info" ):
kelvin8ec71442015-01-15 16:57:00 -08003249 """
Jon Hallefbd9792015-03-05 16:11:36 -08003250 Checks the number of switches & links that ONOS sees against the
kelvin8ec71442015-01-15 16:57:00 -08003251 supplied values. By default this will report to main.log, but the
You Wang24139872016-05-03 11:48:47 -07003252 log level can be specific.
kelvin8ec71442015-01-15 16:57:00 -08003253
Flavio Castro82ee2f62016-06-07 15:04:12 -07003254 Params: numoswitch = expected number of switches
Jon Hallefbd9792015-03-05 16:11:36 -08003255 numolink = expected number of links
Flavio Castro82ee2f62016-06-07 15:04:12 -07003256 numoctrl = expected number of controllers
You Wang24139872016-05-03 11:48:47 -07003257 logLevel = level to log to.
3258 Currently accepts 'info', 'warn' and 'report'
Jon Hall42db6dc2014-10-24 19:03:48 -04003259
Jon Hallefbd9792015-03-05 16:11:36 -08003260 Returns: main.TRUE if the number of switches and links are correct,
3261 main.FALSE if the number of switches and links is incorrect,
Jon Hall42db6dc2014-10-24 19:03:48 -04003262 and main.ERROR otherwise
kelvin8ec71442015-01-15 16:57:00 -08003263 """
Jon Hall42db6dc2014-10-24 19:03:48 -04003264 try:
You Wang13310252016-07-31 10:56:14 -07003265 summary = self.summary()
3266 summary = json.loads( summary )
Flavio Castrof5b3f872016-06-23 17:52:31 -07003267 except ( TypeError, ValueError ):
3268 main.log.exception( "{}: Object not as expected: {!r}".format( self.name, summary ) )
3269 return main.ERROR
3270 try:
3271 topology = self.getTopology( self.topology() )
Jon Halle0f0b342017-04-18 11:43:47 -07003272 if topology == {} or topology is None or summary == {} or summary is None:
Jon Hall42db6dc2014-10-24 19:03:48 -04003273 return main.ERROR
3274 output = ""
kelvin8ec71442015-01-15 16:57:00 -08003275 # Is the number of switches is what we expected
3276 devices = topology.get( 'devices', False )
3277 links = topology.get( 'links', False )
Flavio Castro82ee2f62016-06-07 15:04:12 -07003278 nodes = summary.get( 'nodes', False )
3279 if devices is False or links is False or nodes is False:
Jon Hall42db6dc2014-10-24 19:03:48 -04003280 return main.ERROR
kelvin-onlabd3b64892015-01-20 13:26:24 -08003281 switchCheck = ( int( devices ) == int( numoswitch ) )
kelvin8ec71442015-01-15 16:57:00 -08003282 # Is the number of links is what we expected
Pier6a0c4de2018-03-18 16:01:30 -07003283 linkCheck = ( int( links ) == int( numolink ) ) or int( numolink ) == -1
Flavio Castro82ee2f62016-06-07 15:04:12 -07003284 nodeCheck = ( int( nodes ) == int( numoctrl ) ) or int( numoctrl ) == -1
3285 if switchCheck and linkCheck and nodeCheck:
kelvin8ec71442015-01-15 16:57:00 -08003286 # We expected the correct numbers
You Wang24139872016-05-03 11:48:47 -07003287 output = output + "The number of links and switches match "\
3288 + "what was expected"
Jon Hall42db6dc2014-10-24 19:03:48 -04003289 result = main.TRUE
3290 else:
You Wang24139872016-05-03 11:48:47 -07003291 output = output + \
3292 "The number of links and switches does not match " + \
3293 "what was expected"
Jon Hall42db6dc2014-10-24 19:03:48 -04003294 result = main.FALSE
You Wang24139872016-05-03 11:48:47 -07003295 output = output + "\n ONOS sees %i devices" % int( devices )
3296 output = output + " (%i expected) " % int( numoswitch )
Pier6a0c4de2018-03-18 16:01:30 -07003297 if int( numolink ) > 0:
3298 output = output + "and %i links " % int( links )
3299 output = output + "(%i expected)" % int( numolink )
YPZhangd7e4b6e2016-06-17 16:07:55 -07003300 if int( numoctrl ) > 0:
Flavio Castro82ee2f62016-06-07 15:04:12 -07003301 output = output + "and %i controllers " % int( nodes )
3302 output = output + "(%i expected)" % int( numoctrl )
kelvin-onlabd3b64892015-01-20 13:26:24 -08003303 if logLevel == "report":
kelvin8ec71442015-01-15 16:57:00 -08003304 main.log.report( output )
kelvin-onlabd3b64892015-01-20 13:26:24 -08003305 elif logLevel == "warn":
kelvin8ec71442015-01-15 16:57:00 -08003306 main.log.warn( output )
Jon Hall42db6dc2014-10-24 19:03:48 -04003307 else:
You Wang24139872016-05-03 11:48:47 -07003308 main.log.info( output )
kelvin8ec71442015-01-15 16:57:00 -08003309 return result
Jon Hall42db6dc2014-10-24 19:03:48 -04003310 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08003311 main.log.error( self.name + ": EOF exception found" )
3312 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003313 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -08003314 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -08003315 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003316 main.cleanAndExit()
Jon Hall1c9e8732014-10-27 19:29:27 -04003317
kelvin-onlabd3b64892015-01-20 13:26:24 -08003318 def deviceRole( self, deviceId, onosNode, role="master" ):
kelvin8ec71442015-01-15 16:57:00 -08003319 """
Jon Hall1c9e8732014-10-27 19:29:27 -04003320 Calls the device-role cli command.
kelvin-onlabd3b64892015-01-20 13:26:24 -08003321 deviceId must be the id of a device as seen in the onos devices command
3322 onosNode is the ip of one of the onos nodes in the cluster
Jon Hall1c9e8732014-10-27 19:29:27 -04003323 role must be either master, standby, or none
3324
Jon Halle3f39ff2015-01-13 11:50:53 -08003325 Returns:
3326 main.TRUE or main.FALSE based on argument verification and
3327 main.ERROR if command returns and error
kelvin-onlab898a6c62015-01-16 14:13:53 -08003328 """
Jon Hall1c9e8732014-10-27 19:29:27 -04003329 try:
Jon Halle3f39ff2015-01-13 11:50:53 -08003330 if role.lower() == "master" or role.lower() == "standby" or\
Jon Hall1c9e8732014-10-27 19:29:27 -04003331 role.lower() == "none":
kelvin-onlabd3b64892015-01-20 13:26:24 -08003332 cmdStr = "device-role " +\
3333 str( deviceId ) + " " +\
3334 str( onosNode ) + " " +\
kelvin-onlab898a6c62015-01-16 14:13:53 -08003335 str( role )
kelvin-onlabd3b64892015-01-20 13:26:24 -08003336 handle = self.sendline( cmdStr )
You Wangb5a55f72017-03-03 12:51:05 -08003337 assert handle is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08003338 assert "Command not found:" not in handle, handle
kelvin-onlab898a6c62015-01-16 14:13:53 -08003339 if re.search( "Error", handle ):
3340 # end color output to escape any colours
3341 # from the cli
kelvin8ec71442015-01-15 16:57:00 -08003342 main.log.error( self.name + ": " +
kelvin-onlab898a6c62015-01-16 14:13:53 -08003343 handle + '\033[0m' )
kelvin8ec71442015-01-15 16:57:00 -08003344 return main.ERROR
kelvin8ec71442015-01-15 16:57:00 -08003345 return main.TRUE
Jon Hall1c9e8732014-10-27 19:29:27 -04003346 else:
kelvin-onlab898a6c62015-01-16 14:13:53 -08003347 main.log.error( "Invalid 'role' given to device_role(). " +
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003348 "Value was '" + str( role ) + "'." )
Jon Hall1c9e8732014-10-27 19:29:27 -04003349 return main.FALSE
Jon Hallc6793552016-01-19 14:18:37 -08003350 except AssertionError:
3351 main.log.exception( "" )
3352 return None
Jon Halld4d4b372015-01-28 16:02:41 -08003353 except TypeError:
3354 main.log.exception( self.name + ": Object not as expected" )
3355 return None
Jon Hall1c9e8732014-10-27 19:29:27 -04003356 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08003357 main.log.error( self.name + ": EOF exception found" )
3358 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003359 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -08003360 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -08003361 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003362 main.cleanAndExit()
Jon Hall1c9e8732014-10-27 19:29:27 -04003363
kelvin-onlabd3b64892015-01-20 13:26:24 -08003364 def clusters( self, jsonFormat=True ):
kelvin8ec71442015-01-15 16:57:00 -08003365 """
Jon Hall0dd09952018-04-19 09:59:11 -07003366 Lists all topology clusters
Jon Hallffb386d2014-11-21 13:43:38 -08003367 Optional argument:
kelvin-onlabd3b64892015-01-20 13:26:24 -08003368 * jsonFormat - boolean indicating if you want output in json
kelvin8ec71442015-01-15 16:57:00 -08003369 """
Jon Hall73cf9cc2014-11-20 22:28:38 -08003370 try:
Jon Hall0dd09952018-04-19 09:59:11 -07003371 cmdStr = "topo-clusters"
kelvin-onlabd3b64892015-01-20 13:26:24 -08003372 if jsonFormat:
Jon Hallc6358dd2015-04-10 12:44:28 -07003373 cmdStr += " -j"
3374 handle = self.sendline( cmdStr )
You Wangb5a55f72017-03-03 12:51:05 -08003375 assert handle is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08003376 assert "Command not found:" not in handle, handle
Jon Hallc6358dd2015-04-10 12:44:28 -07003377 return handle
Jon Hallc6793552016-01-19 14:18:37 -08003378 except AssertionError:
3379 main.log.exception( "" )
3380 return None
Jon Halld4d4b372015-01-28 16:02:41 -08003381 except TypeError:
3382 main.log.exception( self.name + ": Object not as expected" )
3383 return None
Jon Hall73cf9cc2014-11-20 22:28:38 -08003384 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08003385 main.log.error( self.name + ": EOF exception found" )
3386 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003387 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -08003388 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -08003389 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003390 main.cleanAndExit()
Jon Hall73cf9cc2014-11-20 22:28:38 -08003391
kelvin-onlabd3b64892015-01-20 13:26:24 -08003392 def electionTestLeader( self ):
kelvin-onlab898a6c62015-01-16 14:13:53 -08003393 """
Jon Halle3f39ff2015-01-13 11:50:53 -08003394 CLI command to get the current leader for the Election test application
3395 NOTE: Requires installation of the onos-app-election feature
3396 Returns: Node IP of the leader if one exists
3397 None if none exists
3398 Main.FALSE on error
kelvin-onlab898a6c62015-01-16 14:13:53 -08003399 """
Jon Hall94fd0472014-12-08 11:52:42 -08003400 try:
kelvin-onlabd3b64892015-01-20 13:26:24 -08003401 cmdStr = "election-test-leader"
3402 response = self.sendline( cmdStr )
You Wangb5a55f72017-03-03 12:51:05 -08003403 assert response is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08003404 assert "Command not found:" not in response, response
Jon Halle3f39ff2015-01-13 11:50:53 -08003405 # Leader
3406 leaderPattern = "The\scurrent\sleader\sfor\sthe\sElection\s" +\
kelvin-onlab898a6c62015-01-16 14:13:53 -08003407 "app\sis\s(?P<node>.+)\."
kelvin-onlabd3b64892015-01-20 13:26:24 -08003408 nodeSearch = re.search( leaderPattern, response )
3409 if nodeSearch:
3410 node = nodeSearch.group( 'node' )
Jon Halle3f39ff2015-01-13 11:50:53 -08003411 main.log.info( "Election-test-leader on " + str( self.name ) +
kelvin-onlab898a6c62015-01-16 14:13:53 -08003412 " found " + node + " as the leader" )
Jon Hall94fd0472014-12-08 11:52:42 -08003413 return node
Jon Halle3f39ff2015-01-13 11:50:53 -08003414 # no leader
3415 nullPattern = "There\sis\scurrently\sno\sleader\selected\sfor\s" +\
kelvin-onlab898a6c62015-01-16 14:13:53 -08003416 "the\sElection\sapp"
kelvin-onlabd3b64892015-01-20 13:26:24 -08003417 nullSearch = re.search( nullPattern, response )
3418 if nullSearch:
Jon Halle3f39ff2015-01-13 11:50:53 -08003419 main.log.info( "Election-test-leader found no leader on " +
kelvin-onlab898a6c62015-01-16 14:13:53 -08003420 self.name )
Jon Hall94fd0472014-12-08 11:52:42 -08003421 return None
kelvin-onlab898a6c62015-01-16 14:13:53 -08003422 # error
Jon Hall0e240372018-05-02 11:21:57 -07003423 main.log.error( self.name + ": Error in electionTestLeader on " + self.name +
Jon Hall97cf84a2016-06-20 13:35:58 -07003424 ": " + "unexpected response" )
3425 main.log.error( repr( response ) )
3426 return main.FALSE
Jon Hallc6793552016-01-19 14:18:37 -08003427 except AssertionError:
3428 main.log.exception( "" )
3429 return None
Jon Halld4d4b372015-01-28 16:02:41 -08003430 except TypeError:
3431 main.log.exception( self.name + ": Object not as expected" )
3432 return main.FALSE
Jon Hall94fd0472014-12-08 11:52:42 -08003433 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08003434 main.log.error( self.name + ": EOF exception found" )
3435 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003436 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -08003437 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -08003438 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003439 main.cleanAndExit()
Jon Hall94fd0472014-12-08 11:52:42 -08003440
kelvin-onlabd3b64892015-01-20 13:26:24 -08003441 def electionTestRun( self ):
kelvin-onlab898a6c62015-01-16 14:13:53 -08003442 """
Jon Halle3f39ff2015-01-13 11:50:53 -08003443 CLI command to run for leadership of the Election test application.
3444 NOTE: Requires installation of the onos-app-election feature
3445 Returns: Main.TRUE on success
3446 Main.FALSE on error
kelvin-onlab898a6c62015-01-16 14:13:53 -08003447 """
Jon Hall94fd0472014-12-08 11:52:42 -08003448 try:
kelvin-onlabd3b64892015-01-20 13:26:24 -08003449 cmdStr = "election-test-run"
3450 response = self.sendline( cmdStr )
You Wangb5a55f72017-03-03 12:51:05 -08003451 assert response is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08003452 assert "Command not found:" not in response, response
kelvin-onlab898a6c62015-01-16 14:13:53 -08003453 # success
Jon Halle3f39ff2015-01-13 11:50:53 -08003454 successPattern = "Entering\sleadership\selections\sfor\sthe\s" +\
kelvin-onlab898a6c62015-01-16 14:13:53 -08003455 "Election\sapp."
Jon Halle3f39ff2015-01-13 11:50:53 -08003456 search = re.search( successPattern, response )
Jon Hall94fd0472014-12-08 11:52:42 -08003457 if search:
Jon Halle3f39ff2015-01-13 11:50:53 -08003458 main.log.info( self.name + " entering leadership elections " +
kelvin-onlab898a6c62015-01-16 14:13:53 -08003459 "for the Election app." )
Jon Hall94fd0472014-12-08 11:52:42 -08003460 return main.TRUE
kelvin-onlab898a6c62015-01-16 14:13:53 -08003461 # error
Jon Hall0e240372018-05-02 11:21:57 -07003462 main.log.error( self.name + ": Error in electionTestRun on " + self.name +
Jon Hall97cf84a2016-06-20 13:35:58 -07003463 ": " + "unexpected response" )
3464 main.log.error( repr( response ) )
3465 return main.FALSE
Jon Hallc6793552016-01-19 14:18:37 -08003466 except AssertionError:
3467 main.log.exception( "" )
3468 return None
Jon Halld4d4b372015-01-28 16:02:41 -08003469 except TypeError:
3470 main.log.exception( self.name + ": Object not as expected" )
3471 return main.FALSE
Jon Hall94fd0472014-12-08 11:52:42 -08003472 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08003473 main.log.error( self.name + ": EOF exception found" )
3474 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003475 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -08003476 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -08003477 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003478 main.cleanAndExit()
Jon Hall94fd0472014-12-08 11:52:42 -08003479
kelvin-onlabd3b64892015-01-20 13:26:24 -08003480 def electionTestWithdraw( self ):
kelvin8ec71442015-01-15 16:57:00 -08003481 """
Jon Hall94fd0472014-12-08 11:52:42 -08003482 * CLI command to withdraw the local node from leadership election for
3483 * the Election test application.
3484 #NOTE: Requires installation of the onos-app-election feature
3485 Returns: Main.TRUE on success
3486 Main.FALSE on error
kelvin8ec71442015-01-15 16:57:00 -08003487 """
Jon Hall94fd0472014-12-08 11:52:42 -08003488 try:
kelvin-onlabd3b64892015-01-20 13:26:24 -08003489 cmdStr = "election-test-withdraw"
3490 response = self.sendline( cmdStr )
You Wangb5a55f72017-03-03 12:51:05 -08003491 assert response is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08003492 assert "Command not found:" not in response, response
kelvin-onlab898a6c62015-01-16 14:13:53 -08003493 # success
Jon Halle3f39ff2015-01-13 11:50:53 -08003494 successPattern = "Withdrawing\sfrom\sleadership\selections\sfor" +\
kelvin-onlab898a6c62015-01-16 14:13:53 -08003495 "\sthe\sElection\sapp."
Jon Halle3f39ff2015-01-13 11:50:53 -08003496 if re.search( successPattern, response ):
3497 main.log.info( self.name + " withdrawing from leadership " +
kelvin-onlab898a6c62015-01-16 14:13:53 -08003498 "elections for the Election app." )
Jon Hall94fd0472014-12-08 11:52:42 -08003499 return main.TRUE
kelvin-onlab898a6c62015-01-16 14:13:53 -08003500 # error
Jon Hall0e240372018-05-02 11:21:57 -07003501 main.log.error( self.name + ": Error in electionTestWithdraw on " +
Jon Hall97cf84a2016-06-20 13:35:58 -07003502 self.name + ": " + "unexpected response" )
3503 main.log.error( repr( response ) )
3504 return main.FALSE
Jon Hallc6793552016-01-19 14:18:37 -08003505 except AssertionError:
3506 main.log.exception( "" )
3507 return None
Jon Halld4d4b372015-01-28 16:02:41 -08003508 except TypeError:
3509 main.log.exception( self.name + ": Object not as expected" )
3510 return main.FALSE
Jon Hall94fd0472014-12-08 11:52:42 -08003511 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08003512 main.log.error( self.name + ": EOF exception found" )
3513 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003514 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -08003515 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -08003516 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003517 main.cleanAndExit()
Jon Hall1c9e8732014-10-27 19:29:27 -04003518
kelvin8ec71442015-01-15 16:57:00 -08003519 def getDevicePortsEnabledCount( self, dpid ):
3520 """
Hari Krishnaa43d4e92014-12-19 13:22:40 -08003521 Get the count of all enabled ports on a particular device/switch
kelvin8ec71442015-01-15 16:57:00 -08003522 """
Hari Krishnaa43d4e92014-12-19 13:22:40 -08003523 try:
Jon Halle3f39ff2015-01-13 11:50:53 -08003524 dpid = str( dpid )
kelvin-onlabd3b64892015-01-20 13:26:24 -08003525 cmdStr = "onos:ports -e " + dpid + " | wc -l"
Jon Halld5a94fb2018-11-13 14:32:23 -08003526 output = self.lineCount( cmdStr )
Jon Halla495f562016-05-16 18:03:26 -07003527 assert output is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08003528 assert "Command not found:" not in output, output
Jon Halle3f39ff2015-01-13 11:50:53 -08003529 if re.search( "No such device", output ):
Jon Hall0e240372018-05-02 11:21:57 -07003530 main.log.error( self.name + ": Error in getting ports" )
Jon Halle3f39ff2015-01-13 11:50:53 -08003531 return ( output, "Error" )
Jon Halla495f562016-05-16 18:03:26 -07003532 return output
Jon Hallc6793552016-01-19 14:18:37 -08003533 except AssertionError:
3534 main.log.exception( "" )
3535 return None
Jon Halld4d4b372015-01-28 16:02:41 -08003536 except TypeError:
3537 main.log.exception( self.name + ": Object not as expected" )
3538 return ( output, "Error" )
Hari Krishnaa43d4e92014-12-19 13:22:40 -08003539 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08003540 main.log.error( self.name + ": EOF exception found" )
3541 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003542 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -08003543 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -08003544 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003545 main.cleanAndExit()
Hari Krishnaa43d4e92014-12-19 13:22:40 -08003546
kelvin8ec71442015-01-15 16:57:00 -08003547 def getDeviceLinksActiveCount( self, dpid ):
3548 """
Hari Krishnaa43d4e92014-12-19 13:22:40 -08003549 Get the count of all enabled ports on a particular device/switch
kelvin8ec71442015-01-15 16:57:00 -08003550 """
Hari Krishnaa43d4e92014-12-19 13:22:40 -08003551 try:
kelvin-onlab898a6c62015-01-16 14:13:53 -08003552 dpid = str( dpid )
kelvin-onlabd3b64892015-01-20 13:26:24 -08003553 cmdStr = "onos:links " + dpid + " | grep ACTIVE | wc -l"
Jon Halld5a94fb2018-11-13 14:32:23 -08003554 output = self.lineCount( cmdStr )
Jon Halla495f562016-05-16 18:03:26 -07003555 assert output is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08003556 assert "Command not found:" not in output, output
Jon Halle3f39ff2015-01-13 11:50:53 -08003557 if re.search( "No such device", output ):
Jon Hall0e240372018-05-02 11:21:57 -07003558 main.log.error( self.name + ": Error in getting ports " )
kelvin-onlab898a6c62015-01-16 14:13:53 -08003559 return ( output, "Error " )
Jon Halla495f562016-05-16 18:03:26 -07003560 return output
Jon Hallc6793552016-01-19 14:18:37 -08003561 except AssertionError:
3562 main.log.exception( "" )
3563 return None
Jon Halld4d4b372015-01-28 16:02:41 -08003564 except TypeError:
3565 main.log.exception( self.name + ": Object not as expected" )
3566 return ( output, "Error " )
Hari Krishnaa43d4e92014-12-19 13:22:40 -08003567 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08003568 main.log.error( self.name + ": EOF exception found" )
3569 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003570 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -08003571 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -08003572 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003573 main.cleanAndExit()
Hari Krishnaa43d4e92014-12-19 13:22:40 -08003574
kelvin8ec71442015-01-15 16:57:00 -08003575 def getAllIntentIds( self ):
3576 """
Hari Krishnaa43d4e92014-12-19 13:22:40 -08003577 Return a list of all Intent IDs
kelvin8ec71442015-01-15 16:57:00 -08003578 """
Hari Krishnaa43d4e92014-12-19 13:22:40 -08003579 try:
kelvin-onlabd3b64892015-01-20 13:26:24 -08003580 cmdStr = "onos:intents | grep id="
3581 output = self.sendline( cmdStr )
Jon Halla495f562016-05-16 18:03:26 -07003582 assert output is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08003583 assert "Command not found:" not in output, output
Jon Halle3f39ff2015-01-13 11:50:53 -08003584 if re.search( "Error", output ):
Jon Hall0e240372018-05-02 11:21:57 -07003585 main.log.error( self.name + ": Error in getting ports" )
Jon Halle3f39ff2015-01-13 11:50:53 -08003586 return ( output, "Error" )
Jon Halla495f562016-05-16 18:03:26 -07003587 return output
Jon Hallc6793552016-01-19 14:18:37 -08003588 except AssertionError:
3589 main.log.exception( "" )
3590 return None
Jon Halld4d4b372015-01-28 16:02:41 -08003591 except TypeError:
3592 main.log.exception( self.name + ": Object not as expected" )
3593 return ( output, "Error" )
Hari Krishnaa43d4e92014-12-19 13:22:40 -08003594 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08003595 main.log.error( self.name + ": EOF exception found" )
3596 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003597 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -08003598 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -08003599 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003600 main.cleanAndExit()
Jon Halld4d4b372015-01-28 16:02:41 -08003601
Jon Hall73509952015-02-24 16:42:56 -08003602 def intentSummary( self ):
3603 """
Jon Hallefbd9792015-03-05 16:11:36 -08003604 Returns a dictionary containing the current intent states and the count
Jon Hall73509952015-02-24 16:42:56 -08003605 """
3606 try:
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00003607 intents = self.intents( )
Jon Hall08f61bc2015-04-13 16:00:30 -07003608 states = []
Jon Hall5aa168b2015-03-23 14:23:09 -07003609 for intent in json.loads( intents ):
Jon Hall08f61bc2015-04-13 16:00:30 -07003610 states.append( intent.get( 'state', None ) )
3611 out = [ ( i, states.count( i ) ) for i in set( states ) ]
Jon Hall63604932015-02-26 17:09:50 -08003612 main.log.info( dict( out ) )
Jon Hall73509952015-02-24 16:42:56 -08003613 return dict( out )
Jon Hallc6793552016-01-19 14:18:37 -08003614 except ( TypeError, ValueError ):
3615 main.log.exception( "{}: Object not as expected: {!r}".format( self.name, intents ) )
Jon Hall73509952015-02-24 16:42:56 -08003616 return None
3617 except pexpect.EOF:
3618 main.log.error( self.name + ": EOF exception found" )
3619 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003620 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -08003621 except Exception:
Jon Hall73509952015-02-24 16:42:56 -08003622 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003623 main.cleanAndExit()
Jon Hall63604932015-02-26 17:09:50 -08003624
Jon Hall61282e32015-03-19 11:34:11 -07003625 def leaders( self, jsonFormat=True ):
Jon Hall63604932015-02-26 17:09:50 -08003626 """
3627 Returns the output of the leaders command.
Jon Hall61282e32015-03-19 11:34:11 -07003628 Optional argument:
3629 * jsonFormat - boolean indicating if you want output in json
Jon Hall63604932015-02-26 17:09:50 -08003630 """
Jon Hall63604932015-02-26 17:09:50 -08003631 try:
Jon Hallc6358dd2015-04-10 12:44:28 -07003632 cmdStr = "onos:leaders"
Jon Hall61282e32015-03-19 11:34:11 -07003633 if jsonFormat:
Jon Hallc6358dd2015-04-10 12:44:28 -07003634 cmdStr += " -j"
3635 output = self.sendline( cmdStr )
Jon Halla495f562016-05-16 18:03:26 -07003636 assert output is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08003637 assert "Command not found:" not in output, output
Jon Hallc6358dd2015-04-10 12:44:28 -07003638 return output
Jon Hallc6793552016-01-19 14:18:37 -08003639 except AssertionError:
3640 main.log.exception( "" )
3641 return None
Jon Hall63604932015-02-26 17:09:50 -08003642 except TypeError:
3643 main.log.exception( self.name + ": Object not as expected" )
3644 return None
Hari Krishnaa43d4e92014-12-19 13:22:40 -08003645 except pexpect.EOF:
3646 main.log.error( self.name + ": EOF exception found" )
3647 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003648 main.cleanAndExit()
Jon Hall77ba41c2015-04-06 10:25:40 -07003649 except Exception:
Jon Hall63604932015-02-26 17:09:50 -08003650 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003651 main.cleanAndExit()
Jon Hall63604932015-02-26 17:09:50 -08003652
acsmarsa4a4d1e2015-07-10 16:01:24 -07003653 def leaderCandidates( self, jsonFormat=True ):
3654 """
3655 Returns the output of the leaders -c command.
3656 Optional argument:
3657 * jsonFormat - boolean indicating if you want output in json
3658 """
3659 try:
3660 cmdStr = "onos:leaders -c"
3661 if jsonFormat:
3662 cmdStr += " -j"
3663 output = self.sendline( cmdStr )
Jon Halla495f562016-05-16 18:03:26 -07003664 assert output is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08003665 assert "Command not found:" not in output, output
acsmarsa4a4d1e2015-07-10 16:01:24 -07003666 return output
Jon Hallc6793552016-01-19 14:18:37 -08003667 except AssertionError:
3668 main.log.exception( "" )
3669 return None
acsmarsa4a4d1e2015-07-10 16:01:24 -07003670 except TypeError:
3671 main.log.exception( self.name + ": Object not as expected" )
3672 return None
3673 except pexpect.EOF:
3674 main.log.error( self.name + ": EOF exception found" )
3675 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003676 main.cleanAndExit()
acsmarsa4a4d1e2015-07-10 16:01:24 -07003677 except Exception:
3678 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003679 main.cleanAndExit()
acsmarsa4a4d1e2015-07-10 16:01:24 -07003680
Jon Hallc6793552016-01-19 14:18:37 -08003681 def specificLeaderCandidate( self, topic ):
acsmarsa4a4d1e2015-07-10 16:01:24 -07003682 """
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00003683 Returns a list in format [leader,candidate1,candidate2,...] for a given
acsmarsa4a4d1e2015-07-10 16:01:24 -07003684 topic parameter and an empty list if the topic doesn't exist
3685 If no leader is elected leader in the returned list will be "none"
3686 Returns None if there is a type error processing the json object
3687 """
3688 try:
Jon Hall6e709752016-02-01 13:38:46 -08003689 cmdStr = "onos:leaders -j"
Jon Hallc6793552016-01-19 14:18:37 -08003690 rawOutput = self.sendline( cmdStr )
Jon Halla495f562016-05-16 18:03:26 -07003691 assert rawOutput is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08003692 assert "Command not found:" not in rawOutput, rawOutput
3693 output = json.loads( rawOutput )
acsmarsa4a4d1e2015-07-10 16:01:24 -07003694 results = []
3695 for dict in output:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003696 if dict[ "topic" ] == topic:
3697 leader = dict[ "leader" ]
3698 candidates = re.split( ", ", dict[ "candidates" ][ 1:-1 ] )
Jon Hallc6793552016-01-19 14:18:37 -08003699 results.append( leader )
3700 results.extend( candidates )
acsmarsa4a4d1e2015-07-10 16:01:24 -07003701 return results
Jon Hallc6793552016-01-19 14:18:37 -08003702 except AssertionError:
3703 main.log.exception( "" )
3704 return None
3705 except ( TypeError, ValueError ):
3706 main.log.exception( "{}: Object not as expected: {!r}".format( self.name, rawOutput ) )
acsmarsa4a4d1e2015-07-10 16:01:24 -07003707 return None
3708 except pexpect.EOF:
3709 main.log.error( self.name + ": EOF exception found" )
3710 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003711 main.cleanAndExit()
acsmarsa4a4d1e2015-07-10 16:01:24 -07003712 except Exception:
3713 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003714 main.cleanAndExit()
acsmarsa4a4d1e2015-07-10 16:01:24 -07003715
Jon Hall61282e32015-03-19 11:34:11 -07003716 def pendingMap( self, jsonFormat=True ):
Jon Hall63604932015-02-26 17:09:50 -08003717 """
3718 Returns the output of the intent Pending map.
3719 """
Jon Hall63604932015-02-26 17:09:50 -08003720 try:
Jon Hallc6358dd2015-04-10 12:44:28 -07003721 cmdStr = "onos:intents -p"
Jon Hall61282e32015-03-19 11:34:11 -07003722 if jsonFormat:
Jon Hallc6358dd2015-04-10 12:44:28 -07003723 cmdStr += " -j"
3724 output = self.sendline( cmdStr )
Jon Halla495f562016-05-16 18:03:26 -07003725 assert output is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08003726 assert "Command not found:" not in output, output
Jon Hallc6358dd2015-04-10 12:44:28 -07003727 return output
Jon Hallc6793552016-01-19 14:18:37 -08003728 except AssertionError:
3729 main.log.exception( "" )
3730 return None
Jon Hall63604932015-02-26 17:09:50 -08003731 except TypeError:
3732 main.log.exception( self.name + ": Object not as expected" )
3733 return None
3734 except pexpect.EOF:
3735 main.log.error( self.name + ": EOF exception found" )
3736 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003737 main.cleanAndExit()
Jon Hall77ba41c2015-04-06 10:25:40 -07003738 except Exception:
Jon Hall63604932015-02-26 17:09:50 -08003739 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003740 main.cleanAndExit()
Jon Hall63604932015-02-26 17:09:50 -08003741
Jon Hall2c8959e2016-12-16 12:17:34 -08003742 def partitions( self, candidates=False, jsonFormat=True ):
Jon Hall63604932015-02-26 17:09:50 -08003743 """
3744 Returns the output of the raft partitions command for ONOS.
3745 """
Jon Hall61282e32015-03-19 11:34:11 -07003746 # Sample JSON
3747 # {
3748 # "leader": "tcp://10.128.30.11:7238",
3749 # "members": [
3750 # "tcp://10.128.30.11:7238",
3751 # "tcp://10.128.30.17:7238",
3752 # "tcp://10.128.30.13:7238",
3753 # ],
3754 # "name": "p1",
3755 # "term": 3
3756 # },
Jon Hall63604932015-02-26 17:09:50 -08003757 try:
Jon Hallc6358dd2015-04-10 12:44:28 -07003758 cmdStr = "onos:partitions"
Jon Hall2c8959e2016-12-16 12:17:34 -08003759 if candidates:
3760 cmdStr += " -c"
Jon Hall61282e32015-03-19 11:34:11 -07003761 if jsonFormat:
Jon Hallc6358dd2015-04-10 12:44:28 -07003762 cmdStr += " -j"
3763 output = self.sendline( cmdStr )
Jon Halla495f562016-05-16 18:03:26 -07003764 assert output is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08003765 assert "Command not found:" not in output, output
Jon Hallc6358dd2015-04-10 12:44:28 -07003766 return output
Jon Hallc6793552016-01-19 14:18:37 -08003767 except AssertionError:
3768 main.log.exception( "" )
3769 return None
Jon Hall63604932015-02-26 17:09:50 -08003770 except TypeError:
3771 main.log.exception( self.name + ": Object not as expected" )
3772 return None
3773 except pexpect.EOF:
3774 main.log.error( self.name + ": EOF exception found" )
3775 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003776 main.cleanAndExit()
Jon Hall77ba41c2015-04-06 10:25:40 -07003777 except Exception:
Jon Hall63604932015-02-26 17:09:50 -08003778 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003779 main.cleanAndExit()
Jon Hall63604932015-02-26 17:09:50 -08003780
Jon Halle9f909e2016-09-23 10:43:12 -07003781 def apps( self, summary=False, active=False, jsonFormat=True ):
Jon Hallbe379602015-03-24 13:39:32 -07003782 """
3783 Returns the output of the apps command for ONOS. This command lists
3784 information about installed ONOS applications
3785 """
3786 # Sample JSON object
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00003787 # [{"name":"org.onosproject.openflow","id":0,"version":"1.2.0",
Jon Hallbe379602015-03-24 13:39:32 -07003788 # "description":"ONOS OpenFlow protocol southbound providers",
3789 # "origin":"ON.Lab","permissions":"[]","featuresRepo":"",
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00003790 # "features":"[onos-openflow]","state":"ACTIVE"}]
Jon Hallbe379602015-03-24 13:39:32 -07003791 try:
Jon Hallc6358dd2015-04-10 12:44:28 -07003792 cmdStr = "onos:apps"
Jon Hallf03ae762019-01-22 13:25:27 -08003793 expectJson = False
Jon Halle9f909e2016-09-23 10:43:12 -07003794 if summary:
3795 cmdStr += " -s"
3796 if active:
3797 cmdStr += " -a"
Jon Hallbe379602015-03-24 13:39:32 -07003798 if jsonFormat:
Jon Hallc6358dd2015-04-10 12:44:28 -07003799 cmdStr += " -j"
Jon Hallf03ae762019-01-22 13:25:27 -08003800 expectJson = True
3801 output = self.sendline( cmdStr, expectJson=expectJson )
Jon Halla495f562016-05-16 18:03:26 -07003802 assert output is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08003803 assert "Command not found:" not in output, output
3804 assert "Error executing command" not in output, output
Jon Hallc6358dd2015-04-10 12:44:28 -07003805 return output
Jon Hallbe379602015-03-24 13:39:32 -07003806 # FIXME: look at specific exceptions/Errors
3807 except AssertionError:
Jon Hall0e240372018-05-02 11:21:57 -07003808 main.log.exception( self.name + ": Error in processing onos:app command." )
Jon Hallbe379602015-03-24 13:39:32 -07003809 return None
3810 except TypeError:
3811 main.log.exception( self.name + ": Object not as expected" )
3812 return None
3813 except pexpect.EOF:
3814 main.log.error( self.name + ": EOF exception found" )
3815 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003816 main.cleanAndExit()
Jon Hall77ba41c2015-04-06 10:25:40 -07003817 except Exception:
Jon Hallbe379602015-03-24 13:39:32 -07003818 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003819 main.cleanAndExit()
Jon Hallbe379602015-03-24 13:39:32 -07003820
You Wangcdc51fe2018-08-12 17:14:56 -07003821 def appStatus( self, appName ):
Jon Hall146f1522015-03-24 15:33:24 -07003822 """
3823 Uses the onos:apps cli command to return the status of an application.
3824 Returns:
3825 "ACTIVE" - If app is installed and activated
3826 "INSTALLED" - If app is installed and deactivated
3827 "UNINSTALLED" - If app is not installed
3828 None - on error
3829 """
Jon Hall146f1522015-03-24 15:33:24 -07003830 try:
3831 if not isinstance( appName, types.StringType ):
3832 main.log.error( self.name + ".appStatus(): appName must be" +
3833 " a string" )
3834 return None
3835 output = self.apps( jsonFormat=True )
3836 appsJson = json.loads( output )
3837 state = None
3838 for app in appsJson:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003839 if appName == app.get( 'name' ):
3840 state = app.get( 'state' )
Jon Hall146f1522015-03-24 15:33:24 -07003841 break
3842 if state == "ACTIVE" or state == "INSTALLED":
3843 return state
3844 elif state is None:
You Wang0d9f2c02018-08-10 14:56:32 -07003845 main.log.warn( "{} app not found".format( appName ) )
Jon Hall146f1522015-03-24 15:33:24 -07003846 return "UNINSTALLED"
3847 elif state:
3848 main.log.error( "Unexpected state from 'onos:apps': " +
3849 str( state ) )
3850 return state
Jon Hallc6793552016-01-19 14:18:37 -08003851 except ( TypeError, ValueError ):
3852 main.log.exception( "{}: Object not as expected: {!r}".format( self.name, output ) )
Jon Hall146f1522015-03-24 15:33:24 -07003853 return None
3854 except pexpect.EOF:
3855 main.log.error( self.name + ": EOF exception found" )
3856 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003857 main.cleanAndExit()
Jon Hall77ba41c2015-04-06 10:25:40 -07003858 except Exception:
Jon Hall146f1522015-03-24 15:33:24 -07003859 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003860 main.cleanAndExit()
Jon Hall146f1522015-03-24 15:33:24 -07003861
Jon Hallbe379602015-03-24 13:39:32 -07003862 def app( self, appName, option ):
3863 """
3864 Interacts with the app command for ONOS. This command manages
3865 application inventory.
3866 """
Jon Hallbe379602015-03-24 13:39:32 -07003867 try:
Jon Hallbd16b922015-03-26 17:53:15 -07003868 # Validate argument types
3869 valid = True
3870 if not isinstance( appName, types.StringType ):
3871 main.log.error( self.name + ".app(): appName must be a " +
3872 "string" )
3873 valid = False
3874 if not isinstance( option, types.StringType ):
3875 main.log.error( self.name + ".app(): option must be a string" )
3876 valid = False
3877 if not valid:
3878 return main.FALSE
3879 # Validate Option
3880 option = option.lower()
3881 # NOTE: Install may become a valid option
3882 if option == "activate":
3883 pass
3884 elif option == "deactivate":
3885 pass
3886 elif option == "uninstall":
3887 pass
3888 else:
3889 # Invalid option
3890 main.log.error( "The ONOS app command argument only takes " +
3891 "the values: (activate|deactivate|uninstall)" +
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003892 "; was given '" + option + "'" )
Jon Hallbd16b922015-03-26 17:53:15 -07003893 return main.FALSE
Jon Hall146f1522015-03-24 15:33:24 -07003894 cmdStr = "onos:app " + option + " " + appName
Jon Hallbe379602015-03-24 13:39:32 -07003895 output = self.sendline( cmdStr )
You Wangb5a55f72017-03-03 12:51:05 -08003896 assert output is not None, "Error in sendline"
3897 assert "Command not found:" not in output, output
Jon Hallbe379602015-03-24 13:39:32 -07003898 if "Error executing command" in output:
Jon Hall0e240372018-05-02 11:21:57 -07003899 main.log.error( self.name + ": Error in processing onos:app command: " +
Jon Hallbe379602015-03-24 13:39:32 -07003900 str( output ) )
Jon Hall146f1522015-03-24 15:33:24 -07003901 return main.FALSE
Jon Hallbe379602015-03-24 13:39:32 -07003902 elif "No such application" in output:
3903 main.log.error( "The application '" + appName +
3904 "' is not installed in ONOS" )
Jon Hall146f1522015-03-24 15:33:24 -07003905 return main.FALSE
3906 elif "Command not found:" in output:
Jon Hall0e240372018-05-02 11:21:57 -07003907 main.log.error( self.name + ": Error in processing onos:app command: " +
Jon Hall146f1522015-03-24 15:33:24 -07003908 str( output ) )
3909 return main.FALSE
Jon Hallbd16b922015-03-26 17:53:15 -07003910 elif "Unsupported command:" in output:
3911 main.log.error( "Incorrect command given to 'app': " +
3912 str( output ) )
Jon Hallbe379602015-03-24 13:39:32 -07003913 # NOTE: we may need to add more checks here
Jon Hallbd16b922015-03-26 17:53:15 -07003914 # else: Command was successful
Jon Hall08f61bc2015-04-13 16:00:30 -07003915 # main.log.debug( "app response: " + repr( output ) )
Jon Hallbe379602015-03-24 13:39:32 -07003916 return main.TRUE
You Wangb5a55f72017-03-03 12:51:05 -08003917 except AssertionError:
3918 main.log.exception( self.name + ": AssertionError exception found" )
3919 return main.ERROR
Jon Hallbe379602015-03-24 13:39:32 -07003920 except TypeError:
3921 main.log.exception( self.name + ": Object not as expected" )
3922 return main.ERROR
3923 except pexpect.EOF:
3924 main.log.error( self.name + ": EOF exception found" )
3925 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003926 main.cleanAndExit()
Jon Hall77ba41c2015-04-06 10:25:40 -07003927 except Exception:
Jon Hallbe379602015-03-24 13:39:32 -07003928 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003929 main.cleanAndExit()
Jon Hall146f1522015-03-24 15:33:24 -07003930
Jon Hallbd16b922015-03-26 17:53:15 -07003931 def activateApp( self, appName, check=True ):
Jon Hall146f1522015-03-24 15:33:24 -07003932 """
3933 Activate an app that is already installed in ONOS
Jon Hallbd16b922015-03-26 17:53:15 -07003934 appName is the hierarchical app name, not the feature name
3935 If check is True, method will check the status of the app after the
3936 command is issued
Jon Hall146f1522015-03-24 15:33:24 -07003937 Returns main.TRUE if the command was successfully sent
3938 main.FALSE if the cli responded with an error or given
3939 incorrect input
3940 """
3941 try:
3942 if not isinstance( appName, types.StringType ):
3943 main.log.error( self.name + ".activateApp(): appName must be" +
3944 " a string" )
3945 return main.FALSE
3946 status = self.appStatus( appName )
3947 if status == "INSTALLED":
3948 response = self.app( appName, "activate" )
Jon Hallbd16b922015-03-26 17:53:15 -07003949 if check and response == main.TRUE:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003950 for i in range( 10 ): # try 10 times then give up
Jon Hallbd16b922015-03-26 17:53:15 -07003951 status = self.appStatus( appName )
3952 if status == "ACTIVE":
3953 return main.TRUE
3954 else:
Jon Hall050e1bd2015-03-30 13:33:02 -07003955 main.log.debug( "The state of application " +
3956 appName + " is " + status )
Jon Hallbd16b922015-03-26 17:53:15 -07003957 time.sleep( 1 )
3958 return main.FALSE
3959 else: # not 'check' or command didn't succeed
3960 return response
Jon Hall146f1522015-03-24 15:33:24 -07003961 elif status == "ACTIVE":
3962 return main.TRUE
3963 elif status == "UNINSTALLED":
3964 main.log.error( self.name + ": Tried to activate the " +
3965 "application '" + appName + "' which is not " +
3966 "installed." )
3967 else:
3968 main.log.error( "Unexpected return value from appStatus: " +
3969 str( status ) )
3970 return main.ERROR
3971 except TypeError:
3972 main.log.exception( self.name + ": Object not as expected" )
3973 return main.ERROR
3974 except pexpect.EOF:
3975 main.log.error( self.name + ": EOF exception found" )
3976 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003977 main.cleanAndExit()
Jon Hall77ba41c2015-04-06 10:25:40 -07003978 except Exception:
Jon Hall146f1522015-03-24 15:33:24 -07003979 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003980 main.cleanAndExit()
Jon Hall146f1522015-03-24 15:33:24 -07003981
Jon Hallbd16b922015-03-26 17:53:15 -07003982 def deactivateApp( self, appName, check=True ):
Jon Hall146f1522015-03-24 15:33:24 -07003983 """
3984 Deactivate an app that is already activated in ONOS
Jon Hallbd16b922015-03-26 17:53:15 -07003985 appName is the hierarchical app name, not the feature name
3986 If check is True, method will check the status of the app after the
3987 command is issued
Jon Hall146f1522015-03-24 15:33:24 -07003988 Returns main.TRUE if the command was successfully sent
3989 main.FALSE if the cli responded with an error or given
3990 incorrect input
3991 """
3992 try:
3993 if not isinstance( appName, types.StringType ):
3994 main.log.error( self.name + ".deactivateApp(): appName must " +
3995 "be a string" )
3996 return main.FALSE
3997 status = self.appStatus( appName )
3998 if status == "INSTALLED":
3999 return main.TRUE
4000 elif status == "ACTIVE":
4001 response = self.app( appName, "deactivate" )
Jon Hallbd16b922015-03-26 17:53:15 -07004002 if check and response == main.TRUE:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07004003 for i in range( 10 ): # try 10 times then give up
Jon Hallbd16b922015-03-26 17:53:15 -07004004 status = self.appStatus( appName )
4005 if status == "INSTALLED":
4006 return main.TRUE
4007 else:
4008 time.sleep( 1 )
4009 return main.FALSE
4010 else: # not check or command didn't succeed
4011 return response
Jon Hall146f1522015-03-24 15:33:24 -07004012 elif status == "UNINSTALLED":
4013 main.log.warn( self.name + ": Tried to deactivate the " +
4014 "application '" + appName + "' which is not " +
4015 "installed." )
4016 return main.TRUE
4017 else:
4018 main.log.error( "Unexpected return value from appStatus: " +
4019 str( status ) )
4020 return main.ERROR
4021 except TypeError:
4022 main.log.exception( self.name + ": Object not as expected" )
4023 return main.ERROR
4024 except pexpect.EOF:
4025 main.log.error( self.name + ": EOF exception found" )
4026 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07004027 main.cleanAndExit()
Jon Hall77ba41c2015-04-06 10:25:40 -07004028 except Exception:
Jon Hall146f1522015-03-24 15:33:24 -07004029 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07004030 main.cleanAndExit()
Jon Hall146f1522015-03-24 15:33:24 -07004031
Jon Hallbd16b922015-03-26 17:53:15 -07004032 def uninstallApp( self, appName, check=True ):
Jon Hall146f1522015-03-24 15:33:24 -07004033 """
4034 Uninstall an app that is already installed in ONOS
Jon Hallbd16b922015-03-26 17:53:15 -07004035 appName is the hierarchical app name, not the feature name
4036 If check is True, method will check the status of the app after the
4037 command is issued
Jon Hall146f1522015-03-24 15:33:24 -07004038 Returns main.TRUE if the command was successfully sent
4039 main.FALSE if the cli responded with an error or given
4040 incorrect input
4041 """
4042 # TODO: check with Thomas about the state machine for apps
4043 try:
4044 if not isinstance( appName, types.StringType ):
4045 main.log.error( self.name + ".uninstallApp(): appName must " +
4046 "be a string" )
4047 return main.FALSE
4048 status = self.appStatus( appName )
4049 if status == "INSTALLED":
4050 response = self.app( appName, "uninstall" )
Jon Hallbd16b922015-03-26 17:53:15 -07004051 if check and response == main.TRUE:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07004052 for i in range( 10 ): # try 10 times then give up
Jon Hallbd16b922015-03-26 17:53:15 -07004053 status = self.appStatus( appName )
4054 if status == "UNINSTALLED":
4055 return main.TRUE
4056 else:
4057 time.sleep( 1 )
4058 return main.FALSE
4059 else: # not check or command didn't succeed
4060 return response
Jon Hall146f1522015-03-24 15:33:24 -07004061 elif status == "ACTIVE":
4062 main.log.warn( self.name + ": Tried to uninstall the " +
4063 "application '" + appName + "' which is " +
4064 "currently active." )
4065 response = self.app( appName, "uninstall" )
Jon Hallbd16b922015-03-26 17:53:15 -07004066 if check and response == main.TRUE:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07004067 for i in range( 10 ): # try 10 times then give up
Jon Hallbd16b922015-03-26 17:53:15 -07004068 status = self.appStatus( appName )
4069 if status == "UNINSTALLED":
4070 return main.TRUE
4071 else:
4072 time.sleep( 1 )
4073 return main.FALSE
4074 else: # not check or command didn't succeed
4075 return response
Jon Hall146f1522015-03-24 15:33:24 -07004076 elif status == "UNINSTALLED":
4077 return main.TRUE
4078 else:
4079 main.log.error( "Unexpected return value from appStatus: " +
4080 str( status ) )
4081 return main.ERROR
4082 except TypeError:
4083 main.log.exception( self.name + ": Object not as expected" )
4084 return main.ERROR
4085 except pexpect.EOF:
4086 main.log.error( self.name + ": EOF exception found" )
4087 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07004088 main.cleanAndExit()
Jon Hall77ba41c2015-04-06 10:25:40 -07004089 except Exception:
Jon Hall146f1522015-03-24 15:33:24 -07004090 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07004091 main.cleanAndExit()
Jon Hallbd16b922015-03-26 17:53:15 -07004092
4093 def appIDs( self, jsonFormat=True ):
4094 """
4095 Show the mappings between app id and app names given by the 'app-ids'
4096 cli command
4097 """
4098 try:
4099 cmdStr = "app-ids"
4100 if jsonFormat:
4101 cmdStr += " -j"
Jon Hallc6358dd2015-04-10 12:44:28 -07004102 output = self.sendline( cmdStr )
Jon Halla495f562016-05-16 18:03:26 -07004103 assert output is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08004104 assert "Command not found:" not in output, output
4105 assert "Error executing command" not in output, output
Jon Hallc6358dd2015-04-10 12:44:28 -07004106 return output
Jon Hallbd16b922015-03-26 17:53:15 -07004107 except AssertionError:
Jon Hall0e240372018-05-02 11:21:57 -07004108 main.log.exception( self.name + ": Error in processing onos:app-ids command." )
Jon Hallbd16b922015-03-26 17:53:15 -07004109 return None
4110 except TypeError:
4111 main.log.exception( self.name + ": Object not as expected" )
4112 return None
4113 except pexpect.EOF:
4114 main.log.error( self.name + ": EOF exception found" )
4115 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07004116 main.cleanAndExit()
Jon Hall77ba41c2015-04-06 10:25:40 -07004117 except Exception:
Jon Hallbd16b922015-03-26 17:53:15 -07004118 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07004119 main.cleanAndExit()
Jon Hallbd16b922015-03-26 17:53:15 -07004120
4121 def appToIDCheck( self ):
4122 """
4123 This method will check that each application's ID listed in 'apps' is
4124 the same as the ID listed in 'app-ids'. The check will also check that
4125 there are no duplicate IDs issued. Note that an app ID should be
4126 a globaly unique numerical identifier for app/app-like features. Once
4127 an ID is registered, the ID is never freed up so that if an app is
4128 reinstalled it will have the same ID.
4129
4130 Returns: main.TRUE if the check passes and
4131 main.FALSE if the check fails or
4132 main.ERROR if there is some error in processing the test
4133 """
4134 try:
Jon Hall0e240372018-05-02 11:21:57 -07004135 # Grab IDs
Jon Hallc6793552016-01-19 14:18:37 -08004136 rawJson = self.appIDs( jsonFormat=True )
4137 if rawJson:
4138 ids = json.loads( rawJson )
Jon Hall390696c2015-05-05 17:13:41 -07004139 else:
Jon Hall0e240372018-05-02 11:21:57 -07004140 main.log.error( "app-ids returned nothing: " + repr( rawJson ) )
4141 return main.FALSE
4142
4143 # Grab Apps
Jon Hallc6793552016-01-19 14:18:37 -08004144 rawJson = self.apps( jsonFormat=True )
4145 if rawJson:
4146 apps = json.loads( rawJson )
Jon Hall390696c2015-05-05 17:13:41 -07004147 else:
Jon Hallc6793552016-01-19 14:18:37 -08004148 main.log.error( "apps returned nothing:" + repr( rawJson ) )
Jon Hall390696c2015-05-05 17:13:41 -07004149 return main.FALSE
Jon Hall0e240372018-05-02 11:21:57 -07004150
Jon Hallbd16b922015-03-26 17:53:15 -07004151 result = main.TRUE
4152 for app in apps:
4153 appID = app.get( 'id' )
4154 if appID is None:
4155 main.log.error( "Error parsing app: " + str( app ) )
4156 result = main.FALSE
4157 appName = app.get( 'name' )
4158 if appName is None:
4159 main.log.error( "Error parsing app: " + str( app ) )
4160 result = main.FALSE
4161 # get the entry in ids that has the same appID
Jon Hall390696c2015-05-05 17:13:41 -07004162 current = filter( lambda item: item[ 'id' ] == appID, ids )
Jon Hallbd16b922015-03-26 17:53:15 -07004163 if not current: # if ids doesn't have this id
4164 result = main.FALSE
4165 main.log.error( "'app-ids' does not have the ID for " +
4166 str( appName ) + " that apps does." )
Jon Hallb9d381e2018-02-05 12:02:10 -08004167 main.log.debug( "apps command returned: " + str( app ) +
4168 "; app-ids has: " + str( ids ) )
Jon Hallbd16b922015-03-26 17:53:15 -07004169 elif len( current ) > 1:
4170 # there is more than one app with this ID
4171 result = main.FALSE
4172 # We will log this later in the method
Jeremy Ronquillo82705492017-10-18 14:19:55 -07004173 elif not current[ 0 ][ 'name' ] == appName:
4174 currentName = current[ 0 ][ 'name' ]
Jon Hallbd16b922015-03-26 17:53:15 -07004175 result = main.FALSE
4176 main.log.error( "'app-ids' has " + str( currentName ) +
4177 " registered under id:" + str( appID ) +
4178 " but 'apps' has " + str( appName ) )
4179 else:
4180 pass # id and name match!
Jon Hall0e240372018-05-02 11:21:57 -07004181
Jon Hallbd16b922015-03-26 17:53:15 -07004182 # now make sure that app-ids has no duplicates
4183 idsList = []
4184 namesList = []
4185 for item in ids:
4186 idsList.append( item[ 'id' ] )
4187 namesList.append( item[ 'name' ] )
4188 if len( idsList ) != len( set( idsList ) ) or\
4189 len( namesList ) != len( set( namesList ) ):
Jeremy Ronquillo82705492017-10-18 14:19:55 -07004190 main.log.error( "'app-ids' has some duplicate entries: \n"
4191 + json.dumps( ids,
4192 sort_keys=True,
4193 indent=4,
4194 separators=( ',', ': ' ) ) )
4195 result = main.FALSE
Jon Hallbd16b922015-03-26 17:53:15 -07004196 return result
Jon Hallc6793552016-01-19 14:18:37 -08004197 except ( TypeError, ValueError ):
4198 main.log.exception( "{}: Object not as expected: {!r}".format( self.name, rawJson ) )
Jon Hallbd16b922015-03-26 17:53:15 -07004199 return main.ERROR
4200 except pexpect.EOF:
4201 main.log.error( self.name + ": EOF exception found" )
4202 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07004203 main.cleanAndExit()
Jon Hall77ba41c2015-04-06 10:25:40 -07004204 except Exception:
Jon Hallbd16b922015-03-26 17:53:15 -07004205 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07004206 main.cleanAndExit()
Jon Hallbd16b922015-03-26 17:53:15 -07004207
Jon Hallfb760a02015-04-13 15:35:03 -07004208 def getCfg( self, component=None, propName=None, short=False,
4209 jsonFormat=True ):
4210 """
4211 Get configuration settings from onos cli
4212 Optional arguments:
4213 component - Optionally only list configurations for a specific
4214 component. If None, all components with configurations
4215 are displayed. Case Sensitive string.
4216 propName - If component is specified, propName option will show
4217 only this specific configuration from that component.
4218 Case Sensitive string.
4219 jsonFormat - Returns output as json. Note that this will override
4220 the short option
4221 short - Short, less verbose, version of configurations.
4222 This is overridden by the json option
4223 returns:
4224 Output from cli as a string or None on error
4225 """
4226 try:
4227 baseStr = "cfg"
4228 cmdStr = " get"
4229 componentStr = ""
4230 if component:
4231 componentStr += " " + component
4232 if propName:
4233 componentStr += " " + propName
4234 if jsonFormat:
4235 baseStr += " -j"
Jon Hall22e94ce2019-01-15 14:52:17 -08004236 expectJson = True
Jon Hallfb760a02015-04-13 15:35:03 -07004237 elif short:
4238 baseStr += " -s"
Jon Hall22e94ce2019-01-15 14:52:17 -08004239 expectJson = False
4240 output = self.sendline( baseStr + cmdStr + componentStr, expectJson=expectJson )
Jon Halla495f562016-05-16 18:03:26 -07004241 assert output is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08004242 assert "Command not found:" not in output, output
4243 assert "Error executing command" not in output, output
Jon Hallfb760a02015-04-13 15:35:03 -07004244 return output
4245 except AssertionError:
Jon Hall0e240372018-05-02 11:21:57 -07004246 main.log.exception( self.name + ": Error in processing 'cfg get' command." )
Jon Hallfb760a02015-04-13 15:35:03 -07004247 return None
4248 except TypeError:
4249 main.log.exception( self.name + ": Object not as expected" )
4250 return None
4251 except pexpect.EOF:
4252 main.log.error( self.name + ": EOF exception found" )
4253 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07004254 main.cleanAndExit()
Jon Hallfb760a02015-04-13 15:35:03 -07004255 except Exception:
4256 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07004257 main.cleanAndExit()
Jon Hallfb760a02015-04-13 15:35:03 -07004258
4259 def setCfg( self, component, propName, value=None, check=True ):
4260 """
4261 Set/Unset configuration settings from ONOS cli
Jon Hall390696c2015-05-05 17:13:41 -07004262 Required arguments:
Jon Hallfb760a02015-04-13 15:35:03 -07004263 component - The case sensitive name of the component whose
4264 property is to be set
4265 propName - The case sensitive name of the property to be set/unset
Jon Hall390696c2015-05-05 17:13:41 -07004266 Optional arguments:
Jon Hallfb760a02015-04-13 15:35:03 -07004267 value - The value to set the property to. If None, will unset the
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00004268 property and revert it to it's default value(if applicable)
Jon Hallfb760a02015-04-13 15:35:03 -07004269 check - Boolean, Check whether the option was successfully set this
4270 only applies when a value is given.
4271 returns:
4272 main.TRUE on success or main.FALSE on failure. If check is False,
4273 will return main.TRUE unless there is an error
4274 """
4275 try:
4276 baseStr = "cfg"
4277 cmdStr = " set " + str( component ) + " " + str( propName )
4278 if value is not None:
4279 cmdStr += " " + str( value )
4280 output = self.sendline( baseStr + cmdStr )
Jon Halla495f562016-05-16 18:03:26 -07004281 assert output is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08004282 assert "Command not found:" not in output, output
4283 assert "Error executing command" not in output, output
Jon Hallfb760a02015-04-13 15:35:03 -07004284 if value and check:
4285 results = self.getCfg( component=str( component ),
4286 propName=str( propName ),
4287 jsonFormat=True )
4288 # Check if current value is what we just set
4289 try:
4290 jsonOutput = json.loads( results )
4291 current = jsonOutput[ 'value' ]
Jon Hallc6793552016-01-19 14:18:37 -08004292 except ( TypeError, ValueError ):
Jon Hallfb760a02015-04-13 15:35:03 -07004293 main.log.exception( "Error parsing cfg output" )
4294 main.log.error( "output:" + repr( results ) )
4295 return main.FALSE
4296 if current == str( value ):
4297 return main.TRUE
4298 return main.FALSE
4299 return main.TRUE
4300 except AssertionError:
Jon Hall0e240372018-05-02 11:21:57 -07004301 main.log.exception( self.name + ": Error in processing 'cfg set' command." )
Jon Hallfb760a02015-04-13 15:35:03 -07004302 return main.FALSE
Jon Hallc6793552016-01-19 14:18:37 -08004303 except ( TypeError, ValueError ):
4304 main.log.exception( "{}: Object not as expected: {!r}".format( self.name, results ) )
Jon Hallfb760a02015-04-13 15:35:03 -07004305 return main.FALSE
4306 except pexpect.EOF:
4307 main.log.error( self.name + ": EOF exception found" )
4308 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07004309 main.cleanAndExit()
Jon Hallfb760a02015-04-13 15:35:03 -07004310 except Exception:
4311 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07004312 main.cleanAndExit()
Jon Hallfb760a02015-04-13 15:35:03 -07004313
Jon Hall7a6ebfd2017-03-13 10:58:58 -07004314 def distPrimitivesSend( self, cmd ):
4315 """
4316 Function to handle sending cli commands for the distributed primitives test app
4317
4318 This command will catch some exceptions and retry the command on some
4319 specific store exceptions.
4320
4321 Required arguments:
4322 cmd - The command to send to the cli
4323 returns:
4324 string containing the cli output
4325 None on Error
4326 """
4327 try:
4328 output = self.sendline( cmd )
4329 try:
4330 assert output is not None, "Error in sendline"
4331 # TODO: Maybe make this less hardcoded
4332 # ConsistentMap Exceptions
4333 assert "org.onosproject.store.service" not in output
4334 # Node not leader
4335 assert "java.lang.IllegalStateException" not in output
4336 except AssertionError:
Jon Hall0e240372018-05-02 11:21:57 -07004337 main.log.error( self.name + ": Error in processing '" + cmd + "' " +
Jon Hall7a6ebfd2017-03-13 10:58:58 -07004338 "command: " + str( output ) )
4339 retryTime = 30 # Conservative time, given by Madan
4340 main.log.info( "Waiting " + str( retryTime ) +
4341 "seconds before retrying." )
4342 time.sleep( retryTime ) # Due to change in mastership
4343 output = self.sendline( cmd )
4344 assert output is not None, "Error in sendline"
4345 assert "Command not found:" not in output, output
4346 assert "Error executing command" not in output, output
4347 main.log.info( self.name + ": " + output )
4348 return output
4349 except AssertionError:
Jon Hall0e240372018-05-02 11:21:57 -07004350 main.log.exception( self.name + ": Error in processing '" + cmd + "' command." )
Jon Hall7a6ebfd2017-03-13 10:58:58 -07004351 return None
4352 except TypeError:
4353 main.log.exception( self.name + ": Object not as expected" )
4354 return None
4355 except pexpect.EOF:
4356 main.log.error( self.name + ": EOF exception found" )
4357 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07004358 main.cleanAndExit()
Jon Hall7a6ebfd2017-03-13 10:58:58 -07004359 except Exception:
4360 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07004361 main.cleanAndExit()
Jon Hall7a6ebfd2017-03-13 10:58:58 -07004362
Jon Hall390696c2015-05-05 17:13:41 -07004363 def setTestAdd( self, setName, values ):
4364 """
4365 CLI command to add elements to a distributed set.
4366 Arguments:
4367 setName - The name of the set to add to.
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00004368 values - The value(s) to add to the set, space seperated.
Jon Hall390696c2015-05-05 17:13:41 -07004369 Example usages:
4370 setTestAdd( "set1", "a b c" )
4371 setTestAdd( "set2", "1" )
4372 returns:
4373 main.TRUE on success OR
4374 main.FALSE if elements were already in the set OR
4375 main.ERROR on error
4376 """
4377 try:
4378 cmdStr = "set-test-add " + str( setName ) + " " + str( values )
Jon Hall7a6ebfd2017-03-13 10:58:58 -07004379 output = self.distPrimitivesSend( cmdStr )
Jon Hall390696c2015-05-05 17:13:41 -07004380 positiveMatch = "\[(.*)\] was added to the set " + str( setName )
4381 negativeMatch = "\[(.*)\] was already in set " + str( setName )
Jeremy Ronquillo82705492017-10-18 14:19:55 -07004382 if re.search( positiveMatch, output ):
Jon Hall390696c2015-05-05 17:13:41 -07004383 return main.TRUE
Jeremy Ronquillo82705492017-10-18 14:19:55 -07004384 elif re.search( negativeMatch, output ):
Jon Hall390696c2015-05-05 17:13:41 -07004385 return main.FALSE
4386 else:
4387 main.log.error( self.name + ": setTestAdd did not" +
4388 " match expected output" )
Jon Hall390696c2015-05-05 17:13:41 -07004389 main.log.debug( self.name + " actual: " + repr( output ) )
4390 return main.ERROR
Jon Hall390696c2015-05-05 17:13:41 -07004391 except TypeError:
4392 main.log.exception( self.name + ": Object not as expected" )
4393 return main.ERROR
Jon Hall390696c2015-05-05 17:13:41 -07004394 except Exception:
4395 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07004396 main.cleanAndExit()
Jon Hall390696c2015-05-05 17:13:41 -07004397
4398 def setTestRemove( self, setName, values, clear=False, retain=False ):
4399 """
4400 CLI command to remove elements from a distributed set.
4401 Required arguments:
4402 setName - The name of the set to remove from.
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00004403 values - The value(s) to remove from the set, space seperated.
Jon Hall390696c2015-05-05 17:13:41 -07004404 Optional arguments:
4405 clear - Clear all elements from the set
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00004406 retain - Retain only the given values. (intersection of the
4407 original set and the given set)
Jon Hall390696c2015-05-05 17:13:41 -07004408 returns:
4409 main.TRUE on success OR
4410 main.FALSE if the set was not changed OR
4411 main.ERROR on error
4412 """
4413 try:
4414 cmdStr = "set-test-remove "
4415 if clear:
4416 cmdStr += "-c " + str( setName )
4417 elif retain:
4418 cmdStr += "-r " + str( setName ) + " " + str( values )
4419 else:
4420 cmdStr += str( setName ) + " " + str( values )
Jon Hall7a6ebfd2017-03-13 10:58:58 -07004421 output = self.distPrimitivesSend( cmdStr )
Jon Hall390696c2015-05-05 17:13:41 -07004422 if clear:
4423 pattern = "Set " + str( setName ) + " cleared"
4424 if re.search( pattern, output ):
4425 return main.TRUE
4426 elif retain:
4427 positivePattern = str( setName ) + " was pruned to contain " +\
4428 "only elements of set \[(.*)\]"
4429 negativePattern = str( setName ) + " was not changed by " +\
4430 "retaining only elements of the set " +\
4431 "\[(.*)\]"
4432 if re.search( positivePattern, output ):
4433 return main.TRUE
4434 elif re.search( negativePattern, output ):
4435 return main.FALSE
4436 else:
4437 positivePattern = "\[(.*)\] was removed from the set " +\
4438 str( setName )
4439 if ( len( values.split() ) == 1 ):
4440 negativePattern = "\[(.*)\] was not in set " +\
4441 str( setName )
4442 else:
4443 negativePattern = "No element of \[(.*)\] was in set " +\
4444 str( setName )
4445 if re.search( positivePattern, output ):
4446 return main.TRUE
4447 elif re.search( negativePattern, output ):
4448 return main.FALSE
4449 main.log.error( self.name + ": setTestRemove did not" +
4450 " match expected output" )
4451 main.log.debug( self.name + " expected: " + pattern )
4452 main.log.debug( self.name + " actual: " + repr( output ) )
4453 return main.ERROR
Jon Hall390696c2015-05-05 17:13:41 -07004454 except TypeError:
4455 main.log.exception( self.name + ": Object not as expected" )
4456 return main.ERROR
Jon Hall390696c2015-05-05 17:13:41 -07004457 except Exception:
4458 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07004459 main.cleanAndExit()
Jon Hall390696c2015-05-05 17:13:41 -07004460
4461 def setTestGet( self, setName, values="" ):
4462 """
4463 CLI command to get the elements in a distributed set.
4464 Required arguments:
4465 setName - The name of the set to remove from.
4466 Optional arguments:
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00004467 values - The value(s) to check if in the set, space seperated.
Jon Hall390696c2015-05-05 17:13:41 -07004468 returns:
4469 main.ERROR on error OR
4470 A list of elements in the set if no optional arguments are
4471 supplied OR
4472 A tuple containing the list then:
4473 main.FALSE if the given values are not in the set OR
4474 main.TRUE if the given values are in the set OR
4475 """
4476 try:
4477 values = str( values ).strip()
4478 setName = str( setName ).strip()
4479 length = len( values.split() )
4480 containsCheck = None
4481 # Patterns to match
4482 setPattern = "\[(.*)\]"
Jon Hall67253832016-12-05 09:47:13 -08004483 pattern = "Items in set " + setName + ":\r\n" + setPattern
Jon Hall390696c2015-05-05 17:13:41 -07004484 containsTrue = "Set " + setName + " contains the value " + values
4485 containsFalse = "Set " + setName + " did not contain the value " +\
4486 values
4487 containsAllTrue = "Set " + setName + " contains the the subset " +\
4488 setPattern
4489 containsAllFalse = "Set " + setName + " did not contain the the" +\
4490 " subset " + setPattern
4491
4492 cmdStr = "set-test-get "
4493 cmdStr += setName + " " + values
Jon Hall7a6ebfd2017-03-13 10:58:58 -07004494 output = self.distPrimitivesSend( cmdStr )
Jon Hall390696c2015-05-05 17:13:41 -07004495 if length == 0:
4496 match = re.search( pattern, output )
4497 else: # if given values
4498 if length == 1: # Contains output
Jon Hall54b994f2016-12-05 10:48:59 -08004499 patternTrue = pattern + "\r\n" + containsTrue
4500 patternFalse = pattern + "\r\n" + containsFalse
Jon Hall390696c2015-05-05 17:13:41 -07004501 else: # ContainsAll output
Jon Hall54b994f2016-12-05 10:48:59 -08004502 patternTrue = pattern + "\r\n" + containsAllTrue
4503 patternFalse = pattern + "\r\n" + containsAllFalse
Jon Hall390696c2015-05-05 17:13:41 -07004504 matchTrue = re.search( patternTrue, output )
4505 matchFalse = re.search( patternFalse, output )
4506 if matchTrue:
4507 containsCheck = main.TRUE
4508 match = matchTrue
4509 elif matchFalse:
4510 containsCheck = main.FALSE
4511 match = matchFalse
4512 else:
Jon Halle0f0b342017-04-18 11:43:47 -07004513 main.log.error( self.name + " setTestGet did not match " +
Jon Hall390696c2015-05-05 17:13:41 -07004514 "expected output" )
4515 main.log.debug( self.name + " expected: " + pattern )
4516 main.log.debug( self.name + " actual: " + repr( output ) )
4517 match = None
4518 if match:
4519 setMatch = match.group( 1 )
4520 if setMatch == '':
4521 setList = []
4522 else:
4523 setList = setMatch.split( ", " )
4524 if length > 0:
4525 return ( setList, containsCheck )
4526 else:
4527 return setList
4528 else: # no match
4529 main.log.error( self.name + ": setTestGet did not" +
4530 " match expected output" )
4531 main.log.debug( self.name + " expected: " + pattern )
4532 main.log.debug( self.name + " actual: " + repr( output ) )
4533 return main.ERROR
Jon Hall390696c2015-05-05 17:13:41 -07004534 except TypeError:
4535 main.log.exception( self.name + ": Object not as expected" )
4536 return main.ERROR
Jon Hall390696c2015-05-05 17:13:41 -07004537 except Exception:
4538 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07004539 main.cleanAndExit()
Jon Hall390696c2015-05-05 17:13:41 -07004540
4541 def setTestSize( self, setName ):
4542 """
4543 CLI command to get the elements in a distributed set.
4544 Required arguments:
4545 setName - The name of the set to remove from.
4546 returns:
Jon Hallfeff3082015-05-19 10:23:26 -07004547 The integer value of the size returned or
Jon Hall390696c2015-05-05 17:13:41 -07004548 None on error
4549 """
4550 try:
4551 # TODO: Should this check against the number of elements returned
4552 # and then return true/false based on that?
4553 setName = str( setName ).strip()
4554 # Patterns to match
4555 setPattern = "\[(.*)\]"
Jon Hall67253832016-12-05 09:47:13 -08004556 pattern = "There are (\d+) items in set " + setName + ":\r\n" +\
Jon Hall390696c2015-05-05 17:13:41 -07004557 setPattern
4558 cmdStr = "set-test-get -s "
4559 cmdStr += setName
Jon Hall7a6ebfd2017-03-13 10:58:58 -07004560 output = self.distPrimitivesSend( cmdStr )
Jon Hall0e240372018-05-02 11:21:57 -07004561 if output:
4562 match = re.search( pattern, output )
4563 if match:
4564 setSize = int( match.group( 1 ) )
4565 setMatch = match.group( 2 )
4566 if len( setMatch.split() ) == setSize:
4567 main.log.info( "The size returned by " + self.name +
4568 " matches the number of elements in " +
4569 "the returned set" )
4570 else:
4571 main.log.error( "The size returned by " + self.name +
4572 " does not match the number of " +
4573 "elements in the returned set." )
4574 return setSize
Jon Hall390696c2015-05-05 17:13:41 -07004575 else: # no match
4576 main.log.error( self.name + ": setTestGet did not" +
4577 " match expected output" )
4578 main.log.debug( self.name + " expected: " + pattern )
4579 main.log.debug( self.name + " actual: " + repr( output ) )
4580 return None
Jon Hall390696c2015-05-05 17:13:41 -07004581 except TypeError:
4582 main.log.exception( self.name + ": Object not as expected" )
4583 return None
Jon Hall390696c2015-05-05 17:13:41 -07004584 except Exception:
4585 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07004586 main.cleanAndExit()
Jon Hall390696c2015-05-05 17:13:41 -07004587
Jon Hall80daded2015-05-27 16:07:00 -07004588 def counters( self, jsonFormat=True ):
Jon Hall390696c2015-05-05 17:13:41 -07004589 """
4590 Command to list the various counters in the system.
4591 returns:
Jon Hall80daded2015-05-27 16:07:00 -07004592 if jsonFormat, a string of the json object returned by the cli
4593 command
4594 if not jsonFormat, the normal string output of the cli command
Jon Hall390696c2015-05-05 17:13:41 -07004595 None on error
4596 """
Jon Hall390696c2015-05-05 17:13:41 -07004597 try:
Jon Hall390696c2015-05-05 17:13:41 -07004598 cmdStr = "counters"
Jon Hall80daded2015-05-27 16:07:00 -07004599 if jsonFormat:
4600 cmdStr += " -j"
Jon Hall390696c2015-05-05 17:13:41 -07004601 output = self.sendline( cmdStr )
Jon Hall22e94ce2019-01-15 14:52:17 -08004602 main.log.debug( self.name + ": Counters unparsed: " + output )
4603 output = output.split( "\r\n" )[ -1 ]
4604 main.log.debug( self.name + ": Counters parsed: " + output )
Jon Halla495f562016-05-16 18:03:26 -07004605 assert output is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08004606 assert "Command not found:" not in output, output
4607 assert "Error executing command" not in output, output
Jon Hall390696c2015-05-05 17:13:41 -07004608 main.log.info( self.name + ": " + output )
Jon Hall80daded2015-05-27 16:07:00 -07004609 return output
Jon Hall390696c2015-05-05 17:13:41 -07004610 except AssertionError:
Jon Hall0e240372018-05-02 11:21:57 -07004611 main.log.exception( self.name + ": Error in processing 'counters' command." )
Jon Hall80daded2015-05-27 16:07:00 -07004612 return None
Jon Hall390696c2015-05-05 17:13:41 -07004613 except TypeError:
4614 main.log.exception( self.name + ": Object not as expected" )
Jon Hall80daded2015-05-27 16:07:00 -07004615 return None
Jon Hall390696c2015-05-05 17:13:41 -07004616 except pexpect.EOF:
4617 main.log.error( self.name + ": EOF exception found" )
4618 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07004619 main.cleanAndExit()
Jon Hall390696c2015-05-05 17:13:41 -07004620 except Exception:
4621 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07004622 main.cleanAndExit()
Jon Hall390696c2015-05-05 17:13:41 -07004623
Jon Hall935db192016-04-19 00:22:04 -07004624 def counterTestAddAndGet( self, counter, delta=1 ):
Jon Hall390696c2015-05-05 17:13:41 -07004625 """
Jon Halle1a3b752015-07-22 13:02:46 -07004626 CLI command to add a delta to then get a distributed counter.
Jon Hall390696c2015-05-05 17:13:41 -07004627 Required arguments:
4628 counter - The name of the counter to increment.
4629 Optional arguments:
Jon Halle1a3b752015-07-22 13:02:46 -07004630 delta - The long to add to the counter
Jon Hall390696c2015-05-05 17:13:41 -07004631 returns:
4632 integer value of the counter or
4633 None on Error
4634 """
4635 try:
4636 counter = str( counter )
Jon Halle1a3b752015-07-22 13:02:46 -07004637 delta = int( delta )
Jon Hall390696c2015-05-05 17:13:41 -07004638 cmdStr = "counter-test-increment "
Jon Hall390696c2015-05-05 17:13:41 -07004639 cmdStr += counter
Jon Halle1a3b752015-07-22 13:02:46 -07004640 if delta != 1:
4641 cmdStr += " " + str( delta )
Jon Hall7a6ebfd2017-03-13 10:58:58 -07004642 output = self.distPrimitivesSend( cmdStr )
Jon Halle1a3b752015-07-22 13:02:46 -07004643 pattern = counter + " was updated to (-?\d+)"
Jon Hall390696c2015-05-05 17:13:41 -07004644 match = re.search( pattern, output )
4645 if match:
4646 return int( match.group( 1 ) )
4647 else:
Jon Halle1a3b752015-07-22 13:02:46 -07004648 main.log.error( self.name + ": counterTestAddAndGet did not" +
Jon Hall390696c2015-05-05 17:13:41 -07004649 " match expected output." )
4650 main.log.debug( self.name + " expected: " + pattern )
4651 main.log.debug( self.name + " actual: " + repr( output ) )
4652 return None
Jon Hall390696c2015-05-05 17:13:41 -07004653 except TypeError:
4654 main.log.exception( self.name + ": Object not as expected" )
4655 return None
Jon Hall390696c2015-05-05 17:13:41 -07004656 except Exception:
4657 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07004658 main.cleanAndExit()
Jon Hall390696c2015-05-05 17:13:41 -07004659
Jon Hall935db192016-04-19 00:22:04 -07004660 def counterTestGetAndAdd( self, counter, delta=1 ):
Jon Halle1a3b752015-07-22 13:02:46 -07004661 """
4662 CLI command to get a distributed counter then add a delta to it.
4663 Required arguments:
4664 counter - The name of the counter to increment.
4665 Optional arguments:
4666 delta - The long to add to the counter
Jon Halle1a3b752015-07-22 13:02:46 -07004667 returns:
4668 integer value of the counter or
4669 None on Error
4670 """
4671 try:
4672 counter = str( counter )
4673 delta = int( delta )
4674 cmdStr = "counter-test-increment -g "
Jon Halle1a3b752015-07-22 13:02:46 -07004675 cmdStr += counter
4676 if delta != 1:
4677 cmdStr += " " + str( delta )
Jon Hall7a6ebfd2017-03-13 10:58:58 -07004678 output = self.distPrimitivesSend( cmdStr )
Jon Halle1a3b752015-07-22 13:02:46 -07004679 pattern = counter + " was updated to (-?\d+)"
4680 match = re.search( pattern, output )
4681 if match:
4682 return int( match.group( 1 ) )
4683 else:
4684 main.log.error( self.name + ": counterTestGetAndAdd did not" +
4685 " match expected output." )
4686 main.log.debug( self.name + " expected: " + pattern )
4687 main.log.debug( self.name + " actual: " + repr( output ) )
4688 return None
Jon Halle1a3b752015-07-22 13:02:46 -07004689 except TypeError:
4690 main.log.exception( self.name + ": Object not as expected" )
4691 return None
Jon Hall7a6ebfd2017-03-13 10:58:58 -07004692 except Exception:
4693 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07004694 main.cleanAndExit()
Jon Hall7a6ebfd2017-03-13 10:58:58 -07004695
4696 def valueTestGet( self, valueName ):
4697 """
4698 CLI command to get the value of an atomic value.
4699 Required arguments:
4700 valueName - The name of the value to get.
4701 returns:
4702 string value of the value or
4703 None on Error
4704 """
4705 try:
4706 valueName = str( valueName )
4707 cmdStr = "value-test "
4708 operation = "get"
4709 cmdStr = "value-test {} {}".format( valueName,
4710 operation )
4711 output = self.distPrimitivesSend( cmdStr )
Jon Hall22e94ce2019-01-15 14:52:17 -08004712 main.log.debug( self.name + ": value test unparsed: " + output )
4713 output = output.split( "\r\n" )[ -1 ]
4714 main.log.debug( self.name + ": value test parsed: " + output )
Jon Hall7a6ebfd2017-03-13 10:58:58 -07004715 pattern = "(\w+)"
4716 match = re.search( pattern, output )
4717 if match:
4718 return match.group( 1 )
4719 else:
4720 main.log.error( self.name + ": valueTestGet did not" +
4721 " match expected output." )
4722 main.log.debug( self.name + " expected: " + pattern )
4723 main.log.debug( self.name + " actual: " + repr( output ) )
4724 return None
4725 except TypeError:
4726 main.log.exception( self.name + ": Object not as expected" )
4727 return None
4728 except Exception:
4729 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07004730 main.cleanAndExit()
Jon Hall7a6ebfd2017-03-13 10:58:58 -07004731
4732 def valueTestSet( self, valueName, newValue ):
4733 """
4734 CLI command to set the value of an atomic value.
4735 Required arguments:
4736 valueName - The name of the value to set.
4737 newValue - The value to assign to the given value.
4738 returns:
4739 main.TRUE on success or
4740 main.ERROR on Error
4741 """
4742 try:
4743 valueName = str( valueName )
4744 newValue = str( newValue )
4745 operation = "set"
4746 cmdStr = "value-test {} {} {}".format( valueName,
4747 operation,
4748 newValue )
4749 output = self.distPrimitivesSend( cmdStr )
4750 if output is not None:
4751 return main.TRUE
4752 else:
4753 return main.ERROR
4754 except TypeError:
4755 main.log.exception( self.name + ": Object not as expected" )
4756 return main.ERROR
4757 except Exception:
4758 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07004759 main.cleanAndExit()
Jon Hall7a6ebfd2017-03-13 10:58:58 -07004760
4761 def valueTestCompareAndSet( self, valueName, oldValue, newValue ):
4762 """
4763 CLI command to compareAndSet the value of an atomic value.
4764 Required arguments:
4765 valueName - The name of the value.
4766 oldValue - Compare the current value of the atomic value to this
4767 newValue - If the value equals oldValue, set the value to newValue
4768 returns:
4769 main.TRUE on success or
4770 main.FALSE on failure or
4771 main.ERROR on Error
4772 """
4773 try:
4774 valueName = str( valueName )
4775 oldValue = str( oldValue )
4776 newValue = str( newValue )
4777 operation = "compareAndSet"
4778 cmdStr = "value-test {} {} {} {}".format( valueName,
4779 operation,
4780 oldValue,
4781 newValue )
4782 output = self.distPrimitivesSend( cmdStr )
4783 pattern = "(\w+)"
4784 match = re.search( pattern, output )
4785 if match:
4786 result = match.group( 1 )
4787 if result == "true":
4788 return main.TRUE
4789 elif result == "false":
4790 return main.FALSE
4791 else:
4792 main.log.error( self.name + ": valueTestCompareAndSet did not" +
4793 " match expected output." )
4794 main.log.debug( self.name + " expected: " + pattern )
4795 main.log.debug( self.name + " actual: " + repr( output ) )
4796 return main.ERROR
4797 except TypeError:
4798 main.log.exception( self.name + ": Object not as expected" )
4799 return main.ERROR
4800 except Exception:
4801 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07004802 main.cleanAndExit()
Jon Hall7a6ebfd2017-03-13 10:58:58 -07004803
4804 def valueTestGetAndSet( self, valueName, newValue ):
4805 """
4806 CLI command to getAndSet the value of an atomic value.
4807 Required arguments:
4808 valueName - The name of the value to get.
4809 newValue - The value to assign to the given value
4810 returns:
4811 string value of the value or
4812 None on Error
4813 """
4814 try:
4815 valueName = str( valueName )
4816 cmdStr = "value-test "
4817 operation = "getAndSet"
4818 cmdStr += valueName + " " + operation
4819 cmdStr = "value-test {} {} {}".format( valueName,
4820 operation,
4821 newValue )
4822 output = self.distPrimitivesSend( cmdStr )
4823 pattern = "(\w+)"
4824 match = re.search( pattern, output )
4825 if match:
4826 return match.group( 1 )
4827 else:
4828 main.log.error( self.name + ": valueTestGetAndSet did not" +
4829 " match expected output." )
4830 main.log.debug( self.name + " expected: " + pattern )
4831 main.log.debug( self.name + " actual: " + repr( output ) )
4832 return None
4833 except TypeError:
4834 main.log.exception( self.name + ": Object not as expected" )
4835 return None
4836 except Exception:
4837 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07004838 main.cleanAndExit()
Jon Hall7a6ebfd2017-03-13 10:58:58 -07004839
4840 def valueTestDestroy( self, valueName ):
4841 """
4842 CLI command to destroy an atomic value.
4843 Required arguments:
4844 valueName - The name of the value to destroy.
4845 returns:
4846 main.TRUE on success or
4847 main.ERROR on Error
4848 """
4849 try:
4850 valueName = str( valueName )
4851 cmdStr = "value-test "
4852 operation = "destroy"
4853 cmdStr += valueName + " " + operation
4854 output = self.distPrimitivesSend( cmdStr )
4855 if output is not None:
4856 return main.TRUE
4857 else:
4858 return main.ERROR
4859 except TypeError:
4860 main.log.exception( self.name + ": Object not as expected" )
4861 return main.ERROR
Jon Halle1a3b752015-07-22 13:02:46 -07004862 except Exception:
4863 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07004864 main.cleanAndExit()
Jon Halle1a3b752015-07-22 13:02:46 -07004865
YPZhangfebf7302016-05-24 16:45:56 -07004866 def summary( self, jsonFormat=True, timeout=30 ):
kelvin-onlaba297c4d2015-06-01 13:53:55 -07004867 """
4868 Description: Execute summary command in onos
4869 Returns: json object ( summary -j ), returns main.FALSE if there is
4870 no output
4871
4872 """
4873 try:
4874 cmdStr = "summary"
4875 if jsonFormat:
4876 cmdStr += " -j"
YPZhangfebf7302016-05-24 16:45:56 -07004877 handle = self.sendline( cmdStr, timeout=timeout )
Jon Halla495f562016-05-16 18:03:26 -07004878 assert handle is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08004879 assert "Command not found:" not in handle, handle
Jon Hall6e709752016-02-01 13:38:46 -08004880 assert "Error:" not in handle, handle
Devin Lima7cfdbd2017-09-29 15:02:22 -07004881 assert "Error executing" not in handle, handle
kelvin-onlaba297c4d2015-06-01 13:53:55 -07004882 if not handle:
4883 main.log.error( self.name + ": There is no output in " +
4884 "summary command" )
4885 return main.FALSE
4886 return handle
Jon Hallc6793552016-01-19 14:18:37 -08004887 except AssertionError:
Jon Hall6e709752016-02-01 13:38:46 -08004888 main.log.exception( "{} Error in summary output:".format( self.name ) )
Jon Hallc6793552016-01-19 14:18:37 -08004889 return None
kelvin-onlaba297c4d2015-06-01 13:53:55 -07004890 except TypeError:
4891 main.log.exception( self.name + ": Object not as expected" )
4892 return None
4893 except pexpect.EOF:
4894 main.log.error( self.name + ": EOF exception found" )
4895 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07004896 main.cleanAndExit()
kelvin-onlaba297c4d2015-06-01 13:53:55 -07004897 except Exception:
4898 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07004899 main.cleanAndExit()
Jon Hall2a5002c2015-08-21 16:49:11 -07004900
Jon Hall935db192016-04-19 00:22:04 -07004901 def transactionalMapGet( self, keyName ):
Jon Hall2a5002c2015-08-21 16:49:11 -07004902 """
4903 CLI command to get the value of a key in a consistent map using
4904 transactions. This a test function and can only get keys from the
4905 test map hard coded into the cli command
4906 Required arguments:
4907 keyName - The name of the key to get
Jon Hall2a5002c2015-08-21 16:49:11 -07004908 returns:
4909 The string value of the key or
4910 None on Error
4911 """
4912 try:
4913 keyName = str( keyName )
4914 cmdStr = "transactional-map-test-get "
Jon Hall2a5002c2015-08-21 16:49:11 -07004915 cmdStr += keyName
Jon Hall7a6ebfd2017-03-13 10:58:58 -07004916 output = self.distPrimitivesSend( cmdStr )
Jon Hall2a5002c2015-08-21 16:49:11 -07004917 pattern = "Key-value pair \(" + keyName + ", (?P<value>.+)\) found."
4918 if "Key " + keyName + " not found." in output:
Jon Hall9bfadd22016-05-11 14:48:07 -07004919 main.log.warn( output )
Jon Hall2a5002c2015-08-21 16:49:11 -07004920 return None
4921 else:
4922 match = re.search( pattern, output )
4923 if match:
4924 return match.groupdict()[ 'value' ]
4925 else:
4926 main.log.error( self.name + ": transactionlMapGet did not" +
4927 " match expected output." )
4928 main.log.debug( self.name + " expected: " + pattern )
4929 main.log.debug( self.name + " actual: " + repr( output ) )
4930 return None
4931 except TypeError:
4932 main.log.exception( self.name + ": Object not as expected" )
4933 return None
Jon Hall2a5002c2015-08-21 16:49:11 -07004934 except Exception:
4935 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07004936 main.cleanAndExit()
Jon Hall2a5002c2015-08-21 16:49:11 -07004937
Jon Hall935db192016-04-19 00:22:04 -07004938 def transactionalMapPut( self, numKeys, value ):
Jon Hall2a5002c2015-08-21 16:49:11 -07004939 """
4940 CLI command to put a value into 'numKeys' number of keys in a
4941 consistent map using transactions. This a test function and can only
4942 put into keys named 'Key#' of the test map hard coded into the cli command
4943 Required arguments:
4944 numKeys - Number of keys to add the value to
4945 value - The string value to put into the keys
Jon Hall2a5002c2015-08-21 16:49:11 -07004946 returns:
4947 A dictionary whose keys are the name of the keys put into the map
4948 and the values of the keys are dictionaries whose key-values are
4949 'value': value put into map and optionaly
4950 'oldValue': Previous value in the key or
4951 None on Error
4952
4953 Example output
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00004954 { 'Key1': {'oldValue': 'oldTestValue', 'value': 'Testing'},
4955 'Key2': {'value': 'Testing'} }
Jon Hall2a5002c2015-08-21 16:49:11 -07004956 """
4957 try:
4958 numKeys = str( numKeys )
4959 value = str( value )
4960 cmdStr = "transactional-map-test-put "
Jon Hall2a5002c2015-08-21 16:49:11 -07004961 cmdStr += numKeys + " " + value
Jon Hall7a6ebfd2017-03-13 10:58:58 -07004962 output = self.distPrimitivesSend( cmdStr )
Jon Hall2a5002c2015-08-21 16:49:11 -07004963 newPattern = 'Created Key (?P<key>(\w)+) with value (?P<value>(.)+)\.'
4964 updatedPattern = "Put (?P<value>(.)+) into key (?P<key>(\w)+)\. The old value was (?P<oldValue>(.)+)\."
4965 results = {}
4966 for line in output.splitlines():
4967 new = re.search( newPattern, line )
4968 updated = re.search( updatedPattern, line )
4969 if new:
4970 results[ new.groupdict()[ 'key' ] ] = { 'value': new.groupdict()[ 'value' ] }
4971 elif updated:
4972 results[ updated.groupdict()[ 'key' ] ] = { 'value': updated.groupdict()[ 'value' ],
Jon Hallc6793552016-01-19 14:18:37 -08004973 'oldValue': updated.groupdict()[ 'oldValue' ] }
Jon Hall2a5002c2015-08-21 16:49:11 -07004974 else:
4975 main.log.error( self.name + ": transactionlMapGet did not" +
4976 " match expected output." )
Jon Hallc6793552016-01-19 14:18:37 -08004977 main.log.debug( "{} expected: {!r} or {!r}".format( self.name,
4978 newPattern,
4979 updatedPattern ) )
Jon Hall2a5002c2015-08-21 16:49:11 -07004980 main.log.debug( self.name + " actual: " + repr( output ) )
4981 return results
Jon Hall0e240372018-05-02 11:21:57 -07004982 except ( TypeError, AttributeError ):
Jon Hall2a5002c2015-08-21 16:49:11 -07004983 main.log.exception( self.name + ": Object not as expected" )
4984 return None
Jon Hall2a5002c2015-08-21 16:49:11 -07004985 except Exception:
4986 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07004987 main.cleanAndExit()
Jon Hallc6793552016-01-19 14:18:37 -08004988
acsmarsdaea66c2015-09-03 11:44:06 -07004989 def maps( self, jsonFormat=True ):
4990 """
4991 Description: Returns result of onos:maps
4992 Optional:
4993 * jsonFormat: enable json formatting of output
4994 """
4995 try:
4996 cmdStr = "maps"
4997 if jsonFormat:
4998 cmdStr += " -j"
4999 handle = self.sendline( cmdStr )
Jon Halla495f562016-05-16 18:03:26 -07005000 assert handle is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08005001 assert "Command not found:" not in handle, handle
acsmarsdaea66c2015-09-03 11:44:06 -07005002 return handle
Jon Hallc6793552016-01-19 14:18:37 -08005003 except AssertionError:
5004 main.log.exception( "" )
5005 return None
acsmarsdaea66c2015-09-03 11:44:06 -07005006 except TypeError:
5007 main.log.exception( self.name + ": Object not as expected" )
5008 return None
5009 except pexpect.EOF:
5010 main.log.error( self.name + ": EOF exception found" )
5011 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07005012 main.cleanAndExit()
acsmarsdaea66c2015-09-03 11:44:06 -07005013 except Exception:
5014 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07005015 main.cleanAndExit()
GlennRC050596c2015-11-18 17:06:41 -08005016
5017 def getSwController( self, uri, jsonFormat=True ):
5018 """
5019 Descrition: Gets the controller information from the device
5020 """
5021 try:
5022 cmd = "device-controllers "
5023 if jsonFormat:
5024 cmd += "-j "
5025 response = self.sendline( cmd + uri )
Jon Halla495f562016-05-16 18:03:26 -07005026 assert response is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08005027 assert "Command not found:" not in response, response
GlennRC050596c2015-11-18 17:06:41 -08005028 return response
Jon Hallc6793552016-01-19 14:18:37 -08005029 except AssertionError:
5030 main.log.exception( "" )
5031 return None
GlennRC050596c2015-11-18 17:06:41 -08005032 except TypeError:
5033 main.log.exception( self.name + ": Object not as expected" )
5034 return None
5035 except pexpect.EOF:
5036 main.log.error( self.name + ": EOF exception found" )
5037 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07005038 main.cleanAndExit()
GlennRC050596c2015-11-18 17:06:41 -08005039 except Exception:
5040 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07005041 main.cleanAndExit()
GlennRC050596c2015-11-18 17:06:41 -08005042
5043 def setSwController( self, uri, ip, proto="tcp", port="6653", jsonFormat=True ):
5044 """
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00005045 Descrition: sets the controller(s) for the specified device
GlennRC050596c2015-11-18 17:06:41 -08005046
5047 Parameters:
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00005048 Required: uri - String: The uri of the device(switch).
GlennRC050596c2015-11-18 17:06:41 -08005049 ip - String or List: The ip address of the controller.
5050 This parameter can be formed in a couple of different ways.
5051 VALID:
5052 10.0.0.1 - just the ip address
5053 tcp:10.0.0.1 - the protocol and the ip address
5054 tcp:10.0.0.1:6653 - the protocol and port can be specified,
5055 so that you can add controllers with different
5056 protocols and ports
5057 INVALID:
5058 10.0.0.1:6653 - this is not supported by ONOS
5059
5060 Optional: proto - The type of connection e.g. tcp, ssl. If a list of ips are given
5061 port - The port number.
5062 jsonFormat - If set ONOS will output in json NOTE: This is currently not supported
5063
5064 Returns: main.TRUE if ONOS returns without any errors, otherwise returns main.FALSE
5065 """
5066 try:
5067 cmd = "device-setcontrollers"
5068
5069 if jsonFormat:
5070 cmd += " -j"
5071 cmd += " " + uri
5072 if isinstance( ip, str ):
Jeremy Ronquillo82705492017-10-18 14:19:55 -07005073 ip = [ ip ]
GlennRC050596c2015-11-18 17:06:41 -08005074 for item in ip:
5075 if ":" in item:
5076 sitem = item.split( ":" )
Jeremy Ronquillo82705492017-10-18 14:19:55 -07005077 if len( sitem ) == 3:
GlennRC050596c2015-11-18 17:06:41 -08005078 cmd += " " + item
Jeremy Ronquillo82705492017-10-18 14:19:55 -07005079 elif "." in sitem[ 1 ]:
5080 cmd += " {}:{}".format( item, port )
GlennRC050596c2015-11-18 17:06:41 -08005081 else:
5082 main.log.error( "Malformed entry: " + item )
5083 raise TypeError
5084 else:
5085 cmd += " {}:{}:{}".format( proto, item, port )
GlennRC050596c2015-11-18 17:06:41 -08005086 response = self.sendline( cmd )
Jon Halla495f562016-05-16 18:03:26 -07005087 assert response is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08005088 assert "Command not found:" not in response, response
GlennRC050596c2015-11-18 17:06:41 -08005089 if "Error" in response:
5090 main.log.error( response )
5091 return main.FALSE
GlennRC050596c2015-11-18 17:06:41 -08005092 return main.TRUE
Jon Hallc6793552016-01-19 14:18:37 -08005093 except AssertionError:
5094 main.log.exception( "" )
Jon Hall2c8959e2016-12-16 12:17:34 -08005095 return main.FALSE
GlennRC050596c2015-11-18 17:06:41 -08005096 except TypeError:
5097 main.log.exception( self.name + ": Object not as expected" )
5098 return main.FALSE
5099 except pexpect.EOF:
5100 main.log.error( self.name + ": EOF exception found" )
5101 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07005102 main.cleanAndExit()
GlennRC050596c2015-11-18 17:06:41 -08005103 except Exception:
5104 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07005105 main.cleanAndExit()
GlennRC20fc6522015-12-23 23:26:57 -08005106
5107 def removeDevice( self, device ):
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00005108 '''
GlennRC20fc6522015-12-23 23:26:57 -08005109 Description:
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00005110 Remove a device from ONOS by passing the uri of the device(s).
GlennRC20fc6522015-12-23 23:26:57 -08005111 Parameters:
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00005112 device - (str or list) the id or uri of the device ex. "of:0000000000000001"
GlennRC20fc6522015-12-23 23:26:57 -08005113 Returns:
5114 Returns main.FALSE if an exception is thrown or an error is present
5115 in the response. Otherwise, returns main.TRUE.
5116 NOTE:
5117 If a host cannot be removed, then this function will return main.FALSE
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00005118 '''
GlennRC20fc6522015-12-23 23:26:57 -08005119 try:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07005120 if isinstance( device, str ):
You Wang823f5022016-08-18 15:24:41 -07005121 deviceStr = device
5122 device = []
5123 device.append( deviceStr )
GlennRC20fc6522015-12-23 23:26:57 -08005124
5125 for d in device:
5126 time.sleep( 1 )
5127 response = self.sendline( "device-remove {}".format( d ) )
Jon Halla495f562016-05-16 18:03:26 -07005128 assert response is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08005129 assert "Command not found:" not in response, response
GlennRC20fc6522015-12-23 23:26:57 -08005130 if "Error" in response:
5131 main.log.warn( "Error for device: {}\nResponse: {}".format( d, response ) )
5132 return main.FALSE
GlennRC20fc6522015-12-23 23:26:57 -08005133 return main.TRUE
Jon Hallc6793552016-01-19 14:18:37 -08005134 except AssertionError:
5135 main.log.exception( "" )
5136 return main.FALSE
GlennRC20fc6522015-12-23 23:26:57 -08005137 except TypeError:
5138 main.log.exception( self.name + ": Object not as expected" )
5139 return main.FALSE
5140 except pexpect.EOF:
5141 main.log.error( self.name + ": EOF exception found" )
5142 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07005143 main.cleanAndExit()
GlennRC20fc6522015-12-23 23:26:57 -08005144 except Exception:
5145 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07005146 main.cleanAndExit()
GlennRC20fc6522015-12-23 23:26:57 -08005147
5148 def removeHost( self, host ):
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00005149 '''
GlennRC20fc6522015-12-23 23:26:57 -08005150 Description:
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00005151 Remove a host from ONOS by passing the id of the host(s)
GlennRC20fc6522015-12-23 23:26:57 -08005152 Parameters:
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00005153 hostId - (str or list) the id or mac of the host ex. "00:00:00:00:00:01"
GlennRC20fc6522015-12-23 23:26:57 -08005154 Returns:
5155 Returns main.FALSE if an exception is thrown or an error is present
5156 in the response. Otherwise, returns main.TRUE.
5157 NOTE:
5158 If a host cannot be removed, then this function will return main.FALSE
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00005159 '''
GlennRC20fc6522015-12-23 23:26:57 -08005160 try:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07005161 if isinstance( host, str ):
GlennRC20fc6522015-12-23 23:26:57 -08005162 host = list( host )
5163
5164 for h in host:
5165 time.sleep( 1 )
5166 response = self.sendline( "host-remove {}".format( h ) )
Jon Halla495f562016-05-16 18:03:26 -07005167 assert response is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08005168 assert "Command not found:" not in response, response
GlennRC20fc6522015-12-23 23:26:57 -08005169 if "Error" in response:
5170 main.log.warn( "Error for host: {}\nResponse: {}".format( h, response ) )
5171 return main.FALSE
GlennRC20fc6522015-12-23 23:26:57 -08005172 return main.TRUE
Jon Hallc6793552016-01-19 14:18:37 -08005173 except AssertionError:
5174 main.log.exception( "" )
Jon Hall2c8959e2016-12-16 12:17:34 -08005175 return main.FALSE
GlennRC20fc6522015-12-23 23:26:57 -08005176 except TypeError:
5177 main.log.exception( self.name + ": Object not as expected" )
5178 return main.FALSE
5179 except pexpect.EOF:
5180 main.log.error( self.name + ": EOF exception found" )
5181 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07005182 main.cleanAndExit()
GlennRC20fc6522015-12-23 23:26:57 -08005183 except Exception:
5184 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07005185 main.cleanAndExit()
GlennRCed771242016-01-13 17:02:47 -08005186
YPZhangfebf7302016-05-24 16:45:56 -07005187 def link( self, begin, end, state, timeout=30, showResponse=True ):
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00005188 '''
GlennRCed771242016-01-13 17:02:47 -08005189 Description:
5190 Bring link down or up in the null-provider.
5191 params:
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00005192 begin - (string) One end of a device or switch.
5193 end - (string) the other end of the device or switch
GlennRCed771242016-01-13 17:02:47 -08005194 returns:
5195 main.TRUE if no exceptions were thrown and no Errors are
5196 present in the resoponse. Otherwise, returns main.FALSE
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00005197 '''
GlennRCed771242016-01-13 17:02:47 -08005198 try:
Jon Halle0f0b342017-04-18 11:43:47 -07005199 cmd = "null-link null:{} null:{} {}".format( begin, end, state )
YPZhangfebf7302016-05-24 16:45:56 -07005200 response = self.sendline( cmd, showResponse=showResponse, timeout=timeout )
Jon Halla495f562016-05-16 18:03:26 -07005201 assert response is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08005202 assert "Command not found:" not in response, response
GlennRCed771242016-01-13 17:02:47 -08005203 if "Error" in response or "Failure" in response:
5204 main.log.error( response )
5205 return main.FALSE
GlennRCed771242016-01-13 17:02:47 -08005206 return main.TRUE
Jon Hallc6793552016-01-19 14:18:37 -08005207 except AssertionError:
5208 main.log.exception( "" )
Jon Hall2c8959e2016-12-16 12:17:34 -08005209 return main.FALSE
GlennRCed771242016-01-13 17:02:47 -08005210 except TypeError:
5211 main.log.exception( self.name + ": Object not as expected" )
5212 return main.FALSE
5213 except pexpect.EOF:
5214 main.log.error( self.name + ": EOF exception found" )
5215 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07005216 main.cleanAndExit()
GlennRCed771242016-01-13 17:02:47 -08005217 except Exception:
5218 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07005219 main.cleanAndExit()
GlennRCed771242016-01-13 17:02:47 -08005220
Jon Hall2c8959e2016-12-16 12:17:34 -08005221 def portstate( self, dpid, port, state ):
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00005222 '''
Flavio Castro82ee2f62016-06-07 15:04:12 -07005223 Description:
5224 Changes the state of port in an OF switch by means of the
5225 PORTSTATUS OF messages.
5226 params:
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00005227 dpid - (string) Datapath ID of the device. Ex: 'of:0000000000000102'
5228 port - (string) target port in the device. Ex: '2'
5229 state - (string) target state (enable or disable)
Flavio Castro82ee2f62016-06-07 15:04:12 -07005230 returns:
5231 main.TRUE if no exceptions were thrown and no Errors are
5232 present in the resoponse. Otherwise, returns main.FALSE
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00005233 '''
Flavio Castro82ee2f62016-06-07 15:04:12 -07005234 try:
Jon Hall2c8959e2016-12-16 12:17:34 -08005235 state = state.lower()
5236 assert state == 'enable' or state == 'disable', "Unknown state"
Jon Halle0f0b342017-04-18 11:43:47 -07005237 cmd = "portstate {} {} {}".format( dpid, port, state )
Flavio Castro82ee2f62016-06-07 15:04:12 -07005238 response = self.sendline( cmd, showResponse=True )
5239 assert response is not None, "Error in sendline"
5240 assert "Command not found:" not in response, response
5241 if "Error" in response or "Failure" in response:
5242 main.log.error( response )
5243 return main.FALSE
5244 return main.TRUE
5245 except AssertionError:
5246 main.log.exception( "" )
Jon Hall2c8959e2016-12-16 12:17:34 -08005247 return main.FALSE
Flavio Castro82ee2f62016-06-07 15:04:12 -07005248 except TypeError:
5249 main.log.exception( self.name + ": Object not as expected" )
5250 return main.FALSE
5251 except pexpect.EOF:
5252 main.log.error( self.name + ": EOF exception found" )
5253 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07005254 main.cleanAndExit()
Flavio Castro82ee2f62016-06-07 15:04:12 -07005255 except Exception:
5256 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07005257 main.cleanAndExit()
Flavio Castro82ee2f62016-06-07 15:04:12 -07005258
5259 def logSet( self, level="INFO", app="org.onosproject" ):
5260 """
5261 Set the logging level to lvl for a specific app
5262 returns main.TRUE on success
5263 returns main.FALSE if Error occurred
5264 if noExit is True, TestON will not exit, but clean up
5265 Available level: DEBUG, TRACE, INFO, WARN, ERROR
5266 Level defaults to INFO
5267 """
5268 try:
Jon Halle0f0b342017-04-18 11:43:47 -07005269 self.handle.sendline( "log:set %s %s" % ( level, app ) )
Jon Hall6c9e2da2018-11-06 12:01:23 -08005270 self.handle.expect( self.karafPrompt )
Flavio Castro82ee2f62016-06-07 15:04:12 -07005271
5272 response = self.handle.before
5273 if re.search( "Error", response ):
5274 return main.FALSE
5275 return main.TRUE
5276 except pexpect.TIMEOUT:
5277 main.log.exception( self.name + ": TIMEOUT exception found" )
Devin Lim44075962017-08-11 10:56:37 -07005278 main.cleanAndExit()
Flavio Castro82ee2f62016-06-07 15:04:12 -07005279 except pexpect.EOF:
5280 main.log.error( self.name + ": EOF exception found" )
5281 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07005282 main.cleanAndExit()
Flavio Castro82ee2f62016-06-07 15:04:12 -07005283 except Exception:
5284 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07005285 main.cleanAndExit()
You Wangdb8cd0a2016-05-26 15:19:45 -07005286
5287 def getGraphDict( self, timeout=60, includeHost=False ):
5288 """
5289 Return a dictionary which describes the latest network topology data as a
5290 graph.
5291 An example of the dictionary:
5292 { vertex1: { 'edges': ..., 'name': ..., 'protocol': ... },
5293 vertex2: { 'edges': ..., 'name': ..., 'protocol': ... } }
5294 Each vertex should at least have an 'edges' attribute which describes the
5295 adjacency information. The value of 'edges' attribute is also represented by
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00005296 a dictionary, which maps each edge (identified by the neighbor vertex) to a
You Wangdb8cd0a2016-05-26 15:19:45 -07005297 list of attributes.
5298 An example of the edges dictionary:
5299 'edges': { vertex2: { 'port': ..., 'weight': ... },
5300 vertex3: { 'port': ..., 'weight': ... } }
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00005301 If includeHost == True, all hosts (and host-switch links) will be included
You Wangdb8cd0a2016-05-26 15:19:45 -07005302 in topology data.
5303 """
5304 graphDict = {}
5305 try:
5306 links = self.links()
5307 links = json.loads( links )
5308 devices = self.devices()
5309 devices = json.loads( devices )
5310 idToDevice = {}
5311 for device in devices:
5312 idToDevice[ device[ 'id' ] ] = device
5313 if includeHost:
5314 hosts = self.hosts()
5315 # FIXME: support 'includeHost' argument
5316 for link in links:
5317 nodeA = link[ 'src' ][ 'device' ]
5318 nodeB = link[ 'dst' ][ 'device' ]
5319 assert idToDevice[ nodeA ][ 'available' ] and idToDevice[ nodeB ][ 'available' ]
Jon Halle0f0b342017-04-18 11:43:47 -07005320 if nodeA not in graphDict.keys():
5321 graphDict[ nodeA ] = { 'edges': {},
Jeremy Ronquillo82705492017-10-18 14:19:55 -07005322 'dpid': idToDevice[ nodeA ][ 'id' ][ 3: ],
Jon Halle0f0b342017-04-18 11:43:47 -07005323 'type': idToDevice[ nodeA ][ 'type' ],
5324 'available': idToDevice[ nodeA ][ 'available' ],
5325 'role': idToDevice[ nodeA ][ 'role' ],
5326 'mfr': idToDevice[ nodeA ][ 'mfr' ],
5327 'hw': idToDevice[ nodeA ][ 'hw' ],
5328 'sw': idToDevice[ nodeA ][ 'sw' ],
5329 'serial': idToDevice[ nodeA ][ 'serial' ],
5330 'chassisId': idToDevice[ nodeA ][ 'chassisId' ],
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00005331 'annotations': idToDevice[ nodeA ][ 'annotations' ]}
You Wangdb8cd0a2016-05-26 15:19:45 -07005332 else:
5333 # Assert nodeB is not connected to any current links of nodeA
You Wang7d14d642019-01-23 15:10:08 -08005334 # assert nodeB not in graphDict[ nodeA ][ 'edges' ].keys()
5335 pass
Jon Halle0f0b342017-04-18 11:43:47 -07005336 graphDict[ nodeA ][ 'edges' ][ nodeB ] = { 'port': link[ 'src' ][ 'port' ],
5337 'type': link[ 'type' ],
5338 'state': link[ 'state' ] }
You Wangdb8cd0a2016-05-26 15:19:45 -07005339 return graphDict
5340 except ( TypeError, ValueError ):
5341 main.log.exception( self.name + ": Object not as expected" )
5342 return None
5343 except KeyError:
5344 main.log.exception( self.name + ": KeyError exception found" )
5345 return None
5346 except AssertionError:
5347 main.log.exception( self.name + ": AssertionError exception found" )
5348 return None
5349 except pexpect.EOF:
5350 main.log.error( self.name + ": EOF exception found" )
5351 main.log.error( self.name + ": " + self.handle.before )
5352 return None
5353 except Exception:
5354 main.log.exception( self.name + ": Uncaught exception!" )
5355 return None
YPZhangcbc2a062016-07-11 10:55:44 -07005356
5357 def getIntentPerfSummary( self ):
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00005358 '''
YPZhangcbc2a062016-07-11 10:55:44 -07005359 Send command to check intent-perf summary
5360 Returns: dictionary for intent-perf summary
5361 if something wrong, function will return None
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00005362 '''
YPZhangcbc2a062016-07-11 10:55:44 -07005363 cmd = "intent-perf -s"
5364 respDic = {}
5365 resp = self.sendline( cmd )
You Wangb5a55f72017-03-03 12:51:05 -08005366 assert resp is not None, "Error in sendline"
5367 assert "Command not found:" not in resp, resp
YPZhangcbc2a062016-07-11 10:55:44 -07005368 try:
5369 # Generate the dictionary to return
5370 for l in resp.split( "\n" ):
5371 # Delete any white space in line
5372 temp = re.sub( r'\s+', '', l )
5373 temp = temp.split( ":" )
Jeremy Ronquillo82705492017-10-18 14:19:55 -07005374 respDic[ temp[ 0 ] ] = temp[ 1 ]
YPZhangcbc2a062016-07-11 10:55:44 -07005375
Jeremy Ronquillo82705492017-10-18 14:19:55 -07005376 except ( TypeError, ValueError ):
YPZhangcbc2a062016-07-11 10:55:44 -07005377 main.log.exception( self.name + ": Object not as expected" )
5378 return None
5379 except KeyError:
5380 main.log.exception( self.name + ": KeyError exception found" )
5381 return None
5382 except AssertionError:
5383 main.log.exception( self.name + ": AssertionError exception found" )
5384 return None
5385 except pexpect.EOF:
5386 main.log.error( self.name + ": EOF exception found" )
5387 main.log.error( self.name + ": " + self.handle.before )
5388 return None
5389 except Exception:
5390 main.log.exception( self.name + ": Uncaught exception!" )
5391 return None
5392 return respDic
5393
Chiyu Chengec63bde2016-11-17 18:11:36 -08005394 def logSearch( self, mode='all', searchTerm='', startLine='', logNum=1 ):
chengchiyu08303a02016-09-08 17:40:26 -07005395 """
5396 Searches the latest ONOS log file for the given search term and
5397 return a list that contains all the lines that have the search term.
YPZhangcbc2a062016-07-11 10:55:44 -07005398
chengchiyu08303a02016-09-08 17:40:26 -07005399 Arguments:
Chiyu Chengec63bde2016-11-17 18:11:36 -08005400 searchTerm:
5401 The string to grep from the ONOS log.
5402 startLine:
5403 The term that decides which line is the start to search the searchTerm in
5404 the karaf log. For now, startTerm only works in 'first' mode.
5405 logNum:
5406 In some extreme cases, one karaf log is not big enough to contain all the
5407 information.Because of this, search mutiply logs is necessary to capture
5408 the right result. logNum is the number of karaf logs that we need to search
5409 the searchTerm.
chengchiyu08303a02016-09-08 17:40:26 -07005410 mode:
5411 all: return all the strings that contain the search term
5412 last: return the last string that contains the search term
5413 first: return the first string that contains the search term
Chiyu Chengec63bde2016-11-17 18:11:36 -08005414 num: return the number of times that the searchTerm appears in the log
5415 total: return how many lines in karaf log
chengchiyu08303a02016-09-08 17:40:26 -07005416 """
5417 try:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07005418 assert isinstance( searchTerm, str )
Jon Halle0f0b342017-04-18 11:43:47 -07005419 # Build the log paths string
Chiyu Chengec63bde2016-11-17 18:11:36 -08005420 logPath = '/opt/onos/log/karaf.log.'
5421 logPaths = '/opt/onos/log/karaf.log'
5422 for i in range( 1, logNum ):
5423 logPaths = logPath + str( i ) + " " + logPaths
5424 cmd = "cat " + logPaths
You Wang6d301d42017-04-21 10:49:33 -07005425 if startLine:
Jon Halla478b852017-12-04 15:00:15 -08005426 # 100000000 is just a extreme large number to make sure this function can
5427 # grep all the lines after startLine
You Wang6d301d42017-04-21 10:49:33 -07005428 cmd = cmd + " | grep -A 100000000 \'" + startLine + "\'"
Chiyu Chengec63bde2016-11-17 18:11:36 -08005429 if mode == 'all':
5430 cmd = cmd + " | grep \'" + searchTerm + "\'"
You Wang6d301d42017-04-21 10:49:33 -07005431 elif mode == 'last':
Chiyu Chengec63bde2016-11-17 18:11:36 -08005432 cmd = cmd + " | grep \'" + searchTerm + "\'" + " | tail -n 1"
You Wang6d301d42017-04-21 10:49:33 -07005433 elif mode == 'first':
5434 cmd = cmd + " | grep \'" + searchTerm + "\'" + " | head -n 1"
5435 elif mode == 'num':
You Wangd91a70f2019-01-03 15:28:10 -08005436 cmd = cmd + " | grep \'" + searchTerm + "\' | wc -l"
5437 num = self.lineCount( cmd )
Chiyu Chengb8c2c842016-10-05 12:40:49 -07005438 return num
You Wang6d301d42017-04-21 10:49:33 -07005439 elif mode == 'total':
Jon Halld5a94fb2018-11-13 14:32:23 -08005440 totalLines = self.lineCount( "cat /opt/onos/log/karaf.log | wc -l" )
Jeremy Ronquillo82705492017-10-18 14:19:55 -07005441 return int( totalLines )
You Wang6d301d42017-04-21 10:49:33 -07005442 else:
5443 main.log.error( self.name + " unsupported mode" )
5444 return main.ERROR
chengchiyu08303a02016-09-08 17:40:26 -07005445 before = self.sendline( cmd )
5446 before = before.splitlines()
5447 # make sure the returned list only contains the search term
Jeremy Ronquillo82705492017-10-18 14:19:55 -07005448 returnLines = [ line for line in before if searchTerm in line ]
chengchiyu08303a02016-09-08 17:40:26 -07005449 return returnLines
5450 except AssertionError:
5451 main.log.error( self.name + " searchTerm is not string type" )
5452 return None
5453 except pexpect.EOF:
5454 main.log.error( self.name + ": EOF exception found" )
5455 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07005456 main.cleanAndExit()
chengchiyu08303a02016-09-08 17:40:26 -07005457 except pexpect.TIMEOUT:
5458 main.log.error( self.name + ": TIMEOUT exception found" )
5459 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07005460 main.cleanAndExit()
chengchiyu08303a02016-09-08 17:40:26 -07005461 except Exception:
5462 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07005463 main.cleanAndExit()
Jon Hall2c8959e2016-12-16 12:17:34 -08005464
5465 def vplsShow( self, jsonFormat=True ):
5466 """
5467 Description: Returns result of onos:vpls show, which should list the
5468 configured VPLS networks and the assigned interfaces.
5469 Optional:
5470 * jsonFormat: enable json formatting of output
5471 Returns:
5472 The output of the command or None on error.
5473 """
5474 try:
5475 cmdStr = "vpls show"
5476 if jsonFormat:
5477 raise NotImplementedError
5478 cmdStr += " -j"
5479 handle = self.sendline( cmdStr )
5480 assert handle is not None, "Error in sendline"
5481 assert "Command not found:" not in handle, handle
5482 return handle
5483 except AssertionError:
5484 main.log.exception( "" )
5485 return None
5486 except TypeError:
5487 main.log.exception( self.name + ": Object not as expected" )
5488 return None
5489 except pexpect.EOF:
5490 main.log.error( self.name + ": EOF exception found" )
5491 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07005492 main.cleanAndExit()
Jon Hall2c8959e2016-12-16 12:17:34 -08005493 except NotImplementedError:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07005494 main.log.exception( self.name + ": Json output not supported" )
Jon Hall2c8959e2016-12-16 12:17:34 -08005495 return None
5496 except Exception:
5497 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07005498 main.cleanAndExit()
Jon Hall2c8959e2016-12-16 12:17:34 -08005499
5500 def parseVplsShow( self ):
5501 """
5502 Parse the cli output of 'vpls show' into json output. This is required
5503 as there is currently no json output available.
5504 """
5505 try:
5506 output = []
5507 raw = self.vplsShow( jsonFormat=False )
5508 namePat = "VPLS name: (?P<name>\w+)"
5509 interfacesPat = "Associated interfaces: \[(?P<interfaces>.*)\]"
5510 encapPat = "Encapsulation: (?P<encap>\w+)"
5511 pattern = "\s+".join( [ namePat, interfacesPat, encapPat ] )
5512 mIter = re.finditer( pattern, raw )
5513 for match in mIter:
5514 item = {}
5515 item[ 'name' ] = match.group( 'name' )
Jeremy Ronquillo82705492017-10-18 14:19:55 -07005516 ifaces = match.group( 'interfaces' ).split( ', ' )
Jon Hall2c8959e2016-12-16 12:17:34 -08005517 if ifaces == [ "" ]:
5518 ifaces = []
5519 item[ 'interfaces' ] = ifaces
5520 encap = match.group( 'encap' )
5521 if encap != 'NONE':
5522 item[ 'encapsulation' ] = encap.lower()
5523 output.append( item )
5524 return output
5525 except Exception:
5526 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07005527 main.cleanAndExit()
Jon Hall2c8959e2016-12-16 12:17:34 -08005528
5529 def vplsList( self, jsonFormat=True ):
5530 """
5531 Description: Returns result of onos:vpls list, which should list the
5532 configured VPLS networks.
5533 Optional:
5534 * jsonFormat: enable json formatting of output
5535 """
5536 try:
5537 cmdStr = "vpls list"
5538 if jsonFormat:
5539 raise NotImplementedError
5540 cmdStr += " -j"
5541 handle = self.sendline( cmdStr )
5542 assert handle is not None, "Error in sendline"
5543 assert "Command not found:" not in handle, handle
5544 return handle
5545 except AssertionError:
5546 main.log.exception( "" )
5547 return None
5548 except TypeError:
5549 main.log.exception( self.name + ": Object not as expected" )
5550 return None
5551 except pexpect.EOF:
5552 main.log.error( self.name + ": EOF exception found" )
5553 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07005554 main.cleanAndExit()
Jon Hall2c8959e2016-12-16 12:17:34 -08005555 except NotImplementedError:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07005556 main.log.exception( self.name + ": Json output not supported" )
Jon Hall2c8959e2016-12-16 12:17:34 -08005557 return None
5558 except Exception:
5559 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07005560 main.cleanAndExit()
Jon Hall2c8959e2016-12-16 12:17:34 -08005561
5562 def vplsCreate( self, network ):
5563 """
5564 CLI command to create a new VPLS network.
5565 Required arguments:
5566 network - String name of the network to create.
5567 returns:
5568 main.TRUE on success and main.FALSE on failure
5569 """
5570 try:
5571 network = str( network )
5572 cmdStr = "vpls create "
5573 cmdStr += network
5574 output = self.sendline( cmdStr )
5575 assert output is not None, "Error in sendline"
5576 assert "Command not found:" not in output, output
5577 assert "Error executing command" not in output, output
5578 assert "VPLS already exists:" not in output, output
5579 return main.TRUE
5580 except AssertionError:
5581 main.log.exception( "" )
5582 return main.FALSE
5583 except TypeError:
5584 main.log.exception( self.name + ": Object not as expected" )
5585 return main.FALSE
5586 except pexpect.EOF:
5587 main.log.error( self.name + ": EOF exception found" )
5588 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07005589 main.cleanAndExit()
Jon Hall2c8959e2016-12-16 12:17:34 -08005590 except Exception:
5591 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07005592 main.cleanAndExit()
Jon Hall2c8959e2016-12-16 12:17:34 -08005593
5594 def vplsDelete( self, network ):
5595 """
5596 CLI command to delete a VPLS network.
5597 Required arguments:
5598 network - Name of the network to delete.
5599 returns:
5600 main.TRUE on success and main.FALSE on failure
5601 """
5602 try:
5603 network = str( network )
5604 cmdStr = "vpls delete "
5605 cmdStr += network
5606 output = self.sendline( cmdStr )
5607 assert output is not None, "Error in sendline"
5608 assert "Command not found:" not in output, output
5609 assert "Error executing command" not in output, output
5610 assert " not found" not in output, output
Jon Hallcf97cf12017-06-06 09:37:51 -07005611 assert "still updating" not in output, output
Jon Hall2c8959e2016-12-16 12:17:34 -08005612 return main.TRUE
5613 except AssertionError:
5614 main.log.exception( "" )
5615 return main.FALSE
5616 except TypeError:
5617 main.log.exception( self.name + ": Object not as expected" )
5618 return main.FALSE
5619 except pexpect.EOF:
5620 main.log.error( self.name + ": EOF exception found" )
5621 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07005622 main.cleanAndExit()
Jon Hall2c8959e2016-12-16 12:17:34 -08005623 except Exception:
5624 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07005625 main.cleanAndExit()
Jon Hall2c8959e2016-12-16 12:17:34 -08005626
5627 def vplsAddIface( self, network, iface ):
5628 """
5629 CLI command to add an interface to a VPLS network.
5630 Required arguments:
5631 network - Name of the network to add the interface to.
5632 iface - The ONOS name for an interface.
5633 returns:
5634 main.TRUE on success and main.FALSE on failure
5635 """
5636 try:
5637 network = str( network )
5638 iface = str( iface )
5639 cmdStr = "vpls add-if "
5640 cmdStr += network + " " + iface
5641 output = self.sendline( cmdStr )
5642 assert output is not None, "Error in sendline"
5643 assert "Command not found:" not in output, output
5644 assert "Error executing command" not in output, output
5645 assert "already associated to network" not in output, output
5646 assert "Interface cannot be added." not in output, output
Jon Hallcf97cf12017-06-06 09:37:51 -07005647 assert "still updating" not in output, output
Jon Hall2c8959e2016-12-16 12:17:34 -08005648 return main.TRUE
5649 except AssertionError:
5650 main.log.exception( "" )
5651 return main.FALSE
5652 except TypeError:
5653 main.log.exception( self.name + ": Object not as expected" )
5654 return main.FALSE
5655 except pexpect.EOF:
5656 main.log.error( self.name + ": EOF exception found" )
5657 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07005658 main.cleanAndExit()
Jon Hall2c8959e2016-12-16 12:17:34 -08005659 except Exception:
5660 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07005661 main.cleanAndExit()
Jon Hall2c8959e2016-12-16 12:17:34 -08005662
5663 def vplsRemIface( self, network, iface ):
5664 """
5665 CLI command to remove an interface from a VPLS network.
5666 Required arguments:
5667 network - Name of the network to remove the interface from.
5668 iface - Name of the interface to remove.
5669 returns:
5670 main.TRUE on success and main.FALSE on failure
5671 """
5672 try:
5673 iface = str( iface )
5674 cmdStr = "vpls rem-if "
5675 cmdStr += network + " " + iface
5676 output = self.sendline( cmdStr )
5677 assert output is not None, "Error in sendline"
5678 assert "Command not found:" not in output, output
5679 assert "Error executing command" not in output, output
5680 assert "is not configured" not in output, output
Jon Hallcf97cf12017-06-06 09:37:51 -07005681 assert "still updating" not in output, output
Jon Hall2c8959e2016-12-16 12:17:34 -08005682 return main.TRUE
5683 except AssertionError:
5684 main.log.exception( "" )
5685 return main.FALSE
5686 except TypeError:
5687 main.log.exception( self.name + ": Object not as expected" )
5688 return main.FALSE
5689 except pexpect.EOF:
5690 main.log.error( self.name + ": EOF exception found" )
5691 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07005692 main.cleanAndExit()
Jon Hall2c8959e2016-12-16 12:17:34 -08005693 except Exception:
5694 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07005695 main.cleanAndExit()
Jon Hall2c8959e2016-12-16 12:17:34 -08005696
5697 def vplsClean( self ):
5698 """
5699 Description: Clears the VPLS app configuration.
5700 Returns: main.TRUE on success and main.FALSE on failure
5701 """
5702 try:
5703 cmdStr = "vpls clean"
5704 handle = self.sendline( cmdStr )
5705 assert handle is not None, "Error in sendline"
5706 assert "Command not found:" not in handle, handle
Jon Hallcf97cf12017-06-06 09:37:51 -07005707 assert "still updating" not in handle, handle
Jon Hall2c8959e2016-12-16 12:17:34 -08005708 return handle
5709 except AssertionError:
5710 main.log.exception( "" )
5711 return main.FALSE
5712 except TypeError:
5713 main.log.exception( self.name + ": Object not as expected" )
5714 return main.FALSE
5715 except pexpect.EOF:
5716 main.log.error( self.name + ": EOF exception found" )
5717 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07005718 main.cleanAndExit()
Jon Hall2c8959e2016-12-16 12:17:34 -08005719 except Exception:
5720 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07005721 main.cleanAndExit()
Jon Hall2c8959e2016-12-16 12:17:34 -08005722
5723 def vplsSetEncap( self, network, encapType ):
5724 """
5725 CLI command to add an interface to a VPLS network.
5726 Required arguments:
5727 network - Name of the network to create.
5728 encapType - Type of encapsulation.
5729 returns:
5730 main.TRUE on success and main.FALSE on failure
5731 """
5732 try:
5733 network = str( network )
5734 encapType = str( encapType ).upper()
5735 assert encapType in [ "MPLS", "VLAN", "NONE" ], "Incorrect type"
5736 cmdStr = "vpls set-encap "
5737 cmdStr += network + " " + encapType
5738 output = self.sendline( cmdStr )
5739 assert output is not None, "Error in sendline"
5740 assert "Command not found:" not in output, output
5741 assert "Error executing command" not in output, output
5742 assert "already associated to network" not in output, output
5743 assert "Encapsulation type " not in output, output
Jon Hallcf97cf12017-06-06 09:37:51 -07005744 assert "still updating" not in output, output
Jon Hall2c8959e2016-12-16 12:17:34 -08005745 return main.TRUE
5746 except AssertionError:
5747 main.log.exception( "" )
5748 return main.FALSE
5749 except TypeError:
5750 main.log.exception( self.name + ": Object not as expected" )
5751 return main.FALSE
5752 except pexpect.EOF:
5753 main.log.error( self.name + ": EOF exception found" )
5754 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07005755 main.cleanAndExit()
Jon Hall2c8959e2016-12-16 12:17:34 -08005756 except Exception:
5757 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07005758 main.cleanAndExit()
Jon Hall2c8959e2016-12-16 12:17:34 -08005759
5760 def interfaces( self, jsonFormat=True ):
5761 """
5762 Description: Returns result of interfaces command.
5763 Optional:
5764 * jsonFormat: enable json formatting of output
5765 Returns:
5766 The output of the command or None on error.
5767 """
5768 try:
5769 cmdStr = "interfaces"
5770 if jsonFormat:
Jon Halle0f0b342017-04-18 11:43:47 -07005771 raise NotImplementedError
Jon Hall2c8959e2016-12-16 12:17:34 -08005772 cmdStr += " -j"
5773 handle = self.sendline( cmdStr )
5774 assert handle is not None, "Error in sendline"
5775 assert "Command not found:" not in handle, handle
5776 return handle
5777 except AssertionError:
5778 main.log.exception( "" )
5779 return None
5780 except TypeError:
5781 main.log.exception( self.name + ": Object not as expected" )
5782 return None
5783 except pexpect.EOF:
5784 main.log.error( self.name + ": EOF exception found" )
5785 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07005786 main.cleanAndExit()
Jon Hall2c8959e2016-12-16 12:17:34 -08005787 except NotImplementedError:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07005788 main.log.exception( self.name + ": Json output not supported" )
Jon Hall2c8959e2016-12-16 12:17:34 -08005789 return None
5790 except Exception:
5791 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07005792 main.cleanAndExit()
Chiyu Chengec63bde2016-11-17 18:11:36 -08005793
5794 def getTimeStampFromLog( self, mode, searchTerm, splitTerm_before, splitTerm_after, startLine='', logNum=1 ):
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00005795 '''
Chiyu Chengec63bde2016-11-17 18:11:36 -08005796 Get the timestamp of searchTerm from karaf log.
5797
5798 Arguments:
5799 splitTerm_before and splitTerm_after:
5800
5801 The terms that split the string that contains the timeStamp of
5802 searchTerm. For example, if that string is "xxxxxxxcreationTime =
5803 1419510501xxxxxx", then the splitTerm_before is "CreationTime = "
5804 and the splitTerm_after is "x"
5805
5806 others:
Jon Halle0f0b342017-04-18 11:43:47 -07005807 Please look at the "logsearch" Function in onosclidriver.py
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00005808 '''
Chiyu Chengec63bde2016-11-17 18:11:36 -08005809 if logNum < 0:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07005810 main.log.error( "Get wrong log number ")
Chiyu Chengec63bde2016-11-17 18:11:36 -08005811 return main.ERROR
5812 lines = self.logSearch( mode=mode, searchTerm=searchTerm, startLine=startLine, logNum=logNum )
Jeremy Ronquillo82705492017-10-18 14:19:55 -07005813 if len( lines ) == 0:
Chiyu Chengec63bde2016-11-17 18:11:36 -08005814 main.log.warn( "Captured timestamp string is empty" )
5815 return main.ERROR
5816 lines = lines[ 0 ]
5817 try:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07005818 assert isinstance( lines, str )
Chiyu Chengec63bde2016-11-17 18:11:36 -08005819 # get the target value
5820 line = lines.split( splitTerm_before )
5821 key = line[ 1 ].split( splitTerm_after )
5822 return int( key[ 0 ] )
5823 except IndexError:
5824 main.log.warn( "Index Error!" )
5825 return main.ERROR
5826 except AssertionError:
5827 main.log.warn( "Search Term Not Found " )
5828 return main.ERROR
Jon Halle0f0b342017-04-18 11:43:47 -07005829
5830 def workQueueAdd( self, queueName, value ):
5831 """
5832 CLI command to add a string to the specified Work Queue.
5833 This function uses the distributed primitives test app, which
5834 gives some cli access to distributed primitives for testing
5835 purposes only.
5836
5837 Required arguments:
5838 queueName - The name of the queue to add to
5839 value - The value to add to the queue
5840 returns:
5841 main.TRUE on success, main.FALSE on failure and
5842 main.ERROR on error.
5843 """
5844 try:
5845 queueName = str( queueName )
5846 value = str( value )
5847 prefix = "work-queue-test"
5848 operation = "add"
5849 cmdStr = " ".join( [ prefix, queueName, operation, value ] )
5850 output = self.distPrimitivesSend( cmdStr )
5851 if "Invalid operation name" in output:
5852 main.log.warn( output )
5853 return main.ERROR
5854 elif "Done" in output:
5855 return main.TRUE
5856 except TypeError:
5857 main.log.exception( self.name + ": Object not as expected" )
5858 return main.ERROR
5859 except Exception:
5860 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07005861 main.cleanAndExit()
Jon Halle0f0b342017-04-18 11:43:47 -07005862
5863 def workQueueAddMultiple( self, queueName, value1, value2 ):
5864 """
5865 CLI command to add two strings to the specified Work Queue.
5866 This function uses the distributed primitives test app, which
5867 gives some cli access to distributed primitives for testing
5868 purposes only.
5869
5870 Required arguments:
5871 queueName - The name of the queue to add to
5872 value1 - The first value to add to the queue
5873 value2 - The second value to add to the queue
5874 returns:
5875 main.TRUE on success, main.FALSE on failure and
5876 main.ERROR on error.
5877 """
5878 try:
5879 queueName = str( queueName )
5880 value1 = str( value1 )
5881 value2 = str( value2 )
5882 prefix = "work-queue-test"
5883 operation = "addMultiple"
5884 cmdStr = " ".join( [ prefix, queueName, operation, value1, value2 ] )
5885 output = self.distPrimitivesSend( cmdStr )
5886 if "Invalid operation name" in output:
5887 main.log.warn( output )
5888 return main.ERROR
5889 elif "Done" in output:
5890 return main.TRUE
5891 except TypeError:
5892 main.log.exception( self.name + ": Object not as expected" )
5893 return main.ERROR
5894 except Exception:
5895 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07005896 main.cleanAndExit()
Jon Halle0f0b342017-04-18 11:43:47 -07005897
5898 def workQueueTakeAndComplete( self, queueName, number=1 ):
5899 """
5900 CLI command to take a value from the specified Work Queue and compelte it.
5901 This function uses the distributed primitives test app, which
5902 gives some cli access to distributed primitives for testing
5903 purposes only.
5904
5905 Required arguments:
5906 queueName - The name of the queue to add to
5907 number - The number of items to take and complete
5908 returns:
5909 main.TRUE on success, main.FALSE on failure and
5910 main.ERROR on error.
5911 """
5912 try:
5913 queueName = str( queueName )
5914 number = str( int( number ) )
5915 prefix = "work-queue-test"
5916 operation = "takeAndComplete"
5917 cmdStr = " ".join( [ prefix, queueName, operation, number ] )
5918 output = self.distPrimitivesSend( cmdStr )
5919 if "Invalid operation name" in output:
5920 main.log.warn( output )
5921 return main.ERROR
5922 elif "Done" in output:
5923 return main.TRUE
5924 except TypeError:
5925 main.log.exception( self.name + ": Object not as expected" )
5926 return main.ERROR
5927 except Exception:
5928 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07005929 main.cleanAndExit()
Jon Halle0f0b342017-04-18 11:43:47 -07005930
5931 def workQueueDestroy( self, queueName ):
5932 """
5933 CLI command to destroy the specified Work Queue.
5934 This function uses the distributed primitives test app, which
5935 gives some cli access to distributed primitives for testing
5936 purposes only.
5937
5938 Required arguments:
5939 queueName - The name of the queue to add to
5940 returns:
5941 main.TRUE on success, main.FALSE on failure and
5942 main.ERROR on error.
5943 """
5944 try:
5945 queueName = str( queueName )
5946 prefix = "work-queue-test"
5947 operation = "destroy"
5948 cmdStr = " ".join( [ prefix, queueName, operation ] )
5949 output = self.distPrimitivesSend( cmdStr )
5950 if "Invalid operation name" in output:
5951 main.log.warn( output )
5952 return main.ERROR
5953 return main.TRUE
5954 except TypeError:
5955 main.log.exception( self.name + ": Object not as expected" )
5956 return main.ERROR
5957 except Exception:
5958 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07005959 main.cleanAndExit()
Jon Halle0f0b342017-04-18 11:43:47 -07005960
5961 def workQueueTotalPending( self, queueName ):
5962 """
5963 CLI command to get the Total Pending items of the specified Work Queue.
5964 This function uses the distributed primitives test app, which
5965 gives some cli access to distributed primitives for testing
5966 purposes only.
5967
5968 Required arguments:
5969 queueName - The name of the queue to add to
5970 returns:
5971 The number of Pending items in the specified work queue or
5972 None on error
5973 """
5974 try:
5975 queueName = str( queueName )
5976 prefix = "work-queue-test"
5977 operation = "totalPending"
5978 cmdStr = " ".join( [ prefix, queueName, operation ] )
5979 output = self.distPrimitivesSend( cmdStr )
Jon Hall22e94ce2019-01-15 14:52:17 -08005980 main.log.debug( self.name + ": work queue unparsed: " + output )
5981 output = output.split( "\r\n" )[ -1 ]
5982 main.log.debug( self.name + ": work queue parsed: " + output )
Jon Halle0f0b342017-04-18 11:43:47 -07005983 pattern = r'\d+'
5984 if "Invalid operation name" in output:
5985 main.log.warn( output )
5986 return None
5987 else:
5988 match = re.search( pattern, output )
Jeremy Ronquillo82705492017-10-18 14:19:55 -07005989 return match.group( 0 )
Jon Halle0f0b342017-04-18 11:43:47 -07005990 except ( AttributeError, TypeError ):
5991 main.log.exception( self.name + ": Object not as expected; " + str( output ) )
5992 return None
5993 except Exception:
5994 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07005995 main.cleanAndExit()
Jon Halle0f0b342017-04-18 11:43:47 -07005996
5997 def workQueueTotalCompleted( self, queueName ):
5998 """
5999 CLI command to get the Total Completed items of the specified Work Queue.
6000 This function uses the distributed primitives test app, which
6001 gives some cli access to distributed primitives for testing
6002 purposes only.
6003
6004 Required arguments:
6005 queueName - The name of the queue to add to
6006 returns:
6007 The number of complete items in the specified work queue or
6008 None on error
6009 """
6010 try:
6011 queueName = str( queueName )
6012 prefix = "work-queue-test"
6013 operation = "totalCompleted"
6014 cmdStr = " ".join( [ prefix, queueName, operation ] )
6015 output = self.distPrimitivesSend( cmdStr )
Jon Hall22e94ce2019-01-15 14:52:17 -08006016 main.log.debug( self.name + ": work queue unparsed: " + output )
6017 output = output.split( "\r\n" )[ -1 ]
6018 main.log.debug( self.name + ": work queue parsed: " + output )
Jon Halle0f0b342017-04-18 11:43:47 -07006019 pattern = r'\d+'
6020 if "Invalid operation name" in output:
6021 main.log.warn( output )
6022 return None
6023 else:
6024 match = re.search( pattern, output )
Jeremy Ronquillo82705492017-10-18 14:19:55 -07006025 return match.group( 0 )
Jon Halle0f0b342017-04-18 11:43:47 -07006026 except ( AttributeError, TypeError ):
6027 main.log.exception( self.name + ": Object not as expected; " + str( output ) )
6028 return None
6029 except Exception:
6030 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07006031 main.cleanAndExit()
Jon Halle0f0b342017-04-18 11:43:47 -07006032
6033 def workQueueTotalInProgress( self, queueName ):
6034 """
6035 CLI command to get the Total In Progress items of the specified Work Queue.
6036 This function uses the distributed primitives test app, which
6037 gives some cli access to distributed primitives for testing
6038 purposes only.
6039
6040 Required arguments:
6041 queueName - The name of the queue to add to
6042 returns:
6043 The number of In Progress items in the specified work queue or
6044 None on error
6045 """
6046 try:
6047 queueName = str( queueName )
6048 prefix = "work-queue-test"
6049 operation = "totalInProgress"
6050 cmdStr = " ".join( [ prefix, queueName, operation ] )
6051 output = self.distPrimitivesSend( cmdStr )
Jon Hall22e94ce2019-01-15 14:52:17 -08006052 main.log.debug( self.name + ": work queue unparsed: " + output )
6053 output = output.split( "\r\n" )[ -1 ]
6054 main.log.debug( self.name + ": work queue parsed: " + output )
Jon Halle0f0b342017-04-18 11:43:47 -07006055 pattern = r'\d+'
6056 if "Invalid operation name" in output:
6057 main.log.warn( output )
6058 return None
6059 else:
6060 match = re.search( pattern, output )
Jeremy Ronquillo82705492017-10-18 14:19:55 -07006061 return match.group( 0 )
Jon Halle0f0b342017-04-18 11:43:47 -07006062 except ( AttributeError, TypeError ):
6063 main.log.exception( self.name + ": Object not as expected; " + str( output ) )
6064 return None
6065 except Exception:
6066 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07006067 main.cleanAndExit()
Jeremy Ronquillo818bc7c2017-08-09 17:14:53 +00006068
6069 def events( self, args='-a' ):
6070 """
6071 Description: Returns events -a command output
6072 Optional:
6073 add other arguments
6074 """
6075 try:
6076 cmdStr = "events"
6077 if args:
6078 cmdStr += " " + args
6079 handle = self.sendline( cmdStr )
6080 assert handle is not None, "Error in sendline"
6081 assert "Command not found:" not in handle, handle
6082 return handle
6083 except AssertionError:
6084 main.log.exception( "" )
6085 return None
6086 except TypeError:
6087 main.log.exception( self.name + ": Object not as expected" )
6088 return None
6089 except pexpect.EOF:
6090 main.log.error( self.name + ": EOF exception found" )
6091 main.log.error( self.name + ": " + self.handle.before )
6092 main.cleanAndExit()
6093 except Exception:
6094 main.log.exception( self.name + ": Uncaught exception!" )
6095 main.cleanAndExit()
6096
6097 def getMaster( self, deviceID ):
6098 """
6099 Description: Obtains current master using "roles" command for a specific deviceID
6100 """
6101 try:
6102 return str( self.getRole( deviceID )[ 'master' ] )
6103 except AssertionError:
6104 main.log.exception( "" )
6105 return None
6106 except TypeError:
6107 main.log.exception( self.name + ": Object not as expected" )
6108 return None
6109 except pexpect.EOF:
6110 main.log.error( self.name + ": EOF exception found" )
6111 main.log.error( self.name + ": " + self.handle.before )
6112 main.cleanAndExit()
6113 except Exception:
6114 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lime6fe3c42017-10-18 16:28:40 -07006115 main.cleanAndExit()
Jon Halla478b852017-12-04 15:00:15 -08006116
6117 def issu( self ):
6118 """
6119 Short summary of In-Service Software Upgrade status
6120
6121 Returns the output of the cli command or None on Error
6122 """
6123 try:
6124 cmdStr = "issu"
6125 handle = self.sendline( cmdStr )
6126 assert handle is not None, "Error in sendline"
6127 assert "Command not found:" not in handle, handle
6128 assert "Unsupported command:" not in handle, handle
6129 return handle
6130 except AssertionError:
6131 main.log.exception( "" )
6132 return None
6133 except TypeError:
6134 main.log.exception( self.name + ": Object not as expected" )
6135 return None
6136 except pexpect.EOF:
6137 main.log.error( self.name + ": EOF exception found" )
6138 main.log.error( self.name + ": " + self.handle.before )
6139 main.cleanAndExit()
6140 except Exception:
6141 main.log.exception( self.name + ": Uncaught exception!" )
6142 main.cleanAndExit()
6143
6144 def issuInit( self ):
6145 """
6146 Initiates an In-Service Software Upgrade
6147
6148 Returns main.TRUE on success, main.ERROR on error, else main.FALSE
6149 """
6150 try:
6151 cmdStr = "issu init"
6152 handle = self.sendline( cmdStr )
6153 assert handle is not None, "Error in sendline"
6154 assert "Command not found:" not in handle, handle
6155 assert "Unsupported command:" not in handle, handle
6156 if "Initialized" in handle:
6157 return main.TRUE
6158 else:
6159 return main.FALSE
6160 except AssertionError:
6161 main.log.exception( "" )
6162 return main.ERROR
6163 except TypeError:
6164 main.log.exception( self.name + ": Object not as expected" )
6165 return main.ERROR
6166 except pexpect.EOF:
6167 main.log.error( self.name + ": EOF exception found" )
6168 main.log.error( self.name + ": " + self.handle.before )
6169 main.cleanAndExit()
6170 except Exception:
6171 main.log.exception( self.name + ": Uncaught exception!" )
6172 main.cleanAndExit()
6173
6174 def issuUpgrade( self ):
6175 """
6176 Transitions stores to upgraded nodes
6177
6178 Returns main.TRUE on success, main.ERROR on error, else main.FALSE
6179 """
6180 try:
6181 cmdStr = "issu upgrade"
6182 handle = self.sendline( cmdStr )
6183 assert handle is not None, "Error in sendline"
6184 assert "Command not found:" not in handle, handle
6185 assert "Unsupported command:" not in handle, handle
6186 if "Upgraded" in handle:
6187 return main.TRUE
6188 else:
6189 return main.FALSE
6190 except AssertionError:
6191 main.log.exception( "" )
6192 return main.ERROR
6193 except TypeError:
6194 main.log.exception( self.name + ": Object not as expected" )
6195 return main.ERROR
6196 except pexpect.EOF:
6197 main.log.error( self.name + ": EOF exception found" )
6198 main.log.error( self.name + ": " + self.handle.before )
6199 main.cleanAndExit()
6200 except Exception:
6201 main.log.exception( self.name + ": Uncaught exception!" )
6202 main.cleanAndExit()
6203
6204 def issuCommit( self ):
6205 """
6206 Finalizes an In-Service Software Upgrade
6207
6208 Returns main.TRUE on success, main.ERROR on error, else main.FALSE
6209 """
6210 try:
6211 cmdStr = "issu commit"
6212 handle = self.sendline( cmdStr )
6213 assert handle is not None, "Error in sendline"
6214 assert "Command not found:" not in handle, handle
6215 assert "Unsupported command:" not in handle, handle
6216 # TODO: Check the version returned by this command
6217 if "Committed version" in handle:
6218 return main.TRUE
6219 else:
6220 return main.FALSE
6221 except AssertionError:
6222 main.log.exception( "" )
6223 return main.ERROR
6224 except TypeError:
6225 main.log.exception( self.name + ": Object not as expected" )
6226 return main.ERROR
6227 except pexpect.EOF:
6228 main.log.error( self.name + ": EOF exception found" )
6229 main.log.error( self.name + ": " + self.handle.before )
6230 main.cleanAndExit()
6231 except Exception:
6232 main.log.exception( self.name + ": Uncaught exception!" )
6233 main.cleanAndExit()
6234
6235 def issuRollback( self ):
6236 """
6237 Rolls back an In-Service Software Upgrade
6238
6239 Returns main.TRUE on success, main.ERROR on error, else main.FALSE
6240 """
6241 try:
6242 cmdStr = "issu rollback"
6243 handle = self.sendline( cmdStr )
6244 assert handle is not None, "Error in sendline"
6245 assert "Command not found:" not in handle, handle
6246 assert "Unsupported command:" not in handle, handle
6247 # TODO: Check the version returned by this command
6248 if "Rolled back to version" in handle:
6249 return main.TRUE
6250 else:
6251 return main.FALSE
6252 except AssertionError:
6253 main.log.exception( "" )
6254 return main.ERROR
6255 except TypeError:
6256 main.log.exception( self.name + ": Object not as expected" )
6257 return main.ERROR
6258 except pexpect.EOF:
6259 main.log.error( self.name + ": EOF exception found" )
6260 main.log.error( self.name + ": " + self.handle.before )
6261 main.cleanAndExit()
6262 except Exception:
6263 main.log.exception( self.name + ": Uncaught exception!" )
6264 main.cleanAndExit()
6265
6266 def issuReset( self ):
6267 """
6268 Resets the In-Service Software Upgrade status after a rollback
6269
6270 Returns main.TRUE on success, main.ERROR on error, else main.FALSE
6271 """
6272 try:
6273 cmdStr = "issu reset"
6274 handle = self.sendline( cmdStr )
6275 assert handle is not None, "Error in sendline"
6276 assert "Command not found:" not in handle, handle
6277 assert "Unsupported command:" not in handle, handle
6278 # TODO: Check the version returned by this command
6279 if "Reset version" in handle:
6280 return main.TRUE
6281 else:
6282 return main.FALSE
6283 except AssertionError:
6284 main.log.exception( "" )
6285 return main.ERROR
6286 except TypeError:
6287 main.log.exception( self.name + ": Object not as expected" )
6288 return main.ERROR
6289 except pexpect.EOF:
6290 main.log.error( self.name + ": EOF exception found" )
6291 main.log.error( self.name + ": " + self.handle.before )
6292 main.cleanAndExit()
6293 except Exception:
6294 main.log.exception( self.name + ": Uncaught exception!" )
6295 main.cleanAndExit()
6296
6297 def issuStatus( self ):
6298 """
6299 Status of an In-Service Software Upgrade
6300
6301 Returns the output of the cli command or None on Error
6302 """
6303 try:
6304 cmdStr = "issu status"
6305 handle = self.sendline( cmdStr )
6306 assert handle is not None, "Error in sendline"
6307 assert "Command not found:" not in handle, handle
6308 assert "Unsupported command:" not in handle, handle
6309 return handle
6310 except AssertionError:
6311 main.log.exception( "" )
6312 return None
6313 except TypeError:
6314 main.log.exception( self.name + ": Object not as expected" )
6315 return None
6316 except pexpect.EOF:
6317 main.log.error( self.name + ": EOF exception found" )
6318 main.log.error( self.name + ": " + self.handle.before )
6319 main.cleanAndExit()
6320 except Exception:
6321 main.log.exception( self.name + ": Uncaught exception!" )
6322 main.cleanAndExit()
6323
6324 def issuVersion( self ):
6325 """
6326 Get the version of an In-Service Software Upgrade
6327
6328 Returns the output of the cli command or None on Error
6329 """
6330 try:
6331 cmdStr = "issu version"
6332 handle = self.sendline( cmdStr )
6333 assert handle is not None, "Error in sendline"
6334 assert "Command not found:" not in handle, handle
6335 assert "Unsupported command:" not in handle, handle
6336 return handle
6337 except AssertionError:
6338 main.log.exception( "" )
6339 return None
6340 except TypeError:
6341 main.log.exception( self.name + ": Object not as expected" )
6342 return None
6343 except pexpect.EOF:
6344 main.log.error( self.name + ": EOF exception found" )
6345 main.log.error( self.name + ": " + self.handle.before )
6346 main.cleanAndExit()
6347 except Exception:
6348 main.log.exception( self.name + ": Uncaught exception!" )
6349 main.cleanAndExit()
You Wange24d6272018-03-27 21:18:50 -07006350
6351 def mcastJoin( self, sIP, groupIP, sPort, dPorts ):
6352 """
6353 Create a multicast route by calling 'mcast-join' command
6354 sIP: source IP of the multicast route
6355 groupIP: group IP of the multicast route
6356 sPort: source port (e.g. of:0000000000000001/3 ) of the multicast route
6357 dPorts: a list of destination ports of the multicast route
6358 Returns main.TRUE if mcast route is added; Otherwise main.FALSE
6359 """
6360 try:
6361 cmdStr = "mcast-join"
6362 cmdStr += " " + str( sIP )
6363 cmdStr += " " + str( groupIP )
6364 cmdStr += " " + str( sPort )
6365 assert isinstance( dPorts, list )
6366 for dPort in dPorts:
6367 cmdStr += " " + str( dPort )
6368 handle = self.sendline( cmdStr )
6369 assert handle is not None, "Error in sendline"
6370 assert "Command not found:" not in handle, handle
6371 assert "Unsupported command:" not in handle, handle
6372 assert "Error executing command" not in handle, handle
6373 if "Added the mcast route" in handle:
6374 return main.TRUE
6375 else:
6376 return main.FALSE
6377 except AssertionError:
6378 main.log.exception( "" )
6379 return None
6380 except TypeError:
6381 main.log.exception( self.name + ": Object not as expected" )
6382 return None
6383 except pexpect.EOF:
6384 main.log.error( self.name + ": EOF exception found" )
6385 main.log.error( self.name + ": " + self.handle.before )
6386 main.cleanAndExit()
6387 except Exception:
6388 main.log.exception( self.name + ": Uncaught exception!" )
6389 main.cleanAndExit()
6390
6391 def mcastDelete( self, sIP, groupIP, dPorts ):
6392 """
6393 Delete a multicast route by calling 'mcast-delete' command
6394 sIP: source IP of the multicast route
6395 groupIP: group IP of the multicast route
6396 dPorts: a list of destination ports of the multicast route
6397 Returns main.TRUE if mcast route is deleted; Otherwise main.FALSE
6398 """
6399 try:
6400 cmdStr = "mcast-delete"
6401 cmdStr += " " + str( sIP )
6402 cmdStr += " " + str( groupIP )
6403 assert isinstance( dPorts, list )
6404 for dPort in dPorts:
6405 cmdStr += " " + str( dPort )
6406 handle = self.sendline( cmdStr )
6407 assert handle is not None, "Error in sendline"
6408 assert "Command not found:" not in handle, handle
6409 assert "Unsupported command:" not in handle, handle
6410 assert "Error executing command" not in handle, handle
6411 if "Updated the mcast route" in handle:
6412 return main.TRUE
6413 else:
6414 return main.FALSE
6415 except AssertionError:
6416 main.log.exception( "" )
6417 return None
6418 except TypeError:
6419 main.log.exception( self.name + ": Object not as expected" )
6420 return None
6421 except pexpect.EOF:
6422 main.log.error( self.name + ": EOF exception found" )
6423 main.log.error( self.name + ": " + self.handle.before )
6424 main.cleanAndExit()
6425 except Exception:
6426 main.log.exception( self.name + ": Uncaught exception!" )
6427 main.cleanAndExit()
6428
6429 def mcastHostJoin( self, sAddr, gAddr, srcs, sinks ):
6430 """
6431 Create a multicast route by calling 'mcast-host-join' command
6432 sAddr: we can provide * for ASM or a specific address for SSM
6433 gAddr: specifies multicast group address
You Wang547893e2018-05-08 13:34:59 -07006434 srcs: a list of HostId of the sources e.g. ["00:AA:00:00:00:01/None"]
You Wange24d6272018-03-27 21:18:50 -07006435 sinks: a list of HostId of the sinks e.g. ["00:AA:00:00:01:05/40"]
6436 Returns main.TRUE if mcast route is added; Otherwise main.FALSE
6437 """
6438 try:
6439 cmdStr = "mcast-host-join"
6440 cmdStr += " -sAddr " + str( sAddr )
6441 cmdStr += " -gAddr " + str( gAddr )
6442 assert isinstance( srcs, list )
6443 for src in srcs:
6444 cmdStr += " -srcs " + str( src )
6445 assert isinstance( sinks, list )
6446 for sink in sinks:
6447 cmdStr += " -sinks " + str( sink )
6448 handle = self.sendline( cmdStr )
6449 assert handle is not None, "Error in sendline"
6450 assert "Command not found:" not in handle, handle
6451 assert "Unsupported command:" not in handle, handle
6452 assert "Error executing command" not in handle, handle
6453 if "Added the mcast route" in handle:
6454 return main.TRUE
6455 else:
6456 return main.FALSE
6457 except AssertionError:
6458 main.log.exception( "" )
6459 return None
6460 except TypeError:
6461 main.log.exception( self.name + ": Object not as expected" )
6462 return None
6463 except pexpect.EOF:
6464 main.log.error( self.name + ": EOF exception found" )
6465 main.log.error( self.name + ": " + self.handle.before )
6466 main.cleanAndExit()
6467 except Exception:
6468 main.log.exception( self.name + ": Uncaught exception!" )
6469 main.cleanAndExit()
6470
6471 def mcastHostDelete( self, sAddr, gAddr, host=None ):
6472 """
6473 Delete multicast sink(s) by calling 'mcast-host-delete' command
6474 sAddr: we can provide * for ASM or a specific address for SSM
6475 gAddr: specifies multicast group address
You Wangc02d8352018-04-17 16:42:10 -07006476 host: HostId of the sink e.g. "00:AA:00:00:01:05/40",
You Wange24d6272018-03-27 21:18:50 -07006477 will delete the route if not specified
6478 Returns main.TRUE if the mcast sink is deleted; Otherwise main.FALSE
6479 """
6480 try:
6481 cmdStr = "mcast-host-delete"
6482 cmdStr += " -sAddr " + str( sAddr )
6483 cmdStr += " -gAddr " + str( gAddr )
6484 if host:
6485 cmdStr += " -h " + str( host )
6486 handle = self.sendline( cmdStr )
6487 assert handle is not None, "Error in sendline"
6488 assert "Command not found:" not in handle, handle
6489 assert "Unsupported command:" not in handle, handle
6490 assert "Error executing command" not in handle, handle
6491 if "Updated the mcast route" in handle:
6492 return main.TRUE
6493 elif "Deleted the mcast route" in handle:
6494 return main.TRUE
6495 else:
6496 return main.FALSE
6497 except AssertionError:
6498 main.log.exception( "" )
6499 return None
6500 except TypeError:
6501 main.log.exception( self.name + ": Object not as expected" )
6502 return None
6503 except pexpect.EOF:
6504 main.log.error( self.name + ": EOF exception found" )
6505 main.log.error( self.name + ": " + self.handle.before )
6506 main.cleanAndExit()
6507 except Exception:
6508 main.log.exception( self.name + ": Uncaught exception!" )
6509 main.cleanAndExit()
6510
You Wang547893e2018-05-08 13:34:59 -07006511 def mcastSinkDelete( self, sAddr, gAddr, sink=None ):
6512 """
6513 Delete multicast sink(s) by calling 'mcast-sink-delete' command
6514 sAddr: we can provide * for ASM or a specific address for SSM
6515 gAddr: specifies multicast group address
6516 host: HostId of the sink e.g. "00:AA:00:00:01:05/40",
6517 will delete the route if not specified
6518 Returns main.TRUE if the mcast sink is deleted; Otherwise main.FALSE
6519 """
6520 try:
6521 cmdStr = "mcast-sink-delete"
6522 cmdStr += " -sAddr " + str( sAddr )
6523 cmdStr += " -gAddr " + str( gAddr )
6524 if sink:
6525 cmdStr += " -s " + str( sink )
6526 handle = self.sendline( cmdStr )
6527 assert handle is not None, "Error in sendline"
6528 assert "Command not found:" not in handle, handle
6529 assert "Unsupported command:" not in handle, handle
6530 assert "Error executing command" not in handle, handle
6531 if "Updated the mcast route" in handle:
6532 return main.TRUE
6533 elif "Deleted the mcast route" in handle:
6534 return main.TRUE
6535 else:
6536 return main.FALSE
6537 except AssertionError:
6538 main.log.exception( "" )
6539 return None
6540 except TypeError:
6541 main.log.exception( self.name + ": Object not as expected" )
6542 return None
6543 except pexpect.EOF:
6544 main.log.error( self.name + ": EOF exception found" )
6545 main.log.error( self.name + ": " + self.handle.before )
6546 main.cleanAndExit()
6547 except Exception:
6548 main.log.exception( self.name + ": Uncaught exception!" )
6549 main.cleanAndExit()
6550
You Wange24d6272018-03-27 21:18:50 -07006551 def mcastSourceDelete( self, sAddr, gAddr, srcs=None ):
6552 """
6553 Delete multicast src(s) by calling 'mcast-source-delete' command
6554 sAddr: we can provide * for ASM or a specific address for SSM
6555 gAddr: specifies multicast group address
You Wang547893e2018-05-08 13:34:59 -07006556 srcs: a list of host IDs of the sources e.g. ["00:AA:00:00:01:05/40"],
You Wange24d6272018-03-27 21:18:50 -07006557 will delete the route if not specified
6558 Returns main.TRUE if mcast sink is deleted; Otherwise main.FALSE
6559 """
6560 try:
6561 cmdStr = "mcast-source-delete"
6562 cmdStr += " -sAddr " + str( sAddr )
6563 cmdStr += " -gAddr " + str( gAddr )
6564 if srcs:
6565 assert isinstance( srcs, list )
6566 for src in srcs:
6567 cmdStr += " -src " + str( src )
6568 handle = self.sendline( cmdStr )
6569 assert handle is not None, "Error in sendline"
6570 assert "Command not found:" not in handle, handle
6571 assert "Unsupported command:" not in handle, handle
6572 assert "Error executing command" not in handle, handle
6573 if "Updated the mcast route" in handle:
6574 return main.TRUE
6575 elif "Deleted the mcast route" in handle:
6576 return main.TRUE
6577 else:
6578 return main.FALSE
6579 except AssertionError:
6580 main.log.exception( "" )
6581 return None
6582 except TypeError:
6583 main.log.exception( self.name + ": Object not as expected" )
6584 return None
6585 except pexpect.EOF:
6586 main.log.error( self.name + ": EOF exception found" )
6587 main.log.error( self.name + ": " + self.handle.before )
6588 main.cleanAndExit()
6589 except Exception:
6590 main.log.exception( self.name + ": Uncaught exception!" )
6591 main.cleanAndExit()
You Wang5da39c82018-04-26 22:55:08 -07006592
6593 def netcfg( self, jsonFormat=True, args="" ):
6594 """
6595 Run netcfg cli command with given args
6596 """
6597 try:
6598 cmdStr = "netcfg"
6599 if jsonFormat:
6600 cmdStr = cmdStr + " -j"
6601 if args:
6602 cmdStr = cmdStr + " " + str( args )
6603 handle = self.sendline( cmdStr )
6604 assert handle is not None, "Error in sendline"
6605 assert "Command not found:" not in handle, handle
6606 assert "Unsupported command:" not in handle, handle
6607 assert "Error executing command" not in handle, handle
6608 return handle
6609 except AssertionError:
6610 main.log.exception( "" )
6611 return None
6612 except TypeError:
6613 main.log.exception( self.name + ": Object not as expected" )
6614 return None
6615 except pexpect.EOF:
6616 main.log.error( self.name + ": EOF exception found" )
6617 main.log.error( self.name + ": " + self.handle.before )
6618 main.cleanAndExit()
6619 except Exception:
6620 main.log.exception( self.name + ": Uncaught exception!" )
6621 main.cleanAndExit()
6622
You Wang0fa76e72018-05-18 11:33:25 -07006623 def composeT3Command( self, sAddr, dAddr, ipv6=False, verbose=True, simple=False ):
You Wang5da39c82018-04-26 22:55:08 -07006624 """
You Wang54b1d672018-06-11 16:44:13 -07006625 Compose and return a list of t3-troubleshoot cli commands for given source and destination addresses
You Wang5da39c82018-04-26 22:55:08 -07006626 Options:
6627 sAddr: IP address of the source host
6628 dAddr: IP address of the destination host
You Wang0fa76e72018-05-18 11:33:25 -07006629 ipv6: True if hosts are IPv6
6630 verbose: return verbose t3 output if True
6631 simple: compose command for t3-troubleshoot-simple if True
You Wang5da39c82018-04-26 22:55:08 -07006632 """
6633 try:
6634 # Collect information of both hosts from onos
6635 hosts = self.hosts()
6636 hosts = json.loads( hosts )
6637 sHost = None
6638 dHost = None
6639 for host in hosts:
6640 if sAddr in host[ "ipAddresses" ]:
6641 sHost = host
6642 elif dAddr in host[ "ipAddresses" ]:
6643 dHost = host
6644 if sHost and dHost:
6645 break
6646 assert sHost, "Not able to find host with IP {}".format( sAddr )
You Wang54b1d672018-06-11 16:44:13 -07006647 cmdList = []
You Wang5d9527b2018-05-29 17:08:54 -07006648 if simple:
6649 assert dHost, "Not able to find host with IP {}".format( dAddr )
You Wang54b1d672018-06-11 16:44:13 -07006650 cmdStr = "t3-troubleshoot-simple"
6651 if verbose:
6652 cmdStr += " -vv"
6653 if ipv6:
6654 cmdStr += " -et ipv6"
You Wang0fa76e72018-05-18 11:33:25 -07006655 cmdStr += " {}/{} {}/{}".format( sHost[ "mac" ], sHost[ "vlan" ], dHost[ "mac" ], dHost[ "vlan" ] )
You Wang54b1d672018-06-11 16:44:13 -07006656 cmdList.append( cmdStr )
You Wang0fa76e72018-05-18 11:33:25 -07006657 else:
You Wang54b1d672018-06-11 16:44:13 -07006658 for location in sHost[ "locations" ]:
6659 cmdStr = "t3-troubleshoot"
6660 if verbose:
6661 cmdStr += " -vv"
6662 if ipv6:
6663 cmdStr += " -et ipv6"
6664 cmdStr += " -s " + str( sAddr )
6665 cmdStr += " -sp " + str( location[ "elementId" ] ) + "/" + str( location[ "port" ] )
6666 cmdStr += " -sm " + str( sHost[ "mac" ] )
6667 if sHost[ "vlan" ] != "None":
6668 cmdStr += " -vid " + sHost[ "vlan" ]
6669 cmdStr += " -d " + str( dAddr )
6670 netcfg = self.netcfg( args="devices {}".format( location[ "elementId" ] ) )
6671 netcfg = json.loads( netcfg )
6672 assert netcfg, "Failed to get netcfg"
6673 cmdStr += " -dm " + str( netcfg[ "segmentrouting" ][ "routerMac" ] )
6674 cmdList.append( cmdStr )
6675 return cmdList
You Wang5da39c82018-04-26 22:55:08 -07006676 except AssertionError:
6677 main.log.exception( "" )
6678 return None
6679 except ( KeyError, TypeError ):
6680 main.log.exception( self.name + ": Object not as expected" )
6681 return None
6682 except Exception:
6683 main.log.exception( self.name + ": Uncaught exception!" )
6684 main.cleanAndExit()
6685
6686 def t3( self, sAddr, dAddr, ipv6=False ):
6687 """
You Wang54b1d672018-06-11 16:44:13 -07006688 Run t3-troubleshoot cli commands for all posible routes given source and destination addresses
You Wang5da39c82018-04-26 22:55:08 -07006689 Options:
6690 sAddr: IP address of the source host
6691 dAddr: IP address of the destination host
6692 """
6693 try:
You Wang54b1d672018-06-11 16:44:13 -07006694 cmdList = self.composeT3Command( sAddr, dAddr, ipv6 )
6695 assert cmdList is not None, "composeT3Command returned None"
6696 t3Output = ""
6697 for cmdStr in cmdList:
6698 handle = self.sendline( cmdStr )
6699 assert handle is not None, "Error in sendline"
6700 assert "Command not found:" not in handle, handle
6701 assert "Unsupported command:" not in handle, handle
6702 assert "Error executing command" not in handle, handle
6703 assert "Tracing packet" in handle
6704 t3Output += handle
6705 return t3Output
You Wang5da39c82018-04-26 22:55:08 -07006706 except AssertionError:
6707 main.log.exception( "" )
6708 return None
6709 except pexpect.EOF:
6710 main.log.error( self.name + ": EOF exception found" )
6711 main.log.error( self.name + ": " + self.handle.before )
6712 main.cleanAndExit()
6713 except Exception:
6714 main.log.exception( self.name + ": Uncaught exception!" )
6715 main.cleanAndExit()